From fd4ec821f944f44da01b5b87f1359647e1170f15 Mon Sep 17 00:00:00 2001 From: Chris Hines Date: Mon, 23 Nov 2015 11:34:37 -0500 Subject: [PATCH 1/5] Factor portable test task out of client/driver/executor. --- client/driver/executor/test_harness_test.go | 102 ++------------------ helper/testtask/testtask.go | 101 +++++++++++++++++++ 2 files changed, 109 insertions(+), 94 deletions(-) create mode 100644 helper/testtask/testtask.go diff --git a/client/driver/executor/test_harness_test.go b/client/driver/executor/test_harness_test.go index 10f16969e081..fa12dd452c94 100644 --- a/client/driver/executor/test_harness_test.go +++ b/client/driver/executor/test_harness_test.go @@ -1,108 +1,22 @@ package executor import ( - "fmt" "io/ioutil" "log" "os" - "os/exec" "path/filepath" - "strings" "testing" "time" "github.com/hashicorp/nomad/client/allocdir" + "github.com/hashicorp/nomad/helper/testtask" "github.com/hashicorp/nomad/nomad/mock" "github.com/hashicorp/nomad/nomad/structs" ) -// testBinary is the path to the running test binary -var testBinary = func() string { - abs, err := filepath.Abs(os.Args[0]) - if err != nil { - return err.Error() - } - - return abs -}() - func TestMain(m *testing.M) { - // The tests in this package recursively execute the test binary produced - // by go test. The TEST_MAIN environment variable controls the recursive - // execution. - switch tm := os.Getenv(testModeEnvVar); tm { - case "": + if !testtask.Run() { os.Exit(m.Run()) - case "app": - appMain() - default: - fmt.Fprintf(os.Stderr, - "Unexpected value for test mode environment variable, %q\n", tm) - os.Exit(1) - } -} - -// setTestAppEnv sets the environement of cmd for a recursive call into -// TestMain. -func setTestAppEnv(cmd *exec.Cmd) { - cmd.Env = append(os.Environ(), fmt.Sprintf("%v=app", testModeEnvVar)) -} - -func appMain() { - if len(os.Args) < 2 { - fmt.Fprintln(os.Stderr, "no command provided") - os.Exit(1) - } - - args := os.Args[1:] - - // popArg removes the first argument from args and returns it. - popArg := func() string { - s := args[0] - args = args[1:] - return s - } - - // execute a sequence of operations from args - for len(args) > 0 { - switch cmd := popArg(); cmd { - - case "sleep": - // sleep : sleep for a duration indicated by the first - // argument - if len(args) < 1 { - fmt.Fprintln(os.Stderr, "expected arg for sleep") - os.Exit(1) - } - dur, err := time.ParseDuration(popArg()) - if err != nil { - fmt.Fprintf(os.Stderr, "could not parse sleep time: %v", err) - os.Exit(1) - } - time.Sleep(dur) - - case "echo": - // echo : write the remaining arguments to stdout each - // separated by a single space and followed by a newline. - fmt.Println(strings.Join(args, " ")) - args = args[:0] - - case "write": - // write : write a message to a file. The first - // argument is the msg. The second argument is the path to the - // target file. - if len(args) < 2 { - fmt.Fprintln(os.Stderr, "expected two args for write") - os.Exit(1) - } - msg := popArg() - file := popArg() - ioutil.WriteFile(file, []byte(msg), 0666) - - default: - fmt.Fprintln(os.Stderr, "unknown command:", cmd) - os.Exit(1) - } } } @@ -139,7 +53,7 @@ func testExecutor(t *testing.T, buildExecutor func() Executor, compatible func(* command := func(name string, args ...string) Executor { e := buildExecutor() SetCommand(e, name, args) - setTestAppEnv(e.Command()) + testtask.SetEnv(e.Command()) return e } @@ -173,7 +87,7 @@ func Executor_Start_Invalid(t *testing.T, command buildExecCommand) { } func Executor_Start_Wait_Failure_Code(t *testing.T, command buildExecCommand) { - e := command(testBinary, "fail") + e := command(testtask.Path(), "fail") if err := e.Limit(constraint); err != nil { log.Panicf("Limit() failed: %v", err) @@ -206,7 +120,7 @@ func Executor_Start_Wait(t *testing.T, command buildExecCommand) { expected := "hello world" file := filepath.Join(allocdir.TaskLocal, "output.txt") absFilePath := filepath.Join(taskDir, file) - e := command(testBinary, "sleep", "1s", "write", expected, file) + e := command(testtask.Path(), "sleep", "1s", "write", expected, file) if err := e.Limit(constraint); err != nil { log.Panicf("Limit() failed: %v", err) @@ -245,7 +159,7 @@ func Executor_Start_Kill(t *testing.T, command buildExecCommand) { } filePath := filepath.Join(taskDir, "output") - e := command(testBinary, "sleep", "1s", "write", "failure", filePath) + e := command(testtask.Path(), "sleep", "1s", "write", "failure", filePath) if err := e.Limit(constraint); err != nil { log.Panicf("Limit() failed: %v", err) @@ -283,7 +197,7 @@ func Executor_Open(t *testing.T, command buildExecCommand, newExecutor func() Ex expected := "hello world" file := filepath.Join(allocdir.TaskLocal, "output.txt") absFilePath := filepath.Join(taskDir, file) - e := command(testBinary, "sleep", "1s", "write", expected, file) + e := command(testtask.Path(), "sleep", "1s", "write", expected, file) if err := e.Limit(constraint); err != nil { log.Panicf("Limit() failed: %v", err) @@ -324,7 +238,7 @@ func Executor_Open(t *testing.T, command buildExecCommand, newExecutor func() Ex func Executor_Open_Invalid(t *testing.T, command buildExecCommand, newExecutor func() Executor) { task, alloc := mockAllocDir(t) - e := command(testBinary, "echo", "foo") + e := command(testtask.Path(), "echo", "foo") if err := e.Limit(constraint); err != nil { log.Panicf("Limit() failed: %v", err) diff --git a/helper/testtask/testtask.go b/helper/testtask/testtask.go new file mode 100644 index 000000000000..60de4047811d --- /dev/null +++ b/helper/testtask/testtask.go @@ -0,0 +1,101 @@ +// Package testtask implements a portable set of commands useful as stand-ins +// for user tasks. +package testtask + +import ( + "fmt" + "io/ioutil" + "os" + "os/exec" + "time" + + "github.com/kardianos/osext" +) + +// Path returns the path to the currently running executable. +func Path() string { + path, err := osext.Executable() + if err != nil { + panic(err) + } + return path +} + +// SetEnv configures the environment of cmd so that Run executes a testtask +// script when called from within cmd when executed. +func SetEnv(cmd *exec.Cmd) { + cmd.Env = append(os.Environ(), "TEST_TASK=execute") +} + +// Run interprets os.Args as a testtask script if the current program was +// launched with an environment configured by SetEnv. It returns false if +// the environment was not set by this package. +func Run() bool { + switch tm := os.Getenv("TEST_TASK"); tm { + case "": + return false + case "execute": + execute() + return true + default: + fmt.Fprintf(os.Stderr, "unexpected value for TEST_TASK, \"%s\"\n", tm) + os.Exit(1) + return true + } +} + +func execute() { + if len(os.Args) < 2 { + fmt.Fprintln(os.Stderr, "no command provided") + os.Exit(1) + } + + args := os.Args[1:] + + // popArg removes the first argument from args and returns it. + popArg := func() string { + s := args[0] + args = args[1:] + return s + } + + // execute a sequence of operations from args + for len(args) > 0 { + switch cmd := popArg(); cmd { + + case "sleep": + // sleep : sleep for a duration indicated by the first + // argument + if len(args) < 1 { + fmt.Fprintln(os.Stderr, "expected arg for sleep") + os.Exit(1) + } + dur, err := time.ParseDuration(popArg()) + if err != nil { + fmt.Fprintf(os.Stderr, "could not parse sleep time: %v", err) + os.Exit(1) + } + time.Sleep(dur) + + case "echo": + // echo : write the msg followed by a newline to stdout. + fmt.Println(popArg()) + + case "write": + // write : write a message to a file. The first + // argument is the msg. The second argument is the path to the + // target file. + if len(args) < 2 { + fmt.Fprintln(os.Stderr, "expected two args for write") + os.Exit(1) + } + msg := popArg() + file := popArg() + ioutil.WriteFile(file, []byte(msg), 0666) + + default: + fmt.Fprintln(os.Stderr, "unknown command:", cmd) + os.Exit(1) + } + } +} From ef7388549d127b1ab76ec4a59dcd6d11e89d574f Mon Sep 17 00:00:00 2001 From: Chris Hines Date: Wed, 25 Nov 2015 14:05:08 -0500 Subject: [PATCH 2/5] Eliminate special case in production code for embedding test binary into chroot. --- client/driver/executor/exec.go | 21 --------------------- client/driver/executor/exec_linux.go | 7 ------- client/driver/executor/exec_linux_test.go | 6 ++++++ 3 files changed, 6 insertions(+), 28 deletions(-) diff --git a/client/driver/executor/exec.go b/client/driver/executor/exec.go index fd812236768e..c514890ef311 100644 --- a/client/driver/executor/exec.go +++ b/client/driver/executor/exec.go @@ -24,7 +24,6 @@ import ( "fmt" "os/exec" "path/filepath" - "strings" "github.com/hashicorp/nomad/client/allocdir" "github.com/hashicorp/nomad/nomad/structs" @@ -34,11 +33,6 @@ import ( var errNoResources = fmt.Errorf("No resources are associated with this task") -// If testModeEnvVar is set in a process's environment variables, the -// LinuxExecutor will detect it and inject the current binary into the chroot. -// This enables using the test binary in tests to provide portability. -var testModeEnvVar = "NOMAD_EXECUTOR_TEST_ONLY_13871827980214" - // Executor is an interface that any platform- or capability-specific exec // wrapper must implement. You should not need to implement a Java executor. // Rather, you would implement a cgroups executor that the Java driver will use. @@ -112,18 +106,3 @@ func OpenId(id string) (Executor, error) { } return executor, nil } - -// isTest returns whether the cmd is a test binary. -func isTest(cmd *exec.Cmd) bool { - if cmd == nil { - return false - } - - for _, env := range cmd.Env { - if strings.HasPrefix(env, testModeEnvVar) { - return true - } - } - - return false -} diff --git a/client/driver/executor/exec_linux.go b/client/driver/executor/exec_linux.go index 4e1753f6106b..43c9270e0642 100644 --- a/client/driver/executor/exec_linux.go +++ b/client/driver/executor/exec_linux.go @@ -252,13 +252,6 @@ func (e *LinuxExecutor) ConfigureTaskDir(taskName string, alloc *allocdir.AllocD return err } - // Embed ourselves if this is a test. This needs to be done so the test - // binary is inside the chroot. - if isTest(&e.cmd) { - bin := e.cmd.Args[0] - alloc.Embed(taskName, map[string]string{bin: bin}) - } - if err := alloc.Embed(taskName, chrootEnv); err != nil { return err } diff --git a/client/driver/executor/exec_linux_test.go b/client/driver/executor/exec_linux_test.go index c0bd2087af95..2c48418e12d1 100644 --- a/client/driver/executor/exec_linux_test.go +++ b/client/driver/executor/exec_linux_test.go @@ -4,8 +4,14 @@ import ( "testing" ctestutil "github.com/hashicorp/nomad/client/testutil" + "github.com/hashicorp/nomad/helper/testtask" ) +func init() { + // Add test binary to chroot during test run. + chrootEnv[testtask.Path()] = testtask.Path() +} + func TestExecutorLinux(t *testing.T) { testExecutor(t, NewLinuxExecutor, ctestutil.ExecCompatible) } From 551104cafe9f30b97ff71383ae570740ff260a8a Mon Sep 17 00:00:00 2001 From: Chris Hines Date: Tue, 24 Nov 2015 15:12:13 -0500 Subject: [PATCH 3/5] Use package testtask in client/driver/spawn tests. --- client/driver/spawn/spawn_test.go | 36 +++++-------------------------- 1 file changed, 5 insertions(+), 31 deletions(-) diff --git a/client/driver/spawn/spawn_test.go b/client/driver/spawn/spawn_test.go index 62323bf8389a..a266ddd66e4b 100644 --- a/client/driver/spawn/spawn_test.go +++ b/client/driver/spawn/spawn_test.go @@ -8,42 +8,16 @@ import ( "strings" "testing" "time" + + "github.com/hashicorp/nomad/helper/testtask" ) func TestMain(m *testing.M) { - switch os.Getenv("TEST_MAIN") { - case "app": - appMain() - default: + if !testtask.Run() { os.Exit(m.Run()) } } -func appMain() { - if len(os.Args) < 2 { - fmt.Fprintln(os.Stderr, "no command provided") - os.Exit(1) - } - switch cmd := os.Args[1]; cmd { - case "echo": - fmt.Println(strings.Join(os.Args[2:], " ")) - case "sleep": - if len(os.Args) != 3 { - fmt.Fprintln(os.Stderr, "expected 3 args") - os.Exit(1) - } - dur, err := time.ParseDuration(os.Args[2]) - if err != nil { - fmt.Fprintf(os.Stderr, "could not parse sleep time: %v", err) - os.Exit(1) - } - time.Sleep(dur) - default: - fmt.Fprintln(os.Stderr, "unknown command:", cmd) - os.Exit(1) - } -} - func TestSpawn_NoCmd(t *testing.T) { t.Parallel() tempFile := tempFileName(t) @@ -355,7 +329,7 @@ func tempFileName(t *testing.T) string { } func testCommand(args ...string) *exec.Cmd { - cmd := exec.Command(os.Args[0], args...) - cmd.Env = append(os.Environ(), "TEST_MAIN=app") + cmd := exec.Command(testtask.Path(), args...) + testtask.SetEnv(cmd) return cmd } From d707adc3ed82f02fb62fec8ccafdca642d7be600 Mon Sep 17 00:00:00 2001 From: Chris Hines Date: Tue, 24 Nov 2015 15:11:26 -0500 Subject: [PATCH 4/5] Use package testtask and httptest.Server to make client/driver tests OS independent. --- client/driver/driver_test.go | 7 +++ client/driver/executor/test_harness_test.go | 2 +- client/driver/raw_exec_test.go | 68 ++++++++++----------- client/driver/spawn/spawn_test.go | 2 +- helper/testtask/testtask.go | 20 ++++-- 5 files changed, 58 insertions(+), 41 deletions(-) diff --git a/client/driver/driver_test.go b/client/driver/driver_test.go index dccd91d7f1bc..c23111462bc6 100644 --- a/client/driver/driver_test.go +++ b/client/driver/driver_test.go @@ -11,6 +11,7 @@ import ( "github.com/hashicorp/nomad/client/allocdir" "github.com/hashicorp/nomad/client/config" + "github.com/hashicorp/nomad/helper/testtask" "github.com/hashicorp/nomad/nomad/structs" ) @@ -30,6 +31,12 @@ func init() { rand.Seed(49875) } +func TestMain(m *testing.M) { + if !testtask.Run() { + os.Exit(m.Run()) + } +} + func testLogger() *log.Logger { return log.New(os.Stderr, "", log.LstdFlags) } diff --git a/client/driver/executor/test_harness_test.go b/client/driver/executor/test_harness_test.go index fa12dd452c94..8e156543ddc1 100644 --- a/client/driver/executor/test_harness_test.go +++ b/client/driver/executor/test_harness_test.go @@ -53,7 +53,7 @@ func testExecutor(t *testing.T, buildExecutor func() Executor, compatible func(* command := func(name string, args ...string) Executor { e := buildExecutor() SetCommand(e, name, args) - testtask.SetEnv(e.Command()) + testtask.SetCmdEnv(e.Command()) return e } diff --git a/client/driver/raw_exec_test.go b/client/driver/raw_exec_test.go index 8b6e0c64975e..0e249d13d127 100644 --- a/client/driver/raw_exec_test.go +++ b/client/driver/raw_exec_test.go @@ -3,14 +3,16 @@ package driver import ( "fmt" "io/ioutil" + "net/http" + "net/http/httptest" "path/filepath" "reflect" - "runtime" "testing" "time" "github.com/hashicorp/nomad/client/config" "github.com/hashicorp/nomad/client/driver/environment" + "github.com/hashicorp/nomad/helper/testtask" "github.com/hashicorp/nomad/nomad/structs" ) @@ -52,11 +54,12 @@ func TestRawExecDriver_StartOpen_Wait(t *testing.T) { task := &structs.Task{ Name: "sleep", Config: map[string]interface{}{ - "command": "/bin/sleep", - "args": []string{"1"}, + "command": testtask.Path(), + "args": []string{"sleep", "1s"}, }, Resources: basicResources, } + testtask.SetTaskEnv(task) driverCtx := testDriverContext(task.Name) ctx := testDriverExecContext(task, driverCtx) defer ctx.AllocDir.Destroy() @@ -88,25 +91,22 @@ func TestRawExecDriver_StartOpen_Wait(t *testing.T) { } func TestRawExecDriver_Start_Artifact_basic(t *testing.T) { - var file, checksum string - switch runtime.GOOS { - case "darwin": - file = "hi_darwin_amd64" - checksum = "md5:d7f2fdb13b36dcb7407721d78926b335" - default: - file = "hi_linux_amd64" - checksum = "md5:a9b14903a8942748e4f8474e11f795d3" - } + path := testtask.Path() + ts := httptest.NewServer(http.FileServer(http.Dir(filepath.Dir(path)))) + defer ts.Close() + file := filepath.Base(path) task := &structs.Task{ Name: "sleep", Config: map[string]interface{}{ - "artifact_source": fmt.Sprintf("https://dl.dropboxusercontent.com/u/47675/jar_thing/%s", file), + "artifact_source": fmt.Sprintf("%s/%s", ts.URL, file), "command": filepath.Join("$NOMAD_TASK_DIR", file), - "checksum": checksum, + "args": []string{"sleep", "1s"}, }, Resources: basicResources, } + testtask.SetTaskEnv(task) + driverCtx := testDriverContext(task.Name) ctx := testDriverExecContext(task, driverCtx) defer ctx.AllocDir.Destroy() @@ -138,26 +138,22 @@ func TestRawExecDriver_Start_Artifact_basic(t *testing.T) { } func TestRawExecDriver_Start_Artifact_expanded(t *testing.T) { - var file string - switch runtime.GOOS { - case "darwin": - file = "hi_darwin_amd64" - default: - file = "hi_linux_amd64" - } + path := testtask.Path() + ts := httptest.NewServer(http.FileServer(http.Dir(filepath.Dir(path)))) + defer ts.Close() + file := filepath.Base(path) task := &structs.Task{ Name: "sleep", Config: map[string]interface{}{ - "artifact_source": fmt.Sprintf("https://dl.dropboxusercontent.com/u/47675/jar_thing/%s", file), - "command": "/bin/bash", - "args": []string{ - "-c", - fmt.Sprintf(`'/bin/sleep 1 && %s'`, filepath.Join("$NOMAD_TASK_DIR", file)), - }, + "artifact_source": fmt.Sprintf("%s/%s", ts.URL, file), + "command": filepath.Join("$NOMAD_TASK_DIR", file), + "args": []string{"sleep", "1s"}, }, Resources: basicResources, } + testtask.SetTaskEnv(task) + driverCtx := testDriverContext(task.Name) ctx := testDriverExecContext(task, driverCtx) defer ctx.AllocDir.Destroy() @@ -192,11 +188,12 @@ func TestRawExecDriver_Start_Wait(t *testing.T) { task := &structs.Task{ Name: "sleep", Config: map[string]interface{}{ - "command": "/bin/sleep", - "args": []string{"1"}, + "command": testtask.Path(), + "args": []string{"sleep", "1s"}, }, Resources: basicResources, } + testtask.SetTaskEnv(task) driverCtx := testDriverContext(task.Name) ctx := testDriverExecContext(task, driverCtx) @@ -231,17 +228,19 @@ func TestRawExecDriver_Start_Wait(t *testing.T) { func TestRawExecDriver_Start_Wait_AllocDir(t *testing.T) { exp := []byte{'w', 'i', 'n'} file := "output.txt" + outPath := fmt.Sprintf(`$%s/%s`, environment.AllocDir, file) task := &structs.Task{ Name: "sleep", Config: map[string]interface{}{ - "command": "/bin/bash", + "command": testtask.Path(), "args": []string{ - "-c", - fmt.Sprintf(`sleep 1; echo -n %s > $%s/%s`, string(exp), environment.AllocDir, file), + "sleep", "1s", + "write", string(exp), outPath, }, }, Resources: basicResources, } + testtask.SetTaskEnv(task) driverCtx := testDriverContext(task.Name) ctx := testDriverExecContext(task, driverCtx) @@ -282,11 +281,12 @@ func TestRawExecDriver_Start_Kill_Wait(t *testing.T) { task := &structs.Task{ Name: "sleep", Config: map[string]interface{}{ - "command": "/bin/sleep", - "args": []string{"1"}, + "command": testtask.Path(), + "args": []string{"sleep", "1s"}, }, Resources: basicResources, } + testtask.SetTaskEnv(task) driverCtx := testDriverContext(task.Name) ctx := testDriverExecContext(task, driverCtx) diff --git a/client/driver/spawn/spawn_test.go b/client/driver/spawn/spawn_test.go index a266ddd66e4b..f231a335c6bf 100644 --- a/client/driver/spawn/spawn_test.go +++ b/client/driver/spawn/spawn_test.go @@ -330,6 +330,6 @@ func tempFileName(t *testing.T) string { func testCommand(args ...string) *exec.Cmd { cmd := exec.Command(testtask.Path(), args...) - testtask.SetEnv(cmd) + testtask.SetCmdEnv(cmd) return cmd } diff --git a/helper/testtask/testtask.go b/helper/testtask/testtask.go index 60de4047811d..9aea5bb7aaf6 100644 --- a/helper/testtask/testtask.go +++ b/helper/testtask/testtask.go @@ -9,6 +9,7 @@ import ( "os/exec" "time" + "github.com/hashicorp/nomad/nomad/structs" "github.com/kardianos/osext" ) @@ -21,15 +22,24 @@ func Path() string { return path } -// SetEnv configures the environment of cmd so that Run executes a testtask -// script when called from within cmd when executed. -func SetEnv(cmd *exec.Cmd) { +// SetCmdEnv configures the environment of cmd so that Run executes a testtask +// script when called from within cmd. +func SetCmdEnv(cmd *exec.Cmd) { cmd.Env = append(os.Environ(), "TEST_TASK=execute") } +// SetTaskEnv configures the environment of t so that Run executes a testtask +// script when called from within t. +func SetTaskEnv(t *structs.Task) { + if t.Env == nil { + t.Env = map[string]string{} + } + t.Env["TEST_TASK"] = "execute" +} + // Run interprets os.Args as a testtask script if the current program was -// launched with an environment configured by SetEnv. It returns false if -// the environment was not set by this package. +// launched with an environment configured by SetCmdEnv or SetTaskEnv. It +// returns false if the environment was not set by this package. func Run() bool { switch tm := os.Getenv("TEST_TASK"); tm { case "": From ffda9d71d464adc6414734c8728c76a395bb2eb0 Mon Sep 17 00:00:00 2001 From: Chris Hines Date: Tue, 24 Nov 2015 15:12:31 -0500 Subject: [PATCH 5/5] Speed up tests by allowing parallel execution. --- client/driver/docker_test.go | 13 +++++++++++++ client/driver/driver_test.go | 3 +++ client/driver/exec_test.go | 7 +++++++ client/driver/executor/exec_basic_test.go | 1 + client/driver/executor/exec_linux_test.go | 1 + client/driver/java_test.go | 4 ++++ client/driver/qemu_test.go | 3 +++ client/driver/raw_exec_test.go | 7 +++++++ 8 files changed, 39 insertions(+) diff --git a/client/driver/docker_test.go b/client/driver/docker_test.go index 40ce7597065b..2213ecaefc69 100644 --- a/client/driver/docker_test.go +++ b/client/driver/docker_test.go @@ -119,6 +119,7 @@ func dockerSetup(t *testing.T, task *structs.Task) (*docker.Client, DriverHandle } func TestDockerDriver_Handle(t *testing.T) { + t.Parallel() h := &DockerHandle{ imageID: "imageid", containerID: "containerid", @@ -135,6 +136,7 @@ func TestDockerDriver_Handle(t *testing.T) { // This test should always pass, even if docker daemon is not available func TestDockerDriver_Fingerprint(t *testing.T) { + t.Parallel() d := NewDockerDriver(testDockerDriverContext("")) node := &structs.Node{ Attributes: make(map[string]string), @@ -153,6 +155,7 @@ func TestDockerDriver_Fingerprint(t *testing.T) { } func TestDockerDriver_StartOpen_Wait(t *testing.T) { + t.Parallel() if !dockerIsConnected(t) { t.SkipNow() } @@ -190,6 +193,7 @@ func TestDockerDriver_StartOpen_Wait(t *testing.T) { } func TestDockerDriver_Start_Wait(t *testing.T) { + t.Parallel() task := &structs.Task{ Name: "redis-demo", Config: map[string]interface{}{ @@ -223,6 +227,7 @@ func TestDockerDriver_Start_Wait(t *testing.T) { } func TestDockerDriver_Start_Wait_AllocDir(t *testing.T) { + t.Parallel() // This test requires that the alloc dir be mounted into docker as a volume. // Because this cannot happen when docker is run remotely, e.g. when running // docker in a VM, we skip this when we detect Docker is being run remotely. @@ -285,6 +290,7 @@ func TestDockerDriver_Start_Wait_AllocDir(t *testing.T) { } func TestDockerDriver_Start_Kill_Wait(t *testing.T) { + t.Parallel() task := &structs.Task{ Name: "redis-demo", Config: map[string]interface{}{ @@ -317,6 +323,7 @@ func TestDockerDriver_Start_Kill_Wait(t *testing.T) { } func TestDocker_StartN(t *testing.T) { + t.Parallel() if !dockerIsConnected(t) { t.SkipNow() } @@ -371,6 +378,7 @@ func TestDocker_StartN(t *testing.T) { } func TestDocker_StartNVersions(t *testing.T) { + t.Parallel() if !dockerIsConnected(t) { t.SkipNow() } @@ -428,6 +436,7 @@ func TestDocker_StartNVersions(t *testing.T) { } func TestDockerHostNet(t *testing.T) { + t.Parallel() expected := "host" task := &structs.Task{ @@ -457,6 +466,7 @@ func TestDockerHostNet(t *testing.T) { } func TestDockerLabels(t *testing.T) { + t.Parallel() task := dockerTask() task.Config["labels"] = []map[string]string{ map[string]string{ @@ -483,6 +493,7 @@ func TestDockerLabels(t *testing.T) { } func TestDockerDNS(t *testing.T) { + t.Parallel() task := dockerTask() task.Config["dns_servers"] = []string{"8.8.8.8", "8.8.4.4"} task.Config["dns_search_domains"] = []string{"example.com", "example.org", "example.net"} @@ -514,6 +525,7 @@ func inSlice(needle string, haystack []string) bool { } func TestDockerPortsNoMap(t *testing.T) { + t.Parallel() task := dockerTask() client, handle, cleanup := dockerSetup(t, task) @@ -564,6 +576,7 @@ func TestDockerPortsNoMap(t *testing.T) { } func TestDockerPortsMapping(t *testing.T) { + t.Parallel() task := dockerTask() task.Config["port_map"] = []map[string]string{ map[string]string{ diff --git a/client/driver/driver_test.go b/client/driver/driver_test.go index c23111462bc6..e35c5c5ad058 100644 --- a/client/driver/driver_test.go +++ b/client/driver/driver_test.go @@ -61,6 +61,7 @@ func testDriverExecContext(task *structs.Task, driverCtx *DriverContext) *ExecCo } func TestDriver_TaskEnvironmentVariables(t *testing.T) { + t.Parallel() ctx := &ExecContext{} task := &structs.Task{ Env: map[string]string{ @@ -108,6 +109,7 @@ func TestDriver_TaskEnvironmentVariables(t *testing.T) { } func TestMapMergeStrInt(t *testing.T) { + t.Parallel() a := map[string]int{ "cakes": 5, "cookies": 3, @@ -132,6 +134,7 @@ func TestMapMergeStrInt(t *testing.T) { } func TestMapMergeStrStr(t *testing.T) { + t.Parallel() a := map[string]string{ "cake": "chocolate", "cookie": "caramel", diff --git a/client/driver/exec_test.go b/client/driver/exec_test.go index f5470074a395..66795781fee1 100644 --- a/client/driver/exec_test.go +++ b/client/driver/exec_test.go @@ -16,6 +16,7 @@ import ( ) func TestExecDriver_Fingerprint(t *testing.T) { + t.Parallel() ctestutils.ExecCompatible(t) d := NewExecDriver(testDriverContext("")) node := &structs.Node{ @@ -34,6 +35,7 @@ func TestExecDriver_Fingerprint(t *testing.T) { } func TestExecDriver_StartOpen_Wait(t *testing.T) { + t.Parallel() ctestutils.ExecCompatible(t) task := &structs.Task{ Name: "sleep", @@ -68,6 +70,7 @@ func TestExecDriver_StartOpen_Wait(t *testing.T) { } func TestExecDriver_Start_Wait(t *testing.T) { + t.Parallel() ctestutils.ExecCompatible(t) task := &structs.Task{ Name: "sleep", @@ -109,6 +112,7 @@ func TestExecDriver_Start_Wait(t *testing.T) { } func TestExecDriver_Start_Artifact_basic(t *testing.T) { + t.Parallel() ctestutils.ExecCompatible(t) file := "hi_linux_amd64" checksum := "sha256:6f99b4c5184726e601ecb062500aeb9537862434dfe1898dbe5c68d9f50c179c" @@ -153,6 +157,7 @@ func TestExecDriver_Start_Artifact_basic(t *testing.T) { } func TestExecDriver_Start_Artifact_expanded(t *testing.T) { + t.Parallel() ctestutils.ExecCompatible(t) file := "hi_linux_amd64" @@ -199,6 +204,7 @@ func TestExecDriver_Start_Artifact_expanded(t *testing.T) { } } func TestExecDriver_Start_Wait_AllocDir(t *testing.T) { + t.Parallel() ctestutils.ExecCompatible(t) exp := []byte{'w', 'i', 'n'} @@ -251,6 +257,7 @@ func TestExecDriver_Start_Wait_AllocDir(t *testing.T) { } func TestExecDriver_Start_Kill_Wait(t *testing.T) { + t.Parallel() ctestutils.ExecCompatible(t) task := &structs.Task{ Name: "sleep", diff --git a/client/driver/executor/exec_basic_test.go b/client/driver/executor/exec_basic_test.go index d9eed49f9776..1a829b95db7c 100644 --- a/client/driver/executor/exec_basic_test.go +++ b/client/driver/executor/exec_basic_test.go @@ -3,5 +3,6 @@ package executor import "testing" func TestExecutorBasic(t *testing.T) { + t.Parallel() testExecutor(t, NewBasicExecutor, nil) } diff --git a/client/driver/executor/exec_linux_test.go b/client/driver/executor/exec_linux_test.go index 2c48418e12d1..6cc2d104cd86 100644 --- a/client/driver/executor/exec_linux_test.go +++ b/client/driver/executor/exec_linux_test.go @@ -13,5 +13,6 @@ func init() { } func TestExecutorLinux(t *testing.T) { + t.Parallel() testExecutor(t, NewLinuxExecutor, ctestutil.ExecCompatible) } diff --git a/client/driver/java_test.go b/client/driver/java_test.go index af6e44d6d8d2..5fa47320b4bd 100644 --- a/client/driver/java_test.go +++ b/client/driver/java_test.go @@ -19,6 +19,7 @@ func javaLocated() bool { // The fingerprinter test should always pass, even if Java is not installed. func TestJavaDriver_Fingerprint(t *testing.T) { + t.Parallel() ctestutils.JavaCompatible(t) d := NewJavaDriver(testDriverContext("")) node := &structs.Node{ @@ -42,6 +43,7 @@ func TestJavaDriver_Fingerprint(t *testing.T) { } func TestJavaDriver_StartOpen_Wait(t *testing.T) { + t.Parallel() if !javaLocated() { t.Skip("Java not found; skipping") } @@ -88,6 +90,7 @@ func TestJavaDriver_StartOpen_Wait(t *testing.T) { } func TestJavaDriver_Start_Wait(t *testing.T) { + t.Parallel() if !javaLocated() { t.Skip("Java not found; skipping") } @@ -134,6 +137,7 @@ func TestJavaDriver_Start_Wait(t *testing.T) { } func TestJavaDriver_Start_Kill_Wait(t *testing.T) { + t.Parallel() if !javaLocated() { t.Skip("Java not found; skipping") } diff --git a/client/driver/qemu_test.go b/client/driver/qemu_test.go index cecca4357f10..65846203bc6a 100644 --- a/client/driver/qemu_test.go +++ b/client/driver/qemu_test.go @@ -12,6 +12,7 @@ import ( // The fingerprinter test should always pass, even if QEMU is not installed. func TestQemuDriver_Fingerprint(t *testing.T) { + t.Parallel() ctestutils.QemuCompatible(t) d := NewQemuDriver(testDriverContext("")) node := &structs.Node{ @@ -33,6 +34,7 @@ func TestQemuDriver_Fingerprint(t *testing.T) { } func TestQemuDriver_StartOpen_Wait(t *testing.T) { + t.Parallel() ctestutils.QemuCompatible(t) // TODO: use test server to load from a fixture task := &structs.Task{ @@ -86,6 +88,7 @@ func TestQemuDriver_StartOpen_Wait(t *testing.T) { } func TestQemuDriver_RequiresMemory(t *testing.T) { + t.Parallel() ctestutils.QemuCompatible(t) // TODO: use test server to load from a fixture task := &structs.Task{ diff --git a/client/driver/raw_exec_test.go b/client/driver/raw_exec_test.go index 0e249d13d127..8d656c9b085c 100644 --- a/client/driver/raw_exec_test.go +++ b/client/driver/raw_exec_test.go @@ -17,6 +17,7 @@ import ( ) func TestRawExecDriver_Fingerprint(t *testing.T) { + t.Parallel() d := NewRawExecDriver(testDriverContext("")) node := &structs.Node{ Attributes: make(map[string]string), @@ -51,6 +52,7 @@ func TestRawExecDriver_Fingerprint(t *testing.T) { } func TestRawExecDriver_StartOpen_Wait(t *testing.T) { + t.Parallel() task := &structs.Task{ Name: "sleep", Config: map[string]interface{}{ @@ -91,6 +93,7 @@ func TestRawExecDriver_StartOpen_Wait(t *testing.T) { } func TestRawExecDriver_Start_Artifact_basic(t *testing.T) { + t.Parallel() path := testtask.Path() ts := httptest.NewServer(http.FileServer(http.Dir(filepath.Dir(path)))) defer ts.Close() @@ -138,6 +141,7 @@ func TestRawExecDriver_Start_Artifact_basic(t *testing.T) { } func TestRawExecDriver_Start_Artifact_expanded(t *testing.T) { + t.Parallel() path := testtask.Path() ts := httptest.NewServer(http.FileServer(http.Dir(filepath.Dir(path)))) defer ts.Close() @@ -185,6 +189,7 @@ func TestRawExecDriver_Start_Artifact_expanded(t *testing.T) { } func TestRawExecDriver_Start_Wait(t *testing.T) { + t.Parallel() task := &structs.Task{ Name: "sleep", Config: map[string]interface{}{ @@ -226,6 +231,7 @@ func TestRawExecDriver_Start_Wait(t *testing.T) { } func TestRawExecDriver_Start_Wait_AllocDir(t *testing.T) { + t.Parallel() exp := []byte{'w', 'i', 'n'} file := "output.txt" outPath := fmt.Sprintf(`$%s/%s`, environment.AllocDir, file) @@ -278,6 +284,7 @@ func TestRawExecDriver_Start_Wait_AllocDir(t *testing.T) { } func TestRawExecDriver_Start_Kill_Wait(t *testing.T) { + t.Parallel() task := &structs.Task{ Name: "sleep", Config: map[string]interface{}{