From 8dd67e1063927b99ee18caa11ccee9abc1c0cbd1 Mon Sep 17 00:00:00 2001 From: Tobias Bosch Date: Mon, 28 Oct 2019 14:26:51 -0700 Subject: toolchain_utils: Remove comparison to old wrapper from compiler_wrapper. BUG=chromium:773875 TEST='go test' passes Change-Id: Iecbe15067bf37fd86fbb8a907d42df32288821d6 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/toolchain-utils/+/1884701 Reviewed-by: George Burgess Tested-by: Tobias Bosch --- compiler_wrapper/android_config_test.go | 3 +- compiler_wrapper/bisect_flag_test.go | 18 +- compiler_wrapper/compiler_wrapper.go | 23 +- compiler_wrapper/compiler_wrapper_test.go | 80 +---- compiler_wrapper/config.go | 11 +- compiler_wrapper/cros_hardened_config_test.go | 45 +-- compiler_wrapper/cros_host_config_test.go | 6 +- compiler_wrapper/cros_nonhardened_config_test.go | 3 +- compiler_wrapper/goldenutil_test.go | 11 +- compiler_wrapper/main.go | 9 +- compiler_wrapper/oldwrapper.go | 392 --------------------- compiler_wrapper/oldwrapper_test.go | 431 ----------------------- compiler_wrapper/print_config_flag_test.go | 12 +- compiler_wrapper/rusage_flag_test.go | 4 - compiler_wrapper/testutil_test.go | 43 --- 15 files changed, 41 insertions(+), 1050 deletions(-) delete mode 100644 compiler_wrapper/oldwrapper.go delete mode 100644 compiler_wrapper/oldwrapper_test.go (limited to 'compiler_wrapper') diff --git a/compiler_wrapper/android_config_test.go b/compiler_wrapper/android_config_test.go index 104be6df..c61490f4 100644 --- a/compiler_wrapper/android_config_test.go +++ b/compiler_wrapper/android_config_test.go @@ -10,14 +10,13 @@ import ( "testing" ) -const oldAndroidPathForTest = "$ANDROID_PREBUILTS/clang/host/linux-x86/clang-r353983c/bin/clang" const androidGoldenDir = "testdata/android_golden" func TestAndroidConfig(t *testing.T) { withTestContext(t, func(ctx *testContext) { useLlvmNext := false useCCache := false - cfg, err := getConfig("android", useCCache, useLlvmNext, oldAndroidPathForTest, "123") + cfg, err := getConfig("android", useCCache, useLlvmNext, "123") if err != nil { t.Fatal(err) } diff --git a/compiler_wrapper/bisect_flag_test.go b/compiler_wrapper/bisect_flag_test.go index 0bb6a820..5c4c82d6 100644 --- a/compiler_wrapper/bisect_flag_test.go +++ b/compiler_wrapper/bisect_flag_test.go @@ -131,14 +131,9 @@ func TestForwardGeneralErrorFromBisect(t *testing.T) { 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"} // We execute the python script but replace the call to the bisect_driver with - // a mock that logs the data in the same way as the oldwrapper. This way - // we can reuse the parseOldWrapperCommands to get the values. + // a mock that logs the data. ctx.cmdMock = func(cmd *command, stdin io.Reader, stdout io.Writer, stderr io.Writer) error { if err := verifyPath(cmd, "/usr/bin/env"); err != nil { return err @@ -177,6 +172,13 @@ bisect_driver = BisectDriver() func mustCallBisectDriver(ctx *testContext, exitCode int) *command { ctx.must(exitCode) - cmds, _ := parseOldWrapperCommands(ctx.stdoutString()) - return cmds[0] + cmd := &command{} + for _, line := range strings.Split(ctx.stdoutString(), "\n") { + if prefix := "command "; strings.HasPrefix(line, prefix) { + cmd.Path = line[len(prefix):] + } else if prefix := "arg "; strings.HasPrefix(line, prefix) { + cmd.Args = append(cmd.Args, line[len(prefix):]) + } + } + return cmd } diff --git a/compiler_wrapper/compiler_wrapper.go b/compiler_wrapper/compiler_wrapper.go index 1ab7e99b..c614b99f 100644 --- a/compiler_wrapper/compiler_wrapper.go +++ b/compiler_wrapper/compiler_wrapper.go @@ -5,7 +5,6 @@ package main import ( - "bytes" "fmt" "io" "path/filepath" @@ -29,11 +28,7 @@ func callCompiler(env env, cfg *config, inputCmd *command) int { } exitCode := 0 if compilerErr == nil { - if cfg.oldWrapperPath != "" { - exitCode, compilerErr = callCompilerWithRunAndCompareToOldWrapper(env, cfg, inputCmd) - } else { - exitCode, compilerErr = callCompilerInternal(env, cfg, inputCmd) - } + exitCode, compilerErr = callCompilerInternal(env, cfg, inputCmd) } if compilerErr != nil { printCompilerError(env.stderr(), compilerErr) @@ -42,22 +37,6 @@ func callCompiler(env env, cfg *config, inputCmd *command) int { return exitCode } -func callCompilerWithRunAndCompareToOldWrapper(env env, cfg *config, inputCmd *command) (exitCode int, err error) { - stdinBuffer := &bytes.Buffer{} - recordingEnv := &commandRecordingEnv{ - env: env, - stdinReader: teeStdinIfNeeded(env, inputCmd, stdinBuffer), - } - // Note: this won't do a real exec as recordingEnv redirects exec to run. - if exitCode, err = callCompilerInternal(recordingEnv, cfg, inputCmd); err != nil { - return 0, err - } - if err = compareToOldWrapper(env, cfg, inputCmd, stdinBuffer.Bytes(), recordingEnv.cmdResults, exitCode); err != nil { - return exitCode, err - } - return exitCode, nil -} - func callCompilerInternal(env env, cfg *config, inputCmd *command) (exitCode int, err error) { if err := checkUnsupportedFlags(inputCmd); err != nil { return 0, err diff --git a/compiler_wrapper/compiler_wrapper_test.go b/compiler_wrapper/compiler_wrapper_test.go index 71cd36df..67cbda92 100644 --- a/compiler_wrapper/compiler_wrapper_test.go +++ b/compiler_wrapper/compiler_wrapper_test.go @@ -9,7 +9,6 @@ import ( "errors" "fmt" "io" - "path/filepath" "strings" "syscall" "testing" @@ -50,27 +49,18 @@ func TestAddClangConfigFlags(t *testing.T) { func TestLogGeneralExecError(t *testing.T) { withTestContext(t, func(ctx *testContext) { - testOldWrapperPaths := []string{ - "", - filepath.Join(ctx.tempDir, "fakewrapper"), - } - 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, stdin io.Reader, 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) - } + ctx.cmdMock = func(cmd *command, stdin io.Reader, 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) } }) } @@ -93,50 +83,12 @@ func TestLogMissingCCacheExecError(t *testing.T) { withTestContext(t, func(ctx *testContext) { ctx.cfg.useCCache = true - testOldWrapperPaths := []string{ - "", - filepath.Join(ctx.tempDir, "fakewrapper"), - } - 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, stdin io.Reader, 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, stdin io.Reader, stdout io.Writer, stderr io.Writer) error { - writePythonMockWrapper(ctx, &mockWrapperConfig{ - Cmds: []*mockWrapperCmd{ - { - Path: cmd.Path, - Args: cmd.Args, - ExitCode: 2, - }, - }, - }) - fmt.Fprint(stderr, "someerror") - return newExitCodeError(2) + return syscall.ENOENT } - - 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 { + 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) } }) diff --git a/compiler_wrapper/config.go b/compiler_wrapper/config.go index 3e446201..5f389684 100644 --- a/compiler_wrapper/config.go +++ b/compiler_wrapper/config.go @@ -25,10 +25,6 @@ type config struct { clangPostFlags []string // Toolchain root path relative to the wrapper binary. rootRelPath string - // Path of the old wrapper using the toolchain root. - oldWrapperPath string - // Whether to mock out the calls that the old wrapper does. - mockOldWrapperCmds bool // Directory to store errors that were prevented with -Wno-error. newWarningsDir string // Version. Only used for printing via -print-cmd. @@ -65,16 +61,14 @@ func getRealConfig() (*config, error) { if err != nil { return nil, wrapErrorwithSourceLocf(err, "invalid format for UseLLvmNext") } - // FIXME: Remove comparison to old wrapper once the new wrapper has landed. - oldWrapperPath := "" - config, err := getConfig(ConfigName, useCCache, useLlvmNext, oldWrapperPath, Version) + config, err := getConfig(ConfigName, useCCache, useLlvmNext, Version) if err != nil { return nil, err } return config, nil } -func getConfig(configName string, useCCache bool, useLlvmNext bool, oldWrapperPath string, version string) (*config, error) { +func getConfig(configName string, useCCache bool, useLlvmNext bool, version string) (*config, error) { cfg := config{} switch configName { case "cros.hardened": @@ -92,7 +86,6 @@ func getConfig(configName string, useCCache bool, useLlvmNext bool, oldWrapperPa if useLlvmNext { cfg.clangFlags = append(cfg.clangFlags, llvmNextFlags...) } - cfg.oldWrapperPath = oldWrapperPath cfg.version = version return &cfg, nil } diff --git a/compiler_wrapper/cros_hardened_config_test.go b/compiler_wrapper/cros_hardened_config_test.go index 10d8bf6f..b459f1e2 100644 --- a/compiler_wrapper/cros_hardened_config_test.go +++ b/compiler_wrapper/cros_hardened_config_test.go @@ -6,15 +6,12 @@ package main import ( "fmt" - "io/ioutil" "path" "path/filepath" - "regexp" "strings" "testing" ) -const oldHardenedWrapperPathForTest = "$CHROOT/usr/x86_64-pc-linux-gnu/x86_64-cros-linux-gnu/gcc-bin/4.9.x/sysroot_wrapper.hardened" const crosHardenedGoldenDir = "testdata/cros_hardened_golden" const crosHardenedNoCCacheGoldenDir = "testdata/cros_hardened_noccache_golden" const crosHardenedLlvmNextGoldenDir = "testdata/cros_hardened_llvmnext_golden" @@ -23,7 +20,7 @@ func TestCrosHardenedConfig(t *testing.T) { withTestContext(t, func(ctx *testContext) { useLlvmNext := false useCCache := true - cfg, err := getConfig("cros.hardened", useCCache, useLlvmNext, oldHardenedWrapperPathForTest, "123") + cfg, err := getConfig("cros.hardened", useCCache, useLlvmNext, "123") if err != nil { t.Fatal(err) } @@ -37,25 +34,12 @@ func TestCrosHardenedConfigWithoutCCache(t *testing.T) { withTestContext(t, func(ctx *testContext) { useLlvmNext := false useCCache := false - cfg, err := getConfig("cros.hardened", useCCache, useLlvmNext, oldHardenedWrapperPathForTest, "123") + cfg, err := getConfig("cros.hardened", useCCache, useLlvmNext, "123") if err != nil { t.Fatal(err) } ctx.updateConfig(cfg) - // Create a copy of the old wrapper where the CCACHE_DEFAULT is false. - if ctx.cfg.oldWrapperPath != "" { - oldWrapperContent, err := ioutil.ReadFile(ctx.cfg.oldWrapperPath) - if err != nil { - t.Fatal(err) - } - oldWrapperContent = regexp.MustCompile(`True\s+#\s+@CCACHE_DEFAULT@`).ReplaceAll(oldWrapperContent, []byte("False #")) - ctx.cfg.oldWrapperPath = filepath.Join(ctx.tempDir, "oldwrapper_noccache") - if err := ioutil.WriteFile(ctx.cfg.oldWrapperPath, oldWrapperContent, 0666); err != nil { - t.Fatal(err) - } - } - // Only run the subset of the sysroot wrapper tests that execute commands. gomaPath := path.Join(ctx.tempDir, "gomacc") ctx.writeFile(gomaPath, "") @@ -75,31 +59,12 @@ func TestCrosHardenedConfigWithLlvmNext(t *testing.T) { withTestContext(t, func(ctx *testContext) { useLlvmNext := true useCCache := true - cfg, err := getConfig("cros.hardened", useCCache, useLlvmNext, oldHardenedWrapperPathForTest, "123") + cfg, err := getConfig("cros.hardened", useCCache, useLlvmNext, "123") if err != nil { t.Fatal(err) } ctx.updateConfig(cfg) - // Create a copy of the old wrapper where we add the llvm next flags - if ctx.cfg.oldWrapperPath != "" { - oldWrapperContent, err := ioutil.ReadFile(ctx.cfg.oldWrapperPath) - if err != nil { - t.Fatal(err) - } - oldWrapperLlvmNextFlags := ` -LLVM_NEXT_FLAGS_TO_ADD = set(['-Wno-reorder-init-list', -'-Wno-final-dtor-non-final-class', -'-Wno-implicit-int-float-conversion', -'-Wno-return-stack-address' -])` - oldWrapperContent = regexp.MustCompile(`LLVM_NEXT_FLAGS_TO_ADD = set\(\[\]\)`).ReplaceAll(oldWrapperContent, []byte(oldWrapperLlvmNextFlags)) - ctx.cfg.oldWrapperPath = filepath.Join(ctx.tempDir, "oldwrapper_llvmnext") - if err := ioutil.WriteFile(ctx.cfg.oldWrapperPath, oldWrapperContent, 0666); err != nil { - t.Fatal(err) - } - } - // Only run the subset of the sysroot wrapper tests that execute commands. gomaPath := path.Join(ctx.tempDir, "gomacc") ctx.writeFile(gomaPath, "") @@ -187,10 +152,6 @@ func createGoldenInputsForAllTargets(compiler string, args ...string) goldenFile func createBisectGoldenInputs(compiler string) goldenFile { return goldenFile{ Name: "bisect.json", - // 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. - ignoreOldWrapper: true, Records: []goldenRecord{ { WrapperCmd: newGoldenCmd(compiler, mainCc), diff --git a/compiler_wrapper/cros_host_config_test.go b/compiler_wrapper/cros_host_config_test.go index d2be9ab6..fee78e62 100644 --- a/compiler_wrapper/cros_host_config_test.go +++ b/compiler_wrapper/cros_host_config_test.go @@ -9,8 +9,6 @@ import ( "testing" ) -const oldClangHostWrapperPathForTest = "$CHROOT/usr/bin/clang_host_wrapper" -const oldGccHostWrapperPathForTest = "$CHROOT/../src/third_party/chromiumos-overlay/sys-devel/gcc/files/host_wrapper" const crosClangHostGoldenDir = "testdata/cros_clang_host_golden" const crosGccHostGoldenDir = "testdata/cros_gcc_host_golden" @@ -18,7 +16,7 @@ func TestCrosClangHostConfig(t *testing.T) { withTestContext(t, func(ctx *testContext) { useLlvmNext := false useCCache := false - cfg, err := getConfig("cros.host", useCCache, useLlvmNext, oldClangHostWrapperPathForTest, "123") + cfg, err := getConfig("cros.host", useCCache, useLlvmNext, "123") if err != nil { t.Fatal(err) } @@ -48,7 +46,7 @@ func TestCrosGccHostConfig(t *testing.T) { withTestContext(t, func(ctx *testContext) { useLlvmNext := false useCCache := false - cfg, err := getConfig("cros.host", useCCache, useLlvmNext, oldGccHostWrapperPathForTest, "123") + cfg, err := getConfig("cros.host", useCCache, useLlvmNext, "123") if err != nil { t.Fatal(err) } diff --git a/compiler_wrapper/cros_nonhardened_config_test.go b/compiler_wrapper/cros_nonhardened_config_test.go index bf8af4d2..4883c5f9 100644 --- a/compiler_wrapper/cros_nonhardened_config_test.go +++ b/compiler_wrapper/cros_nonhardened_config_test.go @@ -8,14 +8,13 @@ import ( "testing" ) -const oldNonHardenedWrapperPathForTest = "$CHROOT/usr/x86_64-pc-linux-gnu/arm-none-eabi/gcc-bin/4.9.x/sysroot_wrapper" const crosNonHardenedGoldenDir = "testdata/cros_nonhardened_golden" func TestCrosNonHardenedConfig(t *testing.T) { withTestContext(t, func(ctx *testContext) { useLlvmNext := false useCCache := true - cfg, err := getConfig("cros.nonhardened", useCCache, useLlvmNext, oldNonHardenedWrapperPathForTest, "123") + cfg, err := getConfig("cros.nonhardened", useCCache, useLlvmNext, "123") if err != nil { t.Fatal(err) } diff --git a/compiler_wrapper/goldenutil_test.go b/compiler_wrapper/goldenutil_test.go index 4eff8738..e6b42f77 100644 --- a/compiler_wrapper/goldenutil_test.go +++ b/compiler_wrapper/goldenutil_test.go @@ -21,9 +21,8 @@ var updateGoldenFiles = flag.Bool("updategolden", false, "update golden files") var filterGoldenTests = flag.String("rungolden", "", "regex filter for golden tests to run") type goldenFile struct { - Name string `json:"name"` - ignoreOldWrapper bool - Records []goldenRecord `json:"records"` + Name string `json:"name"` + Records []goldenRecord `json:"records"` } type goldenRecord struct { @@ -115,14 +114,8 @@ func filterGoldenRecords(pattern string, files []goldenFile) []goldenFile { } func fillGoldenResults(ctx *testContext, files []goldenFile) []goldenFile { - oldWrapperPath := ctx.cfg.oldWrapperPath newFiles := []goldenFile{} for _, file := range files { - ctx.cfg.oldWrapperPath = oldWrapperPath - if file.ignoreOldWrapper { - ctx.cfg.oldWrapperPath = "" - } - newRecords := []goldenRecord{} for _, record := range file.Records { newCmds := []commandResult{} diff --git a/compiler_wrapper/main.go b/compiler_wrapper/main.go index 3fcf3a66..046cf5a5 100644 --- a/compiler_wrapper/main.go +++ b/compiler_wrapper/main.go @@ -6,24 +6,17 @@ // - main.UseCCache: Whether to use ccache. // - main.ConfigName: Name of the configuration to use. // See config.go for the supported values. -// - main.OldWrapperPath: Path to the old wrapper to compare commands -// against. Comparison is deactivated if empty. // // The script ./build simplifies the call to `go build`. // E.g. ./build --use_ccache=true --config=cros.hardened will build a // binary that uses the ccache for ChromeOS with hardened flags. // // Test arguments: -// - crosroot: Specifies the ChromeOS toolchain root directory (aka chroot). -// If this is given, golden tests will compare the produced commands against the -// old compiler wrapper. // - updategolden: To update the golden results for the wrapper. Without it, // the tests will verify that the wrapper output matches the goldens. // - rungolden: To filter the golden tests by a regex for the wrapper env, path and args. // // Examples: -// - run all tests and compare golden output against old compiler wrapper: -// go test third_party/toolchain-utils/compiler_wrapper/ -v --crosroot=$HOME/chromiumos/chroot/ // - run all tests in isolation: // go test third_party/toolchain-utils/compiler_wrapper/ -v package main @@ -43,7 +36,7 @@ func main() { log.Fatal(err) } // Note: callCompiler will exec the command. Only in case of - // an error or when we are comparing against the old wrapper + // an error or when we run other commands like bisect // will this os.Exit be called. os.Exit(callCompiler(env, cfg, newProcessCommand())) } diff --git a/compiler_wrapper/oldwrapper.go b/compiler_wrapper/oldwrapper.go deleted file mode 100644 index 72178da0..00000000 --- a/compiler_wrapper/oldwrapper.go +++ /dev/null @@ -1,392 +0,0 @@ -// 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 ( - "bytes" - "fmt" - "io" - "io/ioutil" - "os" - "path/filepath" - "reflect" - "regexp" - "sort" - "strings" - "text/template" -) - -const compareToOldWrapperFilePattern = "old_wrapper_compare" - -// Note: We can't rely on os.TempDir as that just returns the value of $TMPDIR, -// which some packages set incorrectly. -// E.g. dev-python/pygobject sets it to "`pwd`/pygobject-2.18.0". -const tempDir = "/tmp" - -func compareToOldWrapper(env env, cfg *config, inputCmd *command, stdinBuffer []byte, newCmdResults []*commandResult, newExitCode int) error { - pythonStringEscaper := strings.NewReplacer("\n", "\\n", "'", "\\'", "\\", "\\\\") - - oldWrapperCfg, err := newOldWrapperConfig(env, cfg, inputCmd) - if err != nil { - return err - } - oldWrapperCfg.MockCmds = cfg.mockOldWrapperCmds - newCmds := []*command{} - for _, cmdResult := range newCmdResults { - oldWrapperCfg.CmdResults = append(oldWrapperCfg.CmdResults, oldWrapperCmdResult{ - Stdout: pythonStringEscaper.Replace(cmdResult.Stdout), - Stderr: pythonStringEscaper.Replace(cmdResult.Stderr), - Exitcode: cmdResult.ExitCode, - }) - newCmds = append(newCmds, cmdResult.Cmd) - } - - stderrBuffer := bytes.Buffer{} - oldExitCode := 0 - if strings.HasPrefix(oldWrapperCfg.OldWrapperContent, "#!/bin/sh") { - oldExitCode, err = callOldShellWrapper(env, oldWrapperCfg, inputCmd, stdinBuffer, compareToOldWrapperFilePattern, &bytes.Buffer{}, &stderrBuffer) - } else { - oldExitCode, err = callOldPythonWrapper(env, oldWrapperCfg, inputCmd, stdinBuffer, compareToOldWrapperFilePattern, &bytes.Buffer{}, &stderrBuffer) - } - if err != nil { - return err - } - differences := []string{} - if oldExitCode != newExitCode { - differences = append(differences, fmt.Sprintf("exit codes differ: old %d, new %d", oldExitCode, newExitCode)) - } - oldCmds, stderr := parseOldWrapperCommands(stderrBuffer.String()) - if cmdDifferences := diffCommands(oldCmds, newCmds); cmdDifferences != "" { - differences = append(differences, cmdDifferences) - } - if len(differences) > 0 { - printCmd(env, inputCmd) - return newErrorwithSourceLocf("wrappers differ:\n%s\nOld stderr:%s", - strings.Join(differences, "\n"), - stderr, - ) - } - return nil -} - -func parseOldWrapperCommands(stderr string) (cmds []*command, remainingStderr string) { - allStderrLines := strings.Split(stderr, "\n") - remainingStderrLines := []string{} - commandPrefix := "command " - argPrefix := "arg " - envUpdatePrefix := "envupdate " - currentCmd := (*command)(nil) - for _, line := range allStderrLines { - if strings.HasPrefix(line, commandPrefix) { - currentCmd = &command{ - Path: line[len(commandPrefix):], - } - cmds = append(cmds, currentCmd) - } else if strings.HasPrefix(line, argPrefix) { - currentCmd.Args = append(currentCmd.Args, line[len(argPrefix):]) - } else if strings.HasPrefix(line, envUpdatePrefix) { - currentCmd.EnvUpdates = append(currentCmd.EnvUpdates, line[len(envUpdatePrefix):]) - } else { - remainingStderrLines = append(remainingStderrLines, line) - } - } - remainingStderr = strings.TrimSpace(strings.Join(remainingStderrLines, "\n")) - return cmds, remainingStderr -} - -func diffCommands(oldCmds []*command, newCmds []*command) string { - maxLen := len(newCmds) - if maxLen < len(oldCmds) { - maxLen = len(oldCmds) - } - hasDifferences := false - var cmdDifferences []string - for i := 0; i < maxLen; i++ { - var differences []string - if i >= len(newCmds) { - differences = append(differences, "missing command") - } else if i >= len(oldCmds) { - differences = append(differences, "extra command") - } else { - newCmd := newCmds[i] - oldCmd := oldCmds[i] - - if newCmd.Path != oldCmd.Path { - differences = append(differences, "path") - } - - if !reflect.DeepEqual(newCmd.Args, oldCmd.Args) { - differences = append(differences, "args") - } - - // Sort the environment as we don't care in which order - // it was modified. - copyAndSort := func(data []string) []string { - result := make([]string, len(data)) - copy(result, data) - sort.Strings(result) - return result - } - - newEnvUpdates := copyAndSort(newCmd.EnvUpdates) - oldEnvUpdates := copyAndSort(oldCmd.EnvUpdates) - - if !reflect.DeepEqual(newEnvUpdates, oldEnvUpdates) { - differences = append(differences, "env updates") - } - } - if len(differences) > 0 { - hasDifferences = true - } else { - differences = []string{"none"} - } - cmdDifferences = append(cmdDifferences, - fmt.Sprintf("Index %d: %s", i, strings.Join(differences, ","))) - } - if hasDifferences { - return fmt.Sprintf("commands differ:\n%s\nOld:%#v\nNew:%#v", - strings.Join(cmdDifferences, "\n"), - dumpCommands(oldCmds), - dumpCommands(newCmds)) - } - return "" -} - -func dumpCommands(cmds []*command) string { - lines := []string{} - for _, cmd := range cmds { - lines = append(lines, fmt.Sprintf("%#v", cmd)) - } - return strings.Join(lines, "\n") -} - -// Note: field names are upper case so they can be used in -// a template via reflection. -type oldWrapperConfig struct { - WrapperPath string - CmdPath string - OldWrapperContent string - MockCmds bool - CmdResults []oldWrapperCmdResult -} - -type oldWrapperCmdResult struct { - Stdout string - Stderr string - Exitcode int -} - -func newOldWrapperConfig(env env, cfg *config, inputCmd *command) (*oldWrapperConfig, error) { - absWrapperPath, err := getAbsWrapperPath(env, inputCmd) - if err != nil { - return nil, err - } - absOldWrapperPath := cfg.oldWrapperPath - if !filepath.IsAbs(absOldWrapperPath) { - absOldWrapperPath = filepath.Join(filepath.Dir(absWrapperPath), cfg.oldWrapperPath) - } - oldWrapperContentBytes, err := ioutil.ReadFile(absOldWrapperPath) - if err != nil { - return nil, wrapErrorwithSourceLocf(err, "failed to read old wrapper") - } - oldWrapperContent := string(oldWrapperContentBytes) - return &oldWrapperConfig{ - WrapperPath: absWrapperPath, - CmdPath: inputCmd.Path, - OldWrapperContent: oldWrapperContent, - }, nil -} - -func callOldShellWrapper(env env, cfg *oldWrapperConfig, inputCmd *command, stdinBuffer []byte, filepattern string, stdout io.Writer, stderr io.Writer) (exitCode int, err error) { - oldWrapperContent := cfg.OldWrapperContent - oldWrapperContent = regexp.MustCompile(`(?m)^exec\b`).ReplaceAllString(oldWrapperContent, "exec_mock") - oldWrapperContent = regexp.MustCompile(`\$EXEC`).ReplaceAllString(oldWrapperContent, "exec_mock") - // TODO: Use strings.ReplaceAll once cros sdk uses golang >= 1.12 - oldWrapperContent = strings.Replace(oldWrapperContent, "$0", cfg.CmdPath, -1) - cfg.OldWrapperContent = oldWrapperContent - mockFile, err := ioutil.TempFile(tempDir, filepattern) - if err != nil { - return 0, wrapErrorwithSourceLocf(err, "failed to create tempfile") - } - defer os.Remove(mockFile.Name()) - - const mockTemplate = ` -EXEC=exec - -function exec_mock { - echo command "$1" 1>&2 - for arg in "${@:2}"; do - echo arg "$arg" 1>&2 - done - {{if .MockCmds}} - echo '{{(index .CmdResults 0).Stdout}}' - echo '{{(index .CmdResults 0).Stderr}}' 1>&2 - exit {{(index .CmdResults 0).Exitcode}} - {{else}} - $EXEC "$@" - {{end}} -} - -{{.OldWrapperContent}} -` - tmpl, err := template.New("mock").Parse(mockTemplate) - if err != nil { - return 0, wrapErrorwithSourceLocf(err, "failed to parse old wrapper template") - } - if err := tmpl.Execute(mockFile, cfg); err != nil { - return 0, wrapErrorwithSourceLocf(err, "failed execute old wrapper template") - } - if err := mockFile.Close(); err != nil { - return 0, wrapErrorwithSourceLocf(err, "failed to close temp file") - } - - // Note: Using a self executable wrapper does not work due to a race condition - // on unix systems. See https://github.com/golang/go/issues/22315 - oldWrapperCmd := &command{ - Path: "/bin/sh", - Args: append([]string{mockFile.Name()}, inputCmd.Args...), - EnvUpdates: inputCmd.EnvUpdates, - } - return wrapSubprocessErrorWithSourceLoc(oldWrapperCmd, env.run(oldWrapperCmd, bytes.NewReader(stdinBuffer), stdout, stderr)) -} - -func callOldPythonWrapper(env env, cfg *oldWrapperConfig, inputCmd *command, stdinBuffer []byte, filepattern string, stdout io.Writer, stderr io.Writer) (exitCode int, err error) { - oldWrapperContent := cfg.OldWrapperContent - // TODO: Use strings.ReplaceAll once cros sdk uses golang >= 1.12 - oldWrapperContent = strings.Replace(oldWrapperContent, "from __future__ import print_function", "", -1) - // Replace sets with lists to make our comparisons deterministic - oldWrapperContent = strings.Replace(oldWrapperContent, "set(", "ListSet(", -1) - oldWrapperContent = strings.Replace(oldWrapperContent, "if __name__ == '__main__':", "def runMain():", -1) - oldWrapperContent = strings.Replace(oldWrapperContent, "__file__", "'"+cfg.WrapperPath+"'", -1) - cfg.OldWrapperContent = oldWrapperContent - - mockFile, err := ioutil.TempFile(tempDir, filepattern) - if err != nil { - return 0, wrapErrorwithSourceLocf(err, "failed to create tempfile") - } - defer os.Remove(mockFile.Name()) - - const mockTemplate = ` -# -*- coding: utf-8 -*- -from __future__ import print_function - -class ListSet: - def __init__(self, values): - self.values = list(values) - def __contains__(self, key): - return self.values.__contains__(key) - def __iter__(self): - return self.values.__iter__() - def __nonzero__(self): - return len(self.values) > 0 - def add(self, value): - if value not in self.values: - self.values.append(value) - def discard(self, value): - if value in self.values: - self.values.remove(value) - def intersection(self, values): - return ListSet([value for value in self.values if value in values]) - -{{.OldWrapperContent}} -import subprocess - -init_env = os.environ.copy() - -{{if .MockCmds}} -mockResults = [{{range .CmdResults}} { - 'stdout': '{{.Stdout}}', - 'stderr': '{{.Stderr}}', - 'exitcode': {{.Exitcode}}, -},{{end}}] -{{end}} - -def serialize_cmd(args): - current_env = os.environ - envupdates = [k + "=" + current_env.get(k, '') for k in set(list(current_env.keys()) + list(init_env.keys())) if current_env.get(k, '') != init_env.get(k, '')] - print('command %s' % args[0], file=sys.stderr) - for arg in args[1:]: - print('arg %s' % arg, file=sys.stderr) - for update in envupdates: - print('envupdate %s' % update, file=sys.stderr) - -def check_output_mock(args): - serialize_cmd(args) - {{if .MockCmds}} - result = mockResults.pop(0) - print(result['stderr'], file=sys.stderr) - if result['exitcode']: - raise subprocess.CalledProcessError(result['exitcode']) - return result['stdout'] - {{else}} - return old_check_output(args) - {{end}} - -old_check_output = subprocess.check_output -subprocess.check_output = check_output_mock - -def popen_mock(args, stdout=None, stderr=None): - serialize_cmd(args) - {{if .MockCmds}} - result = mockResults.pop(0) - if stdout is None: - print(result['stdout'], file=sys.stdout) - if stderr is None: - print(result['stderr'], file=sys.stderr) - - class MockResult: - def __init__(self, returncode): - self.returncode = returncode - def wait(self): - return self.returncode - def communicate(self): - return (result['stdout'], result['stderr']) - - return MockResult(result['exitcode']) - {{else}} - return old_popen(args) - {{end}} - -old_popen = subprocess.Popen -subprocess.Popen = popen_mock - -def execv_mock(binary, args): - serialize_cmd([binary] + args[1:]) - {{if .MockCmds}} - result = mockResults.pop(0) - print(result['stdout'], file=sys.stdout) - print(result['stderr'], file=sys.stderr) - sys.exit(result['exitcode']) - {{else}} - old_execv(binary, args) - {{end}} - -old_execv = os.execv -os.execv = execv_mock - -sys.argv[0] = '{{.CmdPath}}' - -runMain() -` - tmpl, err := template.New("mock").Parse(mockTemplate) - if err != nil { - return 0, wrapErrorwithSourceLocf(err, "failed to parse old wrapper template") - } - if err := tmpl.Execute(mockFile, cfg); err != nil { - return 0, wrapErrorwithSourceLocf(err, "failed execute old wrapper template") - } - if err := mockFile.Close(); err != nil { - return 0, wrapErrorwithSourceLocf(err, "failed to close temp file") - } - - // Note: Using a self executable wrapper does not work due to a race condition - // on unix systems. See https://github.com/golang/go/issues/22315 - oldWrapperCmd := &command{ - Path: "/usr/bin/python2", - Args: append([]string{"-S", mockFile.Name()}, inputCmd.Args...), - EnvUpdates: inputCmd.EnvUpdates, - } - return wrapSubprocessErrorWithSourceLoc(oldWrapperCmd, env.run(oldWrapperCmd, bytes.NewReader(stdinBuffer), stdout, stderr)) -} diff --git a/compiler_wrapper/oldwrapper_test.go b/compiler_wrapper/oldwrapper_test.go deleted file mode 100644 index 4f5b3dc0..00000000 --- a/compiler_wrapper/oldwrapper_test.go +++ /dev/null @@ -1,431 +0,0 @@ -// 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 ( - "bytes" - "fmt" - "io" - "path/filepath" - "strings" - "testing" - "text/template" -) - -func TestCompareToOldPythonWrapperCompilerCommand(t *testing.T) { - withTestContext(t, func(ctx *testContext) { - ctx.cfg.mockOldWrapperCmds = false - ctx.cfg.oldWrapperPath = filepath.Join(ctx.tempDir, "fakewrapper") - - pathSuffix := "" - extraArgs := []string{} - exitCode := 0 - newWrapperExitCode := 0 - - reset := func() { - ctx.stderrBuffer.Reset() - pathSuffix = "" - extraArgs = []string{} - exitCode = 0 - newWrapperExitCode = 0 - } - - ctx.cmdMock = func(cmd *command, stdin io.Reader, stdout io.Writer, stderr io.Writer) error { - writePythonMockWrapper(ctx, &mockWrapperConfig{ - Cmds: []*mockWrapperCmd{ - { - Path: cmd.Path + pathSuffix, - Args: append(cmd.Args, extraArgs...), - ExitCode: exitCode, - }, - }, - }) - if newWrapperExitCode != 0 { - return newExitCodeError(newWrapperExitCode) - } - return nil - } - - // Note: This will cause only the compiler command. - inputCmd := ctx.newCommand(gccX86_64) - - reset() - pathSuffix = "xyz" - stderr := ctx.mustFail(callCompiler(ctx, ctx.cfg, inputCmd)) - if !strings.Contains(stderr, "Index 0: path") { - t.Errorf("expected path difference error. Got: %s", stderr) - } - - reset() - extraArgs = []string{"xyz"} - stderr = ctx.mustFail(callCompiler(ctx, ctx.cfg, inputCmd)) - if !strings.Contains(stderr, "Index 0: args") { - t.Errorf("expected args difference error. Got: %s", stderr) - } - - reset() - exitCode = 1 - stderr = ctx.mustFail(callCompiler(ctx, ctx.cfg, inputCmd)) - if !strings.Contains(stderr, "exit codes differ: old 1, new 0") { - t.Errorf("expected exit code difference error. Got: %s", stderr) - } - - reset() - newWrapperExitCode = 1 - stderr = ctx.mustFail(callCompiler(ctx, ctx.cfg, inputCmd)) - if !strings.Contains(stderr, "exit codes differ: old 0, new 1") { - t.Errorf("expected exit code difference error. Got: %s", stderr) - } - - reset() - ctx.must(callCompiler(ctx, ctx.cfg, inputCmd)) - }) -} - -func TestCompareToOldPythonWrapperNestedCommand(t *testing.T) { - withTestContext(t, func(ctx *testContext) { - ctx.cfg.mockOldWrapperCmds = false - ctx.cfg.oldWrapperPath = filepath.Join(ctx.tempDir, "fakewrapper") - - pathSuffix := "" - extraArgs := []string{} - wrapperCfg := &mockWrapperConfig{} - - ctx.cmdMock = func(cmd *command, stdin io.Reader, stdout io.Writer, stderr io.Writer) error { - isNestedCmd := len(wrapperCfg.Cmds) == 0 - var wrapperCmd *mockWrapperCmd - if isNestedCmd { - wrapperCmd = &mockWrapperCmd{ - Path: cmd.Path + pathSuffix, - Args: append(cmd.Args, extraArgs...), - } - } else { - wrapperCmd = &mockWrapperCmd{ - Path: cmd.Path, - Args: cmd.Args, - } - } - wrapperCfg.Cmds = append(wrapperCfg.Cmds, wrapperCmd) - if !isNestedCmd { - writePythonMockWrapper(ctx, wrapperCfg) - } - return nil - } - - // Note: This will cause a nested command call. - inputCmd := ctx.newCommand(clangX86_64, "-Xclang-path=somedir", mainCc) - - ctx.stderrBuffer.Reset() - wrapperCfg = &mockWrapperConfig{} - pathSuffix = "xyz" - extraArgs = nil - stderr := ctx.mustFail(callCompiler(ctx, ctx.cfg, inputCmd)) - if !strings.Contains(stderr, "Index 0: path") { - t.Errorf("expected path difference error. Got: %s", stderr) - } - if !strings.Contains(stderr, "Index 1: none") { - t.Errorf("expected no difference for cmd index 1. Got: %s", stderr) - } - - ctx.stderrBuffer.Reset() - wrapperCfg = &mockWrapperConfig{} - pathSuffix = "" - extraArgs = []string{"xyz"} - stderr = ctx.mustFail(callCompiler(ctx, ctx.cfg, inputCmd)) - if !strings.Contains(stderr, "Index 0: args") { - t.Errorf("expected args difference error. Got: %s", stderr) - } - if !strings.Contains(stderr, "Index 1: none") { - t.Errorf("expected no difference for cmd index 1. Got: %s", stderr) - } - - wrapperCfg = &mockWrapperConfig{} - pathSuffix = "" - extraArgs = nil - ctx.must(callCompiler(ctx, ctx.cfg, inputCmd)) - }) -} - -func TestCompareToOldShellWrapperCompilerCommand(t *testing.T) { - withTestContext(t, func(ctx *testContext) { - ctx.cfg.mockOldWrapperCmds = false - ctx.cfg.oldWrapperPath = filepath.Join(ctx.tempDir, "fakewrapper") - - pathSuffix := "" - extraArgs := []string{} - exitCode := 0 - newWrapperExitCode := 0 - - reset := func() { - ctx.stderrBuffer.Reset() - pathSuffix = "" - extraArgs = []string{} - exitCode = 0 - newWrapperExitCode = 0 - } - - ctx.cmdMock = func(cmd *command, stdin io.Reader, stdout io.Writer, stderr io.Writer) error { - writeShellMockWrapper(ctx, &mockWrapperConfig{ - Cmds: []*mockWrapperCmd{ - { - Path: cmd.Path + pathSuffix, - Args: append(cmd.Args, extraArgs...), - ExitCode: exitCode, - }, - }, - }) - if newWrapperExitCode != 0 { - return newExitCodeError(newWrapperExitCode) - } - return nil - } - - // Note: This will cause only the compiler command. - inputCmd := ctx.newCommand(gccX86_64) - - reset() - pathSuffix = "xyz" - stderr := ctx.mustFail(callCompiler(ctx, ctx.cfg, inputCmd)) - if !strings.Contains(stderr, "Index 0: path") { - t.Errorf("expected path difference error. Got: %s", stderr) - } - - reset() - extraArgs = []string{"xyz"} - stderr = ctx.mustFail(callCompiler(ctx, ctx.cfg, inputCmd)) - if !strings.Contains(stderr, "Index 0: args") { - t.Errorf("expected args difference error. Got: %s", stderr) - } - - reset() - exitCode = 1 - stderr = ctx.mustFail(callCompiler(ctx, ctx.cfg, inputCmd)) - if !strings.Contains(stderr, "exit codes differ: old 1, new 0") { - t.Errorf("expected exit code difference error. Got: %s", stderr) - } - - reset() - newWrapperExitCode = 1 - stderr = ctx.mustFail(callCompiler(ctx, ctx.cfg, inputCmd)) - if !strings.Contains(stderr, "exit codes differ: old 0, new 1") { - t.Errorf("expected exit code difference error. Got: %s", stderr) - } - - reset() - ctx.must(callCompiler(ctx, ctx.cfg, inputCmd)) - - reset() - ctx.must(callCompiler(ctx, ctx.cfg, ctx.newCommand(gccX86_64, " spaces "))) - }) -} - -func TestCompareToOldWrapperEscapeStdoutAndStderr(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, stdin io.Reader, stdout io.Writer, stderr io.Writer) error { - io.WriteString(stdout, "a\n'b'\\") - io.WriteString(stderr, "c\n'd'\\") - writePythonMockWrapper(ctx, &mockWrapperConfig{ - Cmds: []*mockWrapperCmd{ - { - Path: cmd.Path, - Args: cmd.Args, - }, - }, - }) - return nil - } - - ctx.must(callCompiler(ctx, ctx.cfg, - ctx.newCommand(clangX86_64, mainCc))) - if ctx.stdoutString() != "a\n'b'\\" { - t.Errorf("unexpected stdout. Got: %s", ctx.stdoutString()) - } - if ctx.stderrString() != "c\n'd'\\" { - t.Errorf("unexpected stderr. Got: %s", ctx.stderrString()) - } - }) -} - -func TestCompareToOldWrapperSupportUtf8InStdoutAndStderr(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, stdin io.Reader, stdout io.Writer, stderr io.Writer) error { - io.WriteString(stdout, "©") - io.WriteString(stderr, "®") - writePythonMockWrapper(ctx, &mockWrapperConfig{ - Cmds: []*mockWrapperCmd{ - { - Path: cmd.Path, - Args: cmd.Args, - }, - }, - }) - return nil - } - - ctx.must(callCompiler(ctx, ctx.cfg, - ctx.newCommand(clangX86_64, mainCc))) - if ctx.stdoutString() != "©" { - t.Errorf("unexpected stdout. Got: %s", ctx.stdoutString()) - } - if ctx.stderrString() != "®" { - t.Errorf("unexpected stderr. Got: %s", ctx.stderrString()) - } - }) -} - -func TestCompareToOldPythonWrapperArgumentsWithSpaces(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, stdin io.Reader, stdout io.Writer, stderr io.Writer) error { - writePythonMockWrapper(ctx, &mockWrapperConfig{ - Cmds: []*mockWrapperCmd{ - { - Path: cmd.Path, - Args: cmd.Args, - }, - }, - }) - return nil - } - - ctx.must(callCompiler(ctx, ctx.cfg, - ctx.newCommand(clangX86_64, "a b", "c", mainCc))) - }) -} - -func TestCompareToOldShellWrapperArgumentsWithSpaces(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, stdin io.Reader, stdout io.Writer, stderr io.Writer) error { - writeShellMockWrapper(ctx, &mockWrapperConfig{ - Cmds: []*mockWrapperCmd{ - { - Path: cmd.Path, - Args: cmd.Args, - }, - }, - }) - return nil - } - - ctx.must(callCompiler(ctx, ctx.cfg, - ctx.newCommand(clangX86_64, "a b", "c", mainCc))) - }) -} - -func TestForwardStdinWhenUsingOldWrapper(t *testing.T) { - withTestContext(t, func(ctx *testContext) { - io.WriteString(&ctx.stdinBuffer, "someinput") - ctx.cfg.mockOldWrapperCmds = false - ctx.cfg.oldWrapperPath = filepath.Join(ctx.tempDir, "fakewrapper") - - ctx.cmdMock = func(cmd *command, stdin io.Reader, stdout io.Writer, stderr io.Writer) error { - writeShellMockWrapper(ctx, &mockWrapperConfig{ - Cmds: []*mockWrapperCmd{ - { - Path: cmd.Path, - Args: cmd.Args, - }, - }, - }) - stdinStr := ctx.readAllString(stdin) - if stdinStr != "someinput" { - return fmt.Errorf("unexpected stdin. Got: %s", stdinStr) - } - return nil - } - - ctx.must(callCompiler(ctx, ctx.cfg, - ctx.newCommand(clangX86_64, "-", mainCc))) - }) -} - -func writePythonMockWrapper(ctx *testContext, cfg *mockWrapperConfig) { - const mockTemplate = ` -from __future__ import print_function -import os -import sys -import subprocess - -mockCmds = [{{range .Cmds}} { - 'path': '{{.Path}}', - 'args': [{{range .Args}}'{{.}}',{{end}}], - 'exitcode': {{.ExitCode}}, -},{{end}}] - -def execv_impl(binary, args): - cmd = mockCmds.pop(0) - sys.exit(cmd['exitcode']) -os.execv = execv_impl - -def check_output_impl(args): - cmd = mockCmds.pop(0) - if cmd['exitcode']: - raise subprocess.CalledProcessError(cmd['exitcode']) - return "" -subprocess.check_output = check_output_impl - -def main(): - while len(mockCmds) > 1: - subprocess.check_output([mockCmds[0]['path']] + mockCmds[0]['args']) - - os.execv(mockCmds[0]['path'], [mockCmds[0]['path']] + mockCmds[0]['args']) - -if __name__ == '__main__': - sys.exit(main()) -` - tmpl, err := template.New("mock").Parse(mockTemplate) - if err != nil { - ctx.t.Fatalf("failed to parse old wrapper template. Error: %s", err) - } - buf := bytes.Buffer{} - if err := tmpl.Execute(&buf, cfg); err != nil { - ctx.t.Fatalf("failed to execute the template. Error: %s", err) - } - ctx.writeFile(ctx.cfg.oldWrapperPath, buf.String()) -} - -func writeShellMockWrapper(ctx *testContext, cfg *mockWrapperConfig) { - const mockTemplate = `#!/bin/sh -EXEC=fake_exec - -function fake_exec { - exit {{(index .Cmds 0).ExitCode}} -} - -$EXEC "{{(index .Cmds 0).Path}}"{{range (index .Cmds 0).Args}} "{{.}}"{{end}} -` - tmpl, err := template.New("mock").Parse(mockTemplate) - if err != nil { - ctx.t.Fatalf("failed to parse old wrapper template. Error: %s", err) - } - buf := bytes.Buffer{} - if err := tmpl.Execute(&buf, cfg); err != nil { - ctx.t.Fatalf("failed to execute the template. Error: %s", err) - } - ctx.writeFile(ctx.cfg.oldWrapperPath, buf.String()) -} - -// Note: Fields have to be uppercase so that they can be used with template. -type mockWrapperConfig struct { - Cmds []*mockWrapperCmd -} - -// Note: Fields have to be uppercase so that they can be used with template. -type mockWrapperCmd struct { - Path string - Args []string - ExitCode int -} diff --git a/compiler_wrapper/print_config_flag_test.go b/compiler_wrapper/print_config_flag_test.go index 1b1528e8..63451edb 100644 --- a/compiler_wrapper/print_config_flag_test.go +++ b/compiler_wrapper/print_config_flag_test.go @@ -10,7 +10,7 @@ import ( ) func TestRemovePrintConfigArg(t *testing.T) { - withPrintConfigTestContext(t, func(ctx *testContext) { + withTestContext(t, func(ctx *testContext) { cmd := ctx.must(callCompiler(ctx, ctx.cfg, ctx.newCommand(gccX86_64, "-print-config", mainCc))) if err := verifyArgCount(cmd, 0, "-print-config"); err != nil { t.Error(err) @@ -19,18 +19,10 @@ func TestRemovePrintConfigArg(t *testing.T) { } func TestPrintConfig(t *testing.T) { - withPrintConfigTestContext(t, func(ctx *testContext) { + withTestContext(t, func(ctx *testContext) { ctx.must(callCompiler(ctx, ctx.cfg, ctx.newCommand(gccX86_64, "-print-config", mainCc))) if !strings.Contains(ctx.stderrString(), "wrapper config: main.config{") { t.Errorf("config not printed to stderr. Got: %s", ctx.stderrString()) } }) } - -func withPrintConfigTestContext(t *testing.T, work func(ctx *testContext)) { - withTestContext(t, func(ctx *testContext) { - // Not comparing to old wrapper as the old wrapper doesn't have a print-config command. - ctx.cfg.oldWrapperPath = "" - work(ctx) - }) -} diff --git a/compiler_wrapper/rusage_flag_test.go b/compiler_wrapper/rusage_flag_test.go index 7acba0c8..bd0f980c 100644 --- a/compiler_wrapper/rusage_flag_test.go +++ b/compiler_wrapper/rusage_flag_test.go @@ -164,10 +164,6 @@ 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 that uses fork + wait3 - // to calculate resource usage, and the new wrapper uses the getrusage - // syscall. - ctx.cfg.oldWrapperPath = "" ctx.env = []string{"GETRUSAGE=" + filepath.Join(ctx.tempDir, "rusage.log")} work(ctx) }) diff --git a/compiler_wrapper/testutil_test.go b/compiler_wrapper/testutil_test.go index c0e49fdd..57a68df2 100644 --- a/compiler_wrapper/testutil_test.go +++ b/compiler_wrapper/testutil_test.go @@ -6,7 +6,6 @@ package main import ( "bytes" - "flag" "fmt" "io" "io/ioutil" @@ -18,9 +17,6 @@ import ( "testing" ) -var crosRootDirFlag = flag.String("crosroot", "", "root dir of the chrome os toolchain") -var androidPrebuiltsDirFlag = flag.String("androidprebuilts", "", "prebuilts dir of android") - const mainCc = "main.cc" const clangAndroid = "./clang" const clangX86_64 = "./x86_64-cros-linux-gnu-clang" @@ -107,22 +103,6 @@ func (ctx *testContext) stderrString() string { } func (ctx *testContext) run(cmd *command, stdin io.Reader, stdout io.Writer, stderr io.Writer) error { - // Keep calling the old wrapper when we are comparing the output of the - // old wrapper to the new wrapper. - if isCompareToOldWrapperCmd(cmd) { - // Make sure we have a PATH in the env as the old wrapper needs that. - pathFound := false - for _, arg := range ctx.env { - if arg == "PATH" { - pathFound = true - break - } - } - if !pathFound { - ctx.env = append(ctx.env, "PATH=") - } - return runCmd(ctx, cmd, nil, stdout, stderr) - } ctx.cmdCount++ ctx.lastCmd = cmd if ctx.cmdMock != nil { @@ -157,21 +137,7 @@ func (ctx *testContext) mustFail(exitCode int) string { func (ctx *testContext) updateConfig(cfg *config) { *ctx.cfg = *cfg - ctx.cfg.mockOldWrapperCmds = true ctx.cfg.newWarningsDir = filepath.Join(ctx.tempDir, "fatal_clang_warnings") - if strings.HasPrefix(ctx.cfg.oldWrapperPath, "$CHROOT") { - if *crosRootDirFlag != "" && ctx.cfg.oldWrapperPath != "" { - ctx.cfg.oldWrapperPath = strings.Replace(ctx.cfg.oldWrapperPath, "$CHROOT", *crosRootDirFlag, -1) - } else { - ctx.cfg.oldWrapperPath = "" - } - } else if strings.HasPrefix(ctx.cfg.oldWrapperPath, "$ANDROID_PREBUILTS") { - if *androidPrebuiltsDirFlag != "" && ctx.cfg.oldWrapperPath != "" { - ctx.cfg.oldWrapperPath = strings.Replace(ctx.cfg.oldWrapperPath, "$ANDROID_PREBUILTS", *androidPrebuiltsDirFlag, -1) - } else { - ctx.cfg.oldWrapperPath = "" - } - } } func (ctx *testContext) newCommand(path string, args ...string) *command { @@ -325,12 +291,3 @@ func newExitCodeError(exitCode int) error { tmpCmd := exec.Command("/bin/sh", "-c", fmt.Sprintf("exit %d", exitCode)) return tmpCmd.Run() } - -func isCompareToOldWrapperCmd(cmd *command) bool { - for _, arg := range cmd.Args { - if strings.Contains(arg, compareToOldWrapperFilePattern) { - return true - } - } - return false -} -- cgit v1.2.3