github.com/ranjib/nomad@v0.1.1-0.20160225204057-97751b02f70b/client/driver/executor/executor_test.go (about) 1 package executor 2 3 import ( 4 "io/ioutil" 5 "log" 6 "os" 7 "path/filepath" 8 "strings" 9 "testing" 10 "time" 11 12 "github.com/hashicorp/nomad/client/allocdir" 13 "github.com/hashicorp/nomad/client/driver/env" 14 "github.com/hashicorp/nomad/client/testutil" 15 "github.com/hashicorp/nomad/nomad/mock" 16 "github.com/hashicorp/nomad/nomad/structs" 17 tu "github.com/hashicorp/nomad/testutil" 18 ) 19 20 var ( 21 constraint = &structs.Resources{ 22 CPU: 250, 23 MemoryMB: 256, 24 Networks: []*structs.NetworkResource{ 25 &structs.NetworkResource{ 26 MBits: 50, 27 DynamicPorts: []structs.Port{{Label: "http"}}, 28 }, 29 }, 30 } 31 ) 32 33 func mockAllocDir(t *testing.T) (string, *allocdir.AllocDir) { 34 alloc := mock.Alloc() 35 task := alloc.Job.TaskGroups[0].Tasks[0] 36 37 allocDir := allocdir.NewAllocDir(filepath.Join(os.TempDir(), alloc.ID)) 38 if err := allocDir.Build([]*structs.Task{task}); err != nil { 39 log.Panicf("allocDir.Build() failed: %v", err) 40 } 41 42 return task.Name, allocDir 43 } 44 45 func testExecutorContext(t *testing.T) *ExecutorContext { 46 taskEnv := env.NewTaskEnvironment(mock.Node()) 47 taskName, allocDir := mockAllocDir(t) 48 ctx := &ExecutorContext{ 49 TaskEnv: taskEnv, 50 TaskName: taskName, 51 AllocDir: allocDir, 52 TaskResources: constraint, 53 LogConfig: structs.DefaultLogConfig(), 54 } 55 return ctx 56 } 57 58 func TestExecutor_Start_Invalid(t *testing.T) { 59 invalid := "/bin/foobar" 60 execCmd := ExecCommand{Cmd: invalid, Args: []string{"1"}} 61 ctx := testExecutorContext(t) 62 defer ctx.AllocDir.Destroy() 63 executor := NewExecutor(log.New(os.Stdout, "", log.LstdFlags)) 64 _, err := executor.LaunchCmd(&execCmd, ctx) 65 if err == nil { 66 t.Fatalf("Expected error") 67 } 68 } 69 70 func TestExecutor_Start_Wait_Failure_Code(t *testing.T) { 71 execCmd := ExecCommand{Cmd: "/bin/sleep", Args: []string{"fail"}} 72 ctx := testExecutorContext(t) 73 defer ctx.AllocDir.Destroy() 74 executor := NewExecutor(log.New(os.Stdout, "", log.LstdFlags)) 75 ps, _ := executor.LaunchCmd(&execCmd, ctx) 76 if ps.Pid == 0 { 77 t.Fatalf("expected process to start and have non zero pid") 78 } 79 ps, _ = executor.Wait() 80 if ps.ExitCode < 1 { 81 t.Fatalf("expected exit code to be non zero, actual: %v", ps.ExitCode) 82 } 83 } 84 85 func TestExecutor_Start_Wait(t *testing.T) { 86 execCmd := ExecCommand{Cmd: "/bin/echo", Args: []string{"hello world"}} 87 ctx := testExecutorContext(t) 88 defer ctx.AllocDir.Destroy() 89 executor := NewExecutor(log.New(os.Stdout, "", log.LstdFlags)) 90 ps, err := executor.LaunchCmd(&execCmd, ctx) 91 if err != nil { 92 t.Fatalf("error in launching command: %v", err) 93 } 94 if ps.Pid == 0 { 95 t.Fatalf("expected process to start and have non zero pid") 96 } 97 ps, err = executor.Wait() 98 if err != nil { 99 t.Fatalf("error in waiting for command: %v", err) 100 } 101 102 expected := "hello world" 103 file := filepath.Join(ctx.AllocDir.LogDir(), "web.stdout.0") 104 output, err := ioutil.ReadFile(file) 105 if err != nil { 106 t.Fatalf("Couldn't read file %v", file) 107 } 108 109 act := strings.TrimSpace(string(output)) 110 if act != expected { 111 t.Fatalf("Command output incorrectly: want %v; got %v", expected, act) 112 } 113 } 114 115 func TestExecutor_IsolationAndConstraints(t *testing.T) { 116 testutil.ExecCompatible(t) 117 118 execCmd := ExecCommand{Cmd: "/bin/echo", Args: []string{"hello world"}} 119 ctx := testExecutorContext(t) 120 defer ctx.AllocDir.Destroy() 121 122 ctx.FSIsolation = true 123 ctx.ResourceLimits = true 124 ctx.UnprivilegedUser = true 125 126 executor := NewExecutor(log.New(os.Stdout, "", log.LstdFlags)) 127 ps, err := executor.LaunchCmd(&execCmd, ctx) 128 if err != nil { 129 t.Fatalf("error in launching command: %v", err) 130 } 131 if ps.Pid == 0 { 132 t.Fatalf("expected process to start and have non zero pid") 133 } 134 ps, err = executor.Wait() 135 if err != nil { 136 t.Fatalf("error in waiting for command: %v", err) 137 } 138 139 expected := "hello world" 140 file := filepath.Join(ctx.AllocDir.LogDir(), "web.stdout.0") 141 output, err := ioutil.ReadFile(file) 142 if err != nil { 143 t.Fatalf("Couldn't read file %v", file) 144 } 145 146 act := strings.TrimSpace(string(output)) 147 if act != expected { 148 t.Fatalf("Command output incorrectly: want %v; got %v", expected, act) 149 } 150 } 151 152 func TestExecutor_Start_Kill(t *testing.T) { 153 execCmd := ExecCommand{Cmd: "/bin/sleep", Args: []string{"10 && hello world"}} 154 ctx := testExecutorContext(t) 155 defer ctx.AllocDir.Destroy() 156 executor := NewExecutor(log.New(os.Stdout, "", log.LstdFlags)) 157 ps, err := executor.LaunchCmd(&execCmd, ctx) 158 if err != nil { 159 t.Fatalf("error in launching command: %v", err) 160 } 161 if ps.Pid == 0 { 162 t.Fatalf("expected process to start and have non zero pid") 163 } 164 ps, err = executor.Wait() 165 if err != nil { 166 t.Fatalf("error in waiting for command: %v", err) 167 } 168 169 file := filepath.Join(ctx.AllocDir.LogDir(), "web.stdout.0") 170 time.Sleep(time.Duration(tu.TestMultiplier()*2) * time.Second) 171 172 output, err := ioutil.ReadFile(file) 173 if err != nil { 174 t.Fatalf("Couldn't read file %v", file) 175 } 176 177 expected := "" 178 act := strings.TrimSpace(string(output)) 179 if act != expected { 180 t.Fatalf("Command output incorrectly: want %v; got %v", expected, act) 181 } 182 }