From 900dbc92800d8fc927905db29cb302461054cf97 Mon Sep 17 00:00:00 2001 From: Tobias Bosch Date: Mon, 24 Jun 2019 09:31:39 -0700 Subject: Introduce infrastructure for calling and testing nested commands, error messages and exit codes. Also: - implements the -Xclang-path= flag as use case of calling a nested command. - adds tests for forwarding errors, comparing against the old wrapper, and exit codes. - captures the source locations of errors in error messages. - compares exit codes of new wrapper and old wrapper. BUG=chromium:773875 TEST=unit test Change-Id: I919e58091d093d68939809f676f799a68ec7a34e Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/toolchain-utils/+/1676833 Reviewed-by: George Burgess Tested-by: Tobias Bosch --- compiler_wrapper/compiler_wrapper_test.go | 121 +++++++++++++++++++++++------- 1 file changed, 92 insertions(+), 29 deletions(-) (limited to 'compiler_wrapper/compiler_wrapper_test.go') diff --git a/compiler_wrapper/compiler_wrapper_test.go b/compiler_wrapper/compiler_wrapper_test.go index 6ab25e4e..5abf7ce9 100644 --- a/compiler_wrapper/compiler_wrapper_test.go +++ b/compiler_wrapper/compiler_wrapper_test.go @@ -1,13 +1,20 @@ package main import ( + "bytes" + "errors" + "fmt" + "io" + "path/filepath" + "strings" + "syscall" "testing" ) func TestAddCommonFlags(t *testing.T) { withTestContext(t, func(ctx *testContext) { ctx.cfg.commonFlags = []string{"-someflag"} - cmd := ctx.must(calcCompilerCommandAndCompareToOld(ctx, ctx.cfg, + cmd := ctx.must(callCompiler(ctx, ctx.cfg, ctx.newCommand(gccX86_64, mainCc))) if err := verifyArgOrder(cmd, "-someflag", mainCc); err != nil { t.Error(err) @@ -18,7 +25,7 @@ func TestAddCommonFlags(t *testing.T) { func TestAddGccConfigFlags(t *testing.T) { withTestContext(t, func(ctx *testContext) { ctx.cfg.gccFlags = []string{"-someflag"} - cmd := ctx.must(calcCompilerCommandAndCompareToOld(ctx, ctx.cfg, + cmd := ctx.must(callCompiler(ctx, ctx.cfg, ctx.newCommand(gccX86_64, mainCc))) if err := verifyArgOrder(cmd, "-someflag", mainCc); err != nil { t.Error(err) @@ -29,7 +36,7 @@ func TestAddGccConfigFlags(t *testing.T) { func TestAddClangConfigFlags(t *testing.T) { withTestContext(t, func(ctx *testContext) { ctx.cfg.clangFlags = []string{"-someflag"} - cmd := ctx.must(calcCompilerCommandAndCompareToOld(ctx, ctx.cfg, + cmd := ctx.must(callCompiler(ctx, ctx.cfg, ctx.newCommand(clangX86_64, mainCc))) if err := verifyArgOrder(cmd, "-someflag", mainCc); err != nil { t.Error(err) @@ -37,42 +44,98 @@ func TestAddClangConfigFlags(t *testing.T) { }) } -func TestShouldForwardToOldWrapperBecauseOfArgs(t *testing.T) { +func TestLogGeneralExecError(t *testing.T) { withTestContext(t, func(ctx *testContext) { - testdata := []struct { - arg string - shouldForward bool - }{ - {"abc", false}, - {"-Xclang-path=abc", true}, - {"-clang-syntax", true}, - {"-clang-syntaxabc", false}, + testOldWrapperPaths := []string{ + "", + filepath.Join(ctx.tempDir, "fakewrapper"), } - for _, tt := range testdata { - if actual := shouldForwardToOldWrapper(ctx, ctx.newCommand(clangX86_64, tt.arg)); actual != tt.shouldForward { - t.Fatalf("Forward to old wrapper incorrect for arg %s. Expected %t but was %t.", tt.arg, tt.shouldForward, actual) + for _, testOldWrapperPath := range testOldWrapperPaths { + ctx.cfg.oldWrapperPath = testOldWrapperPath + // Note: No need to write the old wrapper as we don't execute + // it due to the general error from the new error. + ctx.cmdMock = func(cmd *command, stdout io.Writer, stderr io.Writer) error { + return errors.New("someerror") + } + stderr := ctx.mustFail(callCompiler(ctx, ctx.cfg, ctx.newCommand(gccX86_64, mainCc))) + if err := verifyInternalError(stderr); err != nil { + t.Fatal(err) + } + if !strings.Contains(stderr, gccX86_64) { + t.Errorf("could not find compiler path on stderr. Got: %s", stderr) + } + if !strings.Contains(stderr, "someerror") { + t.Errorf("could not find original error on stderr. Got: %s", stderr) } } }) } -func TestShouldForwardToOldWrapperBecauseOfEnv(t *testing.T) { +func TestLogMissingCCacheExecError(t *testing.T) { withTestContext(t, func(ctx *testContext) { - testdata := []struct { - env string - shouldForward bool - }{ - {"PATH=abc", false}, - {"WITH_TIDY=abc", true}, - {"FORCE_DISABLE_WERROR=abc", true}, - {"GETRUSAGE=abc", true}, - {"BISECT_STAGE=abc", true}, + ctx.cfg.useCCache = true + + testOldWrapperPaths := []string{ + "", + filepath.Join(ctx.tempDir, "fakewrapper"), } - for _, tt := range testdata { - ctx.env = []string{tt.env} - if actual := shouldForwardToOldWrapper(ctx, ctx.newCommand(clangX86_64)); actual != tt.shouldForward { - t.Fatalf("Forward to old wrapper incorrect for env %s. Expected %t but was %t.", tt.env, tt.shouldForward, actual) + for _, testOldWrapperPath := range testOldWrapperPaths { + ctx.cfg.oldWrapperPath = testOldWrapperPath + // Note: No need to write the old wrapper as we don't execute + // it due to the general error from the new error. + ctx.cmdMock = func(cmd *command, stdout io.Writer, stderr io.Writer) error { + return syscall.ENOENT + } + ctx.stderrBuffer.Reset() + stderr := ctx.mustFail(callCompiler(ctx, ctx.cfg, ctx.newCommand(gccX86_64, mainCc))) + if err := verifyNonInternalError(stderr, "ccache not found under .*. Please install it"); err != nil { + t.Fatal(err) } } }) } + +func TestLogExitCodeErrorWhenComparingToOldWrapper(t *testing.T) { + withTestContext(t, func(ctx *testContext) { + ctx.cfg.mockOldWrapperCmds = false + ctx.cfg.oldWrapperPath = filepath.Join(ctx.tempDir, "fakewrapper") + + ctx.cmdMock = func(cmd *command, stdout io.Writer, stderr io.Writer) error { + writeMockWrapper(ctx, &mockWrapperConfig{ + Cmds: []*mockWrapperCmd{ + { + Path: cmd.path, + Args: cmd.args, + ExitCode: 2, + }, + }, + }) + fmt.Fprint(stderr, "someerror") + return newExitCodeError(2) + } + + exitCode := callCompiler(ctx, ctx.cfg, ctx.newCommand(gccX86_64, mainCc)) + if exitCode != 2 { + t.Fatalf("Expected exit code 2. Got: %d", exitCode) + } + if err := verifyNonInternalError(ctx.stderrString(), "someerror"); err != nil { + t.Fatal(err) + } + }) +} + +func TestPrintUserCompilerError(t *testing.T) { + buffer := bytes.Buffer{} + printCompilerError(&buffer, newUserErrorf("abcd")) + if buffer.String() != "abcd\n" { + t.Errorf("Unexpected string. Got: %s", buffer.String()) + } +} + +func TestPrintOtherCompilerError(t *testing.T) { + buffer := bytes.Buffer{} + printCompilerError(&buffer, errors.New("abcd")) + if buffer.String() != "Internal error. Please report to chromeos-toolchain@google.com.\nabcd\n" { + t.Errorf("Unexpected string. Got: %s", buffer.String()) + } +} -- cgit v1.2.3