diff options
author | Tobias Bosch <tbosch@google.com> | 2019-07-11 01:19:42 -0700 |
---|---|---|
committer | Tobias Bosch <tbosch@google.com> | 2019-07-12 08:25:40 +0000 |
commit | 9780ea97662c429f6dcb53fb2ef90e98fe1a5f1b (patch) | |
tree | 671f3f511abcbc383b45f1fc3954bb447494e36d /compiler_wrapper | |
parent | 9d60930e882d0e39b48e6dfab0bffa12f6f544ee (diff) | |
download | toolchain-utils-9780ea97662c429f6dcb53fb2ef90e98fe1a5f1b.tar.gz |
Add support for calling bisect driver
Also removes forwarding to old wrapper as we now have all
functionality in the new wrapper.
BUG=chromium:773875
TEST=unit test, ran command for bisect driver manually in terminal.
Change-Id: Icea8a20030bc72e46d6802934acd1d657f62d766
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/toolchain-utils/+/1697929
Reviewed-by: George Burgess <gbiv@chromium.org>
Tested-by: Tobias Bosch <tbosch@google.com>
Diffstat (limited to 'compiler_wrapper')
-rw-r--r-- | compiler_wrapper/bisect_flag.go | 30 | ||||
-rw-r--r-- | compiler_wrapper/bisect_flag_test.go | 88 | ||||
-rw-r--r-- | compiler_wrapper/compiler_wrapper.go | 16 | ||||
-rw-r--r-- | compiler_wrapper/compiler_wrapper_test.go | 28 | ||||
-rw-r--r-- | compiler_wrapper/oldwrapper.go | 14 | ||||
-rw-r--r-- | compiler_wrapper/oldwrapper_test.go | 103 | ||||
-rw-r--r-- | compiler_wrapper/rusage_flag_test.go | 2 |
7 files changed, 157 insertions, 124 deletions
diff --git a/compiler_wrapper/bisect_flag.go b/compiler_wrapper/bisect_flag.go new file mode 100644 index 00000000..14d84cd4 --- /dev/null +++ b/compiler_wrapper/bisect_flag.go @@ -0,0 +1,30 @@ +package main + +import "path/filepath" + +const bisectPythonCommand = "import bisect_driver; sys.exit(bisect_driver.bisect_driver(sys.argv[1], sys.argv[2], sys.argv[3:]))" + +func getBisectStage(env env) string { + return env.getenv("BISECT_STAGE") +} + +func calcBisectCommand(env env, bisectStage string, compilerCmd *command) *command { + bisectDir := env.getenv("BISECT_DIR") + if bisectDir == "" { + bisectDir = "/tmp/sysroot_bisect" + } + absCompilerPath := compilerCmd.path + if !filepath.IsAbs(absCompilerPath) { + absCompilerPath = filepath.Join(env.getwd(), absCompilerPath) + } + return &command{ + path: "/usr/bin/python2", + args: append([]string{ + "-c", + bisectPythonCommand, + bisectStage, + bisectDir, + absCompilerPath, + }, compilerCmd.args...), + } +} diff --git a/compiler_wrapper/bisect_flag_test.go b/compiler_wrapper/bisect_flag_test.go new file mode 100644 index 00000000..2b099912 --- /dev/null +++ b/compiler_wrapper/bisect_flag_test.go @@ -0,0 +1,88 @@ +package main + +import ( + "errors" + "fmt" + "io" + "path/filepath" + "regexp" + "strings" + "testing" +) + +func TestCallBisectDriver(t *testing.T) { + withBisectTestContext(t, func(ctx *testContext) { + ctx.env = []string{ + "BISECT_STAGE=someBisectStage", + "BISECT_DIR=someBisectDir", + } + cmd := ctx.must(callCompiler(ctx, ctx.cfg, ctx.newCommand(gccX86_64, mainCc))) + if err := verifyPath(cmd, "/usr/bin/python2"); err != nil { + t.Error(err) + } + if err := verifyArgOrder(cmd, "-c", regexp.QuoteMeta(bisectPythonCommand), + "someBisectStage", "someBisectDir", filepath.Join(ctx.tempDir, gccX86_64+".real"), "--sysroot=.*", mainCc); err != nil { + t.Error(err) + } + }) +} + +func TestDefaultBisectDir(t *testing.T) { + withBisectTestContext(t, func(ctx *testContext) { + ctx.env = []string{ + "BISECT_STAGE=someBisectStage", + } + cmd := ctx.must(callCompiler(ctx, ctx.cfg, ctx.newCommand(gccX86_64, mainCc))) + if err := verifyArgOrder(cmd, "-c", regexp.QuoteMeta(bisectPythonCommand), + "someBisectStage", "/tmp/sysroot_bisect"); err != nil { + t.Error(err) + } + }) +} + +func TestForwardStdOutAndStdErrAndExitCodeFromBisect(t *testing.T) { + withBisectTestContext(t, func(ctx *testContext) { + ctx.cmdMock = func(cmd *command, stdout io.Writer, stderr io.Writer) error { + fmt.Fprint(stdout, "somemessage") + fmt.Fprint(stderr, "someerror") + return newExitCodeError(23) + } + exitCode := callCompiler(ctx, ctx.cfg, ctx.newCommand(gccX86_64, mainCc)) + if exitCode != 23 { + t.Errorf("unexpected exit code. Got: %d", exitCode) + } + 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 TestForwardGeneralErrorFromBisect(t *testing.T) { + withBisectTestContext(t, func(ctx *testContext) { + 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, "someerror") { + t.Errorf("unexpected error. Got: %s", stderr) + } + }) +} + +func withBisectTestContext(t *testing.T, work func(ctx *testContext)) { + withTestContext(t, func(ctx *testContext) { + // Disable comparing to the old wrapper as that calls the bisect_driver + // directly from python, and the new wrapper calls it via a separate + // sub command. + ctx.cfg.oldWrapperPath = "" + ctx.env = []string{"BISECT_STAGE=xyz"} + work(ctx) + }) +} diff --git a/compiler_wrapper/compiler_wrapper.go b/compiler_wrapper/compiler_wrapper.go index 8c5825e8..b0269abe 100644 --- a/compiler_wrapper/compiler_wrapper.go +++ b/compiler_wrapper/compiler_wrapper.go @@ -9,11 +9,7 @@ import ( func callCompiler(env env, cfg *config, inputCmd *command) int { exitCode := 0 var compilerErr error - if shouldForwardToOldWrapper(env, inputCmd) { - // TODO: Once this is only checking for bisect, create a command - // that directly calls the bisect driver in calcCompilerCommand. - exitCode, compilerErr = forwardToOldWrapper(env, cfg, inputCmd) - } else if cfg.oldWrapperPath != "" { + if cfg.oldWrapperPath != "" { exitCode, compilerErr = callCompilerWithRunAndCompareToOldWrapper(env, cfg, inputCmd) } else { exitCode, compilerErr = callCompilerInternal(env, cfg, inputCmd) @@ -75,15 +71,25 @@ func callCompilerInternal(env env, cfg *config, inputCmd *command) (exitCode int compilerCmd = calcGccCommand(mainBuilder) } rusageLogfileName := getRusageLogFilename(env) + bisectStage := getBisectStage(env) if shouldForceDisableWError(env) { if rusageLogfileName != "" { return 0, newUserErrorf("GETRUSAGE is meaningless with FORCE_DISABLE_WERROR") } + if bisectStage != "" { + return 0, newUserErrorf("BISECT_STAGE is meaningless with FORCE_DISABLE_WERROR") + } return doubleBuildWithWNoError(env, cfg, compilerCmd) } if rusageLogfileName != "" { + if bisectStage != "" { + return 0, newUserErrorf("BISECT_STAGE is meaningless with GETRUSAGE") + } return logRusage(env, rusageLogfileName, compilerCmd) } + if bisectStage != "" { + compilerCmd = calcBisectCommand(env, bisectStage, compilerCmd) + } // Note: We return an exit code only if the underlying env is not // really doing an exec, e.g. commandRecordingEnv. return wrapSubprocessErrorWithSourceLoc(compilerCmd, env.exec(compilerCmd)) diff --git a/compiler_wrapper/compiler_wrapper_test.go b/compiler_wrapper/compiler_wrapper_test.go index 0a041fe8..5e347ec1 100644 --- a/compiler_wrapper/compiler_wrapper_test.go +++ b/compiler_wrapper/compiler_wrapper_test.go @@ -128,7 +128,7 @@ func TestErrorOnLogRusageAndForceDisableWError(t *testing.T) { withTestContext(t, func(ctx *testContext) { ctx.env = []string{ "FORCE_DISABLE_WERROR=1", - "GETRUSAGE=" + filepath.Join(ctx.tempDir, "rusage.log"), + "GETRUSAGE=rusage.log", } stderr := ctx.mustFail(callCompiler(ctx, ctx.cfg, ctx.newCommand(gccX86_64, mainCc))) if err := verifyNonInternalError(stderr, "GETRUSAGE is meaningless with FORCE_DISABLE_WERROR"); err != nil { @@ -137,6 +137,32 @@ func TestErrorOnLogRusageAndForceDisableWError(t *testing.T) { }) } +func TestErrorOnLogRusageAndBisect(t *testing.T) { + withTestContext(t, func(ctx *testContext) { + ctx.env = []string{ + "BISECT_STAGE=xyz", + "GETRUSAGE=rusage.log", + } + stderr := ctx.mustFail(callCompiler(ctx, ctx.cfg, ctx.newCommand(gccX86_64, mainCc))) + if err := verifyNonInternalError(stderr, "BISECT_STAGE is meaningless with GETRUSAGE"); err != nil { + t.Error(err) + } + }) +} + +func TestErrorOnBisectAndForceDisableWError(t *testing.T) { + withTestContext(t, func(ctx *testContext) { + ctx.env = []string{ + "BISECT_STAGE=xyz", + "FORCE_DISABLE_WERROR=1", + } + stderr := ctx.mustFail(callCompiler(ctx, ctx.cfg, ctx.newCommand(gccX86_64, mainCc))) + if err := verifyNonInternalError(stderr, "BISECT_STAGE is meaningless with FORCE_DISABLE_WERROR"); err != nil { + t.Error(err) + } + }) +} + func TestPrintUserCompilerError(t *testing.T) { buffer := bytes.Buffer{} printCompilerError(&buffer, newUserErrorf("abcd")) diff --git a/compiler_wrapper/oldwrapper.go b/compiler_wrapper/oldwrapper.go index 1b510f6c..e4ec0b81 100644 --- a/compiler_wrapper/oldwrapper.go +++ b/compiler_wrapper/oldwrapper.go @@ -17,20 +17,6 @@ import ( const forwardToOldWrapperFilePattern = "old_wrapper_forward" const compareToOldWrapperFilePattern = "old_wrapper_compare" -// Whether the command should be executed by the old wrapper as we don't -// support it yet. -func shouldForwardToOldWrapper(env env, inputCmd *command) bool { - return env.getenv("BISECT_STAGE") != "" -} - -func forwardToOldWrapper(env env, cfg *config, inputCmd *command) (exitCode int, err error) { - oldWrapperCfg, err := newOldWrapperConfig(env, cfg, inputCmd) - if err != nil { - return 0, err - } - return callOldWrapper(env, oldWrapperCfg, inputCmd, forwardToOldWrapperFilePattern, env.stdout(), env.stderr()) -} - func compareToOldWrapper(env env, cfg *config, inputCmd *command, newCmdResults []*commandResult, newExitCode int) error { oldWrapperCfg, err := newOldWrapperConfig(env, cfg, inputCmd) if err != nil { diff --git a/compiler_wrapper/oldwrapper_test.go b/compiler_wrapper/oldwrapper_test.go index 5c4b20c3..d981d0a9 100644 --- a/compiler_wrapper/oldwrapper_test.go +++ b/compiler_wrapper/oldwrapper_test.go @@ -2,8 +2,6 @@ package main import ( "bytes" - "errors" - "fmt" "io" "path/filepath" "strings" @@ -11,107 +9,6 @@ import ( "text/template" ) -func TestNoForwardToOldWrapperBecauseOfEnv(t *testing.T) { - withTestContext(t, func(ctx *testContext) { - testEnvs := []string{"PATH=abc"} - for _, testEnv := range testEnvs { - ctx.env = []string{testEnv} - forwarded := false - ctx.cmdMock = func(cmd *command, stdout io.Writer, stderr io.Writer) error { - if isForwardToOldWrapperCmd(cmd) { - forwarded = true - } - return nil - } - ctx.must(callCompiler(ctx, ctx.cfg, ctx.newCommand(clangX86_64))) - if forwarded { - t.Errorf("forwarded to old wrapper for env %s", testEnv) - } - } - }) -} - -func TestForwardToOldWrapperBecauseOfEnv(t *testing.T) { - withForwardToOldWrapperTestContext(t, func(ctx *testContext) { - testEnvs := []string{ - "BISECT_STAGE=abc", - } - for _, testEnv := range testEnvs { - ctx.env = []string{testEnv} - forwarded := false - ctx.cmdMock = func(cmd *command, stdout io.Writer, stderr io.Writer) error { - forwarded = true - if !isForwardToOldWrapperCmd(cmd) { - return newErrorwithSourceLocf("expected call to old wrapper. Got: %s", cmd.path) - } - return nil - } - ctx.must(callCompiler(ctx, ctx.cfg, ctx.newCommand(clangX86_64))) - if !forwarded { - t.Errorf("not forwarded to old wrapper for env %s", testEnv) - } - } - }) -} - -func TestForwardStdOutAndStderrFromOldWrapperOnSuccess(t *testing.T) { - withForwardToOldWrapperTestContext(t, func(ctx *testContext) { - ctx.env = []string{"BISECT_STAGE=abc"} - ctx.cmdMock = func(cmd *command, stdout io.Writer, stderr io.Writer) error { - fmt.Fprint(stdout, "somemessage") - fmt.Fprint(stderr, "someerror") - return nil - } - - ctx.must(callCompiler(ctx, ctx.cfg, ctx.newCommand(clangX86_64))) - if ctx.stdoutString() != "somemessage" { - t.Errorf("stdout was not exactly forwarded. Got: %s", ctx.stdoutString()) - } - if ctx.stderrString() != "someerror" { - t.Errorf("stderr was not exactly forwarded. Got: %s", ctx.stderrString()) - } - }) -} - -func TestReportExitCodeErrorsWhenForwardingToOldWrapper(t *testing.T) { - withForwardToOldWrapperTestContext(t, func(ctx *testContext) { - ctx.env = []string{"BISECT_STAGE=abc"} - ctx.cmdMock = func(cmd *command, stdout io.Writer, stderr io.Writer) error { - fmt.Fprint(stderr, "someerror") - return newExitCodeError(2) - } - - exitCode := callCompiler(ctx, ctx.cfg, ctx.newCommand(clangX86_64)) - if exitCode != 2 { - t.Fatalf("Expected exit code 2. Got %d", exitCode) - } - if err := verifyNonInternalError(ctx.stderrString(), "someerror"); err != nil { - t.Fatal(err) - } - }) -} - -func TestReportGeneralErrorsWhenForwardingToOldWrapper(t *testing.T) { - withForwardToOldWrapperTestContext(t, func(ctx *testContext) { - ctx.env = []string{"BISECT_STAGE=abc"} - ctx.cmdMock = func(cmd *command, stdout io.Writer, stderr io.Writer) error { - fmt.Fprint(stderr, "someoldwrappererror") - return errors.New("someerror") - } - - stderr := ctx.mustFail(callCompiler(ctx, ctx.cfg, ctx.newCommand(clangX86_64))) - if err := verifyInternalError(stderr); err != nil { - t.Fatal(err) - } - if !strings.Contains(stderr, "someerror") { - t.Errorf("error message was not forwarded. Got: %s", stderr) - } - if !strings.Contains(stderr, "someoldwrappererror") { - t.Errorf("stderr was not forwarded. Got: %s", stderr) - } - }) -} - func TestCompareToOldWrapperCompilerCommand(t *testing.T) { withTestContext(t, func(ctx *testContext) { ctx.cfg.mockOldWrapperCmds = false diff --git a/compiler_wrapper/rusage_flag_test.go b/compiler_wrapper/rusage_flag_test.go index 4fb3133f..9e877458 100644 --- a/compiler_wrapper/rusage_flag_test.go +++ b/compiler_wrapper/rusage_flag_test.go @@ -143,7 +143,7 @@ func TestLogRusageAppendsToFile(t *testing.T) { func withLogRusageTestContext(t *testing.T, work func(ctx *testContext)) { withTestContext(t, func(ctx *testContext) { - // Disable comparing to the old wrapper as we that uses fork + wait3 + // Disable comparing to the old wrapper as that uses fork + wait3 // to calculate resource usage, and the new wrapper uses the getrusage // syscall. ctx.cfg.oldWrapperPath = "" |