216 lines
5.2 KiB
Go
216 lines
5.2 KiB
Go
// 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 := `
|
|
/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,
|
|
}
|
|
}
|