github.com/kardianos/nomad@v0.1.3-0.20151022182107-b13df73ee850/client/alloc_runner_test.go (about) 1 package client 2 3 import ( 4 "os" 5 "testing" 6 "time" 7 8 "github.com/hashicorp/nomad/nomad/mock" 9 "github.com/hashicorp/nomad/nomad/structs" 10 "github.com/hashicorp/nomad/testutil" 11 12 ctestutil "github.com/hashicorp/nomad/client/testutil" 13 ) 14 15 type MockAllocStateUpdater struct { 16 Count int 17 Allocs []*structs.Allocation 18 Err error 19 } 20 21 func (m *MockAllocStateUpdater) Update(alloc *structs.Allocation) error { 22 m.Count += 1 23 m.Allocs = append(m.Allocs, alloc) 24 return m.Err 25 } 26 27 func testAllocRunner() (*MockAllocStateUpdater, *AllocRunner) { 28 logger := testLogger() 29 conf := DefaultConfig() 30 conf.StateDir = os.TempDir() 31 conf.AllocDir = os.TempDir() 32 upd := &MockAllocStateUpdater{} 33 alloc := mock.Alloc() 34 ar := NewAllocRunner(logger, conf, upd.Update, alloc) 35 return upd, ar 36 } 37 38 func TestAllocRunner_SimpleRun(t *testing.T) { 39 ctestutil.ExecCompatible(t) 40 upd, ar := testAllocRunner() 41 go ar.Run() 42 defer ar.Destroy() 43 44 testutil.WaitForResult(func() (bool, error) { 45 if upd.Count == 0 { 46 return false, nil 47 } 48 last := upd.Allocs[upd.Count-1] 49 return last.ClientStatus == structs.AllocClientStatusDead, nil 50 }, func(err error) { 51 t.Fatalf("err: %v", err) 52 }) 53 } 54 55 func TestAllocRunner_Destroy(t *testing.T) { 56 ctestutil.ExecCompatible(t) 57 upd, ar := testAllocRunner() 58 59 // Ensure task takes some time 60 task := ar.alloc.Job.TaskGroups[0].Tasks[0] 61 task.Config["command"] = "/bin/sleep" 62 task.Config["args"] = "10" 63 go ar.Run() 64 start := time.Now() 65 66 // Begin the tear down 67 go func() { 68 time.Sleep(100 * time.Millisecond) 69 ar.Destroy() 70 }() 71 72 testutil.WaitForResult(func() (bool, error) { 73 if upd.Count == 0 { 74 return false, nil 75 } 76 last := upd.Allocs[upd.Count-1] 77 return last.ClientStatus == structs.AllocClientStatusDead, nil 78 }, func(err error) { 79 t.Fatalf("err: %v %#v %#v", err, upd.Allocs[0], ar.taskStatus) 80 }) 81 82 if time.Since(start) > time.Second { 83 t.Fatalf("took too long to terminate") 84 } 85 } 86 87 func TestAllocRunner_Update(t *testing.T) { 88 ctestutil.ExecCompatible(t) 89 upd, ar := testAllocRunner() 90 91 // Ensure task takes some time 92 task := ar.alloc.Job.TaskGroups[0].Tasks[0] 93 task.Config["command"] = "/bin/sleep" 94 task.Config["args"] = "10" 95 go ar.Run() 96 defer ar.Destroy() 97 start := time.Now() 98 99 // Update the alloc definition 100 newAlloc := new(structs.Allocation) 101 *newAlloc = *ar.alloc 102 newAlloc.DesiredStatus = structs.AllocDesiredStatusStop 103 ar.Update(newAlloc) 104 105 testutil.WaitForResult(func() (bool, error) { 106 if upd.Count == 0 { 107 return false, nil 108 } 109 last := upd.Allocs[upd.Count-1] 110 return last.ClientStatus == structs.AllocClientStatusDead, nil 111 }, func(err error) { 112 t.Fatalf("err: %v %#v %#v", err, upd.Allocs[0], ar.taskStatus) 113 }) 114 115 if time.Since(start) > time.Second { 116 t.Fatalf("took too long to terminate") 117 } 118 } 119 120 /* 121 TODO: This test is disabled til a follow-up api changes the restore state interface. 122 The driver/executor interface will be changed from Open to Cleanup, in which 123 clean-up tears down previous allocs. 124 125 func TestAllocRunner_SaveRestoreState(t *testing.T) { 126 upd, ar := testAllocRunner() 127 128 // Ensure task takes some time 129 task := ar.alloc.Job.TaskGroups[0].Tasks[0] 130 task.Config["command"] = "/bin/sleep" 131 task.Config["args"] = "10" 132 go ar.Run() 133 defer ar.Destroy() 134 135 // Snapshot state 136 time.Sleep(200 * time.Millisecond) 137 err := ar.SaveState() 138 if err != nil { 139 t.Fatalf("err: %v", err) 140 } 141 142 // Create a new alloc runner 143 ar2 := NewAllocRunner(ar.logger, ar.config, upd.Update, 144 &structs.Allocation{ID: ar.alloc.ID}) 145 err = ar2.RestoreState() 146 if err != nil { 147 t.Fatalf("err: %v", err) 148 } 149 go ar2.Run() 150 defer ar2.Destroy() 151 152 // Destroy and wait 153 ar2.Destroy() 154 start := time.Now() 155 156 testutil.WaitForResult(func() (bool, error) { 157 if upd.Count == 0 { 158 return false, nil 159 } 160 last := upd.Allocs[upd.Count-1] 161 return last.ClientStatus == structs.AllocClientStatusDead, nil 162 }, func(err error) { 163 t.Fatalf("err: %v %#v %#v", err, upd.Allocs[0], ar.taskStatus) 164 }) 165 166 if time.Since(start) > time.Second { 167 t.Fatalf("took too long to terminate") 168 } 169 } 170 */