diff options
Diffstat (limited to 'compiler_wrapper/env_test.go')
-rw-r--r-- | compiler_wrapper/env_test.go | 215 |
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, + } +} |