// Copyright 2019 The Chromium OS Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. package main import ( "errors" "fmt" "io" "path" "strings" "testing" ) func TestCheckClangSyntaxByNestedCall(t *testing.T) { withTestContext(t, func(ctx *testContext) { ctx.cmdMock = func(cmd *command, stdin io.Reader, stdout io.Writer, stderr io.Writer) error { if ctx.cmdCount == 1 { if err := verifyPath(cmd, "usr/bin/clang"); err != nil { return err } if err := verifyArgOrder(cmd, mainCc, "-fsyntax-only", `-stdlib=libstdc\+\+`); err != nil { return err } } return nil } cmd := ctx.must(callCompiler(ctx, ctx.cfg, ctx.newCommand(gccX86_64, "-clang-syntax", mainCc))) if ctx.cmdCount != 2 { t.Errorf("expected 2 calls. Got: %d", ctx.cmdCount) } if err := verifyPath(cmd, gccX86_64+".real"); err != nil { t.Error(err) } if err := verifyArgCount(cmd, 0, "-clang-syntax"); err != nil { t.Error(err) } }) } func TestForwardStdOutAndStderrFromClangSyntaxCheck(t *testing.T) { withTestContext(t, func(ctx *testContext) { ctx.cmdMock = func(cmd *command, stdin io.Reader, stdout io.Writer, stderr io.Writer) error { if ctx.cmdCount == 1 { fmt.Fprint(stdout, "somemessage") fmt.Fprint(stderr, "someerror") } return nil } ctx.must(callCompiler(ctx, ctx.cfg, ctx.newCommand(gccX86_64, "-clang-syntax", mainCc))) if ctx.stdoutString() != "somemessage" { t.Errorf("stdout was not forwarded. Got: %s", ctx.stdoutString()) } if ctx.stderrString() != "someerror" { t.Errorf("stderr was not forwarded. Got: %s", ctx.stderrString()) } }) } func TestForwardStdinToClangSyntaxCheck(t *testing.T) { withTestContext(t, func(ctx *testContext) { ctx.cmdMock = func(cmd *command, stdin io.Reader, stdout io.Writer, stderr io.Writer) error { // Note: This is called for the clang syntax call as well as for // the gcc call, and we assert that stdin is cloned and forwarded // to both. stdinStr := ctx.readAllString(stdin) if stdinStr != "someinput" { return fmt.Errorf("unexpected stdin. Got: %s", stdinStr) } return nil } io.WriteString(&ctx.stdinBuffer, "someinput") ctx.must(callCompiler(ctx, ctx.cfg, ctx.newCommand(gccX86_64, "-clang-syntax", "-", mainCc))) }) } func TestForwardExitCodeFromClangSyntaxCheck(t *testing.T) { withTestContext(t, func(ctx *testContext) { ctx.cmdMock = func(cmd *command, stdin io.Reader, stdout io.Writer, stderr io.Writer) error { if ctx.cmdCount == 1 { return newExitCodeError(23) } return nil } exitCode := callCompiler(ctx, ctx.cfg, ctx.newCommand(gccX86_64, "-clang-syntax", mainCc)) if exitCode != 23 { t.Errorf("unexpected exit code. Got: %d", exitCode) } }) } func TestReportGeneralErrorsFromClangSyntaxCheck(t *testing.T) { withTestContext(t, func(ctx *testContext) { ctx.cmdMock = func(cmd *command, stdin io.Reader, stdout io.Writer, stderr io.Writer) error { if ctx.cmdCount == 1 { return errors.New("someerror") } return nil } stderr := ctx.mustFail(callCompiler(ctx, ctx.cfg, ctx.newCommand(gccX86_64, "-clang-syntax", mainCc))) if err := verifyInternalError(stderr); err != nil { t.Fatal(err) } if !strings.Contains(stderr, "someerror") { t.Errorf("unexpected error. Got: %s", stderr) } }) } func TestIgnoreClangSyntaxCheckWhenCallingClang(t *testing.T) { withTestContext(t, func(ctx *testContext) { ctx.cmdMock = func(cmd *command, stdin io.Reader, stdout io.Writer, stderr io.Writer) error { if ctx.cmdCount > 1 { return fmt.Errorf("Unexpected call %#v", cmd) } return nil } cmd := ctx.must(callCompiler(ctx, ctx.cfg, ctx.newCommand(clangX86_64, "-clang-syntax", mainCc))) if err := verifyArgCount(cmd, 0, "-clang-syntax"); err != nil { t.Error(err) } }) } func TestUseGomaForClangSyntaxCheck(t *testing.T) { withTestContext(t, func(ctx *testContext) { gomaPath := path.Join(ctx.tempDir, "gomacc") // Create a file so the gomacc path is valid. ctx.writeFile(gomaPath, "") ctx.env = []string{"GOMACC_PATH=" + gomaPath} ctx.cmdMock = func(cmd *command, stdin io.Reader, stdout io.Writer, stderr io.Writer) error { if ctx.cmdCount == 1 { if err := verifyPath(cmd, gomaPath); err != nil { return err } if err := verifyArgOrder(cmd, "usr/bin/clang", mainCc); err != nil { return err } } return nil } cmd := ctx.must(callCompiler(ctx, ctx.cfg, ctx.newCommand(gccX86_64, "-clang-syntax", mainCc))) if ctx.cmdCount != 2 { t.Errorf("expected 2 calls. Got: %d", ctx.cmdCount) } if err := verifyPath(cmd, gomaPath); err != nil { t.Error(err) } }) } func TestPartiallyOmitCCacheForClangSyntaxCheck(t *testing.T) { withTestContext(t, func(ctx *testContext) { ctx.cfg.useCCache = true ctx.cmdMock = func(cmd *command, stdin io.Reader, stdout io.Writer, stderr io.Writer) error { if ctx.cmdCount == 1 { if err := verifyPath(cmd, "usr/bin/clang"); err != nil { return err } } return nil } cmd := ctx.must(callCompiler(ctx, ctx.cfg, ctx.newCommand(gccX86_64, "-clang-syntax", mainCc))) if ctx.cmdCount != 2 { t.Errorf("expected 2 calls. Got: %d", ctx.cmdCount) } if err := verifyPath(cmd, "/usr/bin/ccache"); err != nil { t.Error(err) } }) }