aboutsummaryrefslogtreecommitdiff
path: root/compiler_wrapper/env_test.go
diff options
context:
space:
mode:
authorTobias Bosch <tbosch@google.com>2019-09-12 15:19:57 -0700
committerTobias Bosch <tbosch@google.com>2019-09-13 18:57:43 +0000
commit3b8531f0c0739003a208b7beb002d1058656a962 (patch)
tree1f53081777ba01d9ecd1b31bd2ee76285a69d91c /compiler_wrapper/env_test.go
parentc183559d9c40285129d08a1146cfde0982b6c356 (diff)
downloadtoolchain-utils-3b8531f0c0739003a208b7beb002d1058656a962.tar.gz
Allow to remove env variables.
Previously, we only supported setting env variables to empty, but not to remove it. This lead to the case that we never removed the CCACHE_DISABLE env variable, which kept the ccache disabled, and caused a performance regression compared to the old wrapper as the new wrapper didn't use the ccache in this case. This cl also adds tests for the real exec and run commands to prevent regressions in these cases. BUG=chromium:773875 TEST=new unit tests TEST=performance analysis for TEST=emerge-veyron_jerry --nodeps chromeos-kernel-4_19 Change-Id: I5ca88ba8d7b05c3e12e292465fcd4ff9925b0344 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/toolchain-utils/+/1802159 Tested-by: Tobias Bosch <tbosch@google.com> Reviewed-by: George Burgess <gbiv@chromium.org>
Diffstat (limited to 'compiler_wrapper/env_test.go')
-rw-r--r--compiler_wrapper/env_test.go215
1 files changed, 215 insertions, 0 deletions
diff --git a/compiler_wrapper/env_test.go b/compiler_wrapper/env_test.go
new file mode 100644
index 00000000..05d7d136
--- /dev/null
+++ b/compiler_wrapper/env_test.go
@@ -0,0 +1,215 @@
+// 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"
+ "flag"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "strings"
+ "testing"
+)
+
+// Attention: The tests in this file execute the test binary again with the `-run` flag.
+// This is needed as they want to test an `exec`, which terminates the test process.
+var internalexececho = flag.Bool("internalexececho", false, "internal flag used for tests that exec")
+
+func TestProcessEnvExecPathAndArgs(t *testing.T) {
+ withTestContext(t, func(ctx *testContext) {
+ if *internalexececho {
+ execEcho(ctx, &command{
+ Path: "some_binary",
+ Args: []string{"arg1", "arg2"},
+ })
+ return
+ }
+ logLines := forkAndReadEcho(ctx)
+ if !strings.HasSuffix(logLines[0], "/some_binary arg1 arg2") {
+ t.Errorf("incorrect path or args: %s", logLines[0])
+ }
+ })
+}
+
+func TestProcessEnvExecAddEnv(t *testing.T) {
+ withTestContext(t, func(ctx *testContext) {
+ if *internalexececho {
+ execEcho(ctx, &command{
+ Path: "some_binary",
+ EnvUpdates: []string{"ABC=xyz"},
+ })
+ return
+ }
+
+ logLines := forkAndReadEcho(ctx)
+ for _, ll := range logLines {
+ if ll == "ABC=xyz" {
+ return
+ }
+ }
+ t.Errorf("could not find new env variable: %s", logLines)
+ })
+}
+
+func TestProcessEnvExecUpdateEnv(t *testing.T) {
+ if os.Getenv("PATH") == "" {
+ t.Fatal("no PATH environment variable found!")
+ }
+ withTestContext(t, func(ctx *testContext) {
+ if *internalexececho {
+ execEcho(ctx, &command{
+ Path: "some_binary",
+ EnvUpdates: []string{"PATH=xyz"},
+ })
+ return
+ }
+ logLines := forkAndReadEcho(ctx)
+ for _, ll := range logLines {
+ if ll == "PATH=xyz" {
+ return
+ }
+ }
+ t.Errorf("could not find updated env variable: %s", logLines)
+ })
+}
+
+func TestProcessEnvExecDeleteEnv(t *testing.T) {
+ if os.Getenv("PATH") == "" {
+ t.Fatal("no PATH environment variable found!")
+ }
+ withTestContext(t, func(ctx *testContext) {
+ if *internalexececho {
+ execEcho(ctx, &command{
+ Path: "some_binary",
+ EnvUpdates: []string{"PATH="},
+ })
+ return
+ }
+ logLines := forkAndReadEcho(ctx)
+ for _, ll := range logLines {
+ if strings.HasPrefix(ll, "PATH=") {
+ t.Errorf("path env was not removed: %s", ll)
+ }
+ }
+ })
+}
+
+func TestProcessEnvRunCmdPathAndArgs(t *testing.T) {
+ withTestContext(t, func(ctx *testContext) {
+ cmd := &command{
+ Path: "some_binary",
+ Args: []string{"arg1", "arg2"},
+ }
+ logLines := runAndEcho(ctx, cmd)
+ if !strings.HasSuffix(logLines[0], "/some_binary arg1 arg2") {
+ t.Errorf("incorrect path or args: %s", logLines[0])
+ }
+ })
+}
+
+func TestProcessEnvRunCmdAddEnv(t *testing.T) {
+ withTestContext(t, func(ctx *testContext) {
+ cmd := &command{
+ Path: "some_binary",
+ EnvUpdates: []string{"ABC=xyz"},
+ }
+ logLines := runAndEcho(ctx, cmd)
+ for _, ll := range logLines {
+ if ll == "ABC=xyz" {
+ return
+ }
+ }
+ t.Errorf("could not find new env variable: %s", logLines)
+ })
+}
+
+func TestProcessEnvRunCmdUpdateEnv(t *testing.T) {
+ withTestContext(t, func(ctx *testContext) {
+ if os.Getenv("PATH") == "" {
+ t.Fatal("no PATH environment variable found!")
+ }
+ cmd := &command{
+ Path: "some_binary",
+ EnvUpdates: []string{"PATH=xyz"},
+ }
+ logLines := runAndEcho(ctx, cmd)
+ for _, ll := range logLines {
+ if ll == "PATH=xyz" {
+ return
+ }
+ }
+ t.Errorf("could not find updated env variable: %s", logLines)
+ })
+}
+
+func TestProcessEnvRunCmdDeleteEnv(t *testing.T) {
+ withTestContext(t, func(ctx *testContext) {
+ if os.Getenv("PATH") == "" {
+ t.Fatal("no PATH environment variable found!")
+ }
+ cmd := &command{
+ Path: "some_binary",
+ EnvUpdates: []string{"PATH="},
+ }
+ logLines := runAndEcho(ctx, cmd)
+ for _, ll := range logLines {
+ if strings.HasPrefix(ll, "PATH=") {
+ t.Errorf("path env was not removed: %s", ll)
+ }
+ }
+ })
+}
+
+func execEcho(ctx *testContext, cmd *command) {
+ env := &processEnv{}
+ err := env.exec(createEcho(ctx, cmd))
+ if err != nil {
+ os.Stderr.WriteString(err.Error())
+ }
+ os.Exit(1)
+}
+
+func forkAndReadEcho(ctx *testContext) []string {
+ testBin, err := os.Executable()
+ if err != nil {
+ ctx.t.Fatalf("unable to read the executable: %s", err)
+ }
+
+ subCmd := exec.Command(testBin, "-internalexececho", "-test.run="+ctx.t.Name())
+ output, err := subCmd.CombinedOutput()
+ if err != nil {
+ ctx.t.Fatalf("error calling test binary again for exec: %s", err)
+ }
+ return strings.Split(string(output), "\n")
+}
+
+func runAndEcho(ctx *testContext, cmd *command) []string {
+ env, err := newProcessEnv()
+ if err != nil {
+ ctx.t.Fatalf("creation of process env failed: %s", err)
+ }
+ buffer := bytes.Buffer{}
+ if err := env.run(createEcho(ctx, cmd), nil, &buffer, &buffer); err != nil {
+ ctx.t.Fatalf("run failed: %s", err)
+ }
+ return strings.Split(buffer.String(), "\n")
+}
+
+func createEcho(ctx *testContext, cmd *command) *command {
+ content := `
+/usr/bin/echo "$0" "$@"
+/usr/bin/env
+`
+ fullPath := filepath.Join(ctx.tempDir, cmd.Path)
+ ctx.writeFile(fullPath, content)
+ // 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
+ return &command{
+ Path: "bash",
+ Args: append([]string{fullPath}, cmd.Args...),
+ EnvUpdates: cmd.EnvUpdates,
+ }
+}