1package main 2 3import ( 4 "context" 5 "math/rand" 6 "strconv" 7 "testing" 8 "time" 9 10 "github.com/containerd/containerd/errdefs" 11) 12 13func setupTestHcsTask(t *testing.T) (*hcsTask, *testShimExec, *testShimExec) { 14 initExec := newTestShimExec(t.Name(), t.Name(), int(rand.Int31())) 15 lt := &hcsTask{ 16 events: newFakePublisher(), 17 id: t.Name(), 18 init: initExec, 19 closed: make(chan struct{}), 20 } 21 secondExecID := strconv.Itoa(rand.Int()) 22 secondExec := newTestShimExec(t.Name(), secondExecID, int(rand.Int31())) 23 lt.execs.Store(secondExecID, secondExec) 24 return lt, initExec, secondExec 25} 26 27func Test_hcsTask_ID(t *testing.T) { 28 lt, _, _ := setupTestHcsTask(t) 29 30 if lt.ID() != t.Name() { 31 t.Fatalf("expect ID: '%s', got: '%s'", t.Name(), lt.ID()) 32 } 33} 34 35func Test_hcsTask_GetExec_Empty_Success(t *testing.T) { 36 lt, i, _ := setupTestHcsTask(t) 37 38 e, err := lt.GetExec("") 39 if err != nil { 40 t.Fatalf("should not have failed with error: %v", err) 41 } 42 if i != e { 43 t.Fatal("should of returned the init exec on empty") 44 } 45} 46 47func Test_hcsTask_GetExec_UnknownExecID_Error(t *testing.T) { 48 lt, _, _ := setupTestHcsTask(t) 49 50 e, err := lt.GetExec("shouldnotmatch") 51 52 verifyExpectedError(t, e, err, errdefs.ErrNotFound) 53} 54 55func Test_hcsTask_GetExec_2ndID_Success(t *testing.T) { 56 lt, _, second := setupTestHcsTask(t) 57 58 e, err := lt.GetExec(second.id) 59 if err != nil { 60 t.Fatalf("should not have failed with error: %v", err) 61 } 62 if second != e { 63 t.Fatal("should of returned the second exec") 64 } 65} 66 67func Test_hcsTask_KillExec_UnknownExecID_Error(t *testing.T) { 68 lt, _, _ := setupTestHcsTask(t) 69 70 err := lt.KillExec(context.TODO(), "thisshouldnotmatch", 0xf, false) 71 72 verifyExpectedError(t, nil, err, errdefs.ErrNotFound) 73} 74 75func Test_hcsTask_KillExec_InitExecID_Unexited2ndExec_Success(t *testing.T) { 76 lt, init, second := setupTestHcsTask(t) 77 78 err := lt.KillExec(context.TODO(), "", 0xf, false) 79 if err != nil { 80 t.Fatalf("should not have failed, got: %v", err) 81 } 82 if init.state != shimExecStateExited { 83 t.Fatalf("init should be in exited state got: %v", init.state) 84 } 85 // A real platform would take this down when the pid namespace or silo goes 86 // down. For the test verify the shim did not issue the signal. 87 if second.state != shimExecStateCreated { 88 t.Fatalf("2nd exec should be in created state, got: %v", second.state) 89 } 90} 91 92func Test_hcsTask_KillExec_InitExecID_All_Success(t *testing.T) { 93 lt, init, second := setupTestHcsTask(t) 94 95 err := lt.KillExec(context.TODO(), "", 0xf, true) 96 if err != nil { 97 t.Fatalf("should not have failed, got: %v", err) 98 } 99 if init.state != shimExecStateExited { 100 t.Fatalf("init should be in exited state got: %v", init.state) 101 } 102 if second.state != shimExecStateExited { 103 t.Fatalf("2nd exec should be in exited state got: %v", second.state) 104 } 105} 106 107func Test_hcsTask_KillExec_2ndExecID_Success(t *testing.T) { 108 lt, _, second := setupTestHcsTask(t) 109 110 err := lt.KillExec(context.TODO(), second.id, 0xf, false) 111 if err != nil { 112 t.Fatalf("should not have failed, got: %v", err) 113 } 114 if second.state != shimExecStateExited { 115 t.Fatalf("2nd exec should be in exited state got: %v", second.state) 116 } 117} 118 119func Test_hcsTask_KillExec_2ndExecID_All_Error(t *testing.T) { 120 lt, _, second := setupTestHcsTask(t) 121 122 err := lt.KillExec(context.TODO(), second.id, 0xf, true) 123 124 verifyExpectedError(t, nil, err, errdefs.ErrFailedPrecondition) 125} 126 127func verifyDeleteFailureValues(t *testing.T, pid int, status uint32, at time.Time) { 128 if pid != 0 { 129 t.Fatalf("pid expected '0' got: '%d'", pid) 130 } 131 if status != 0 { 132 t.Fatalf("status expected '0' got: '%d'", status) 133 } 134 if !at.IsZero() { 135 t.Fatalf("at expected 'zero' got: '%v'", at) 136 } 137} 138 139func verifyDeleteSuccessValues(t *testing.T, pid int, status uint32, at time.Time, e *testShimExec) { 140 if pid != e.pid { 141 t.Fatalf("pid expected '%d' got: '%d'", e.pid, pid) 142 } 143 if status != e.status { 144 t.Fatalf("status expected '%d' got: '%d'", e.status, status) 145 } 146 if at != e.at { 147 t.Fatalf("at expected '%v' got: '%v'", e.at, at) 148 } 149} 150 151func Test_hcsTask_DeleteExec_UnknownExecID_Error(t *testing.T) { 152 lt, _, _ := setupTestHcsTask(t) 153 154 pid, status, at, err := lt.DeleteExec(context.TODO(), "thisshouldnotmatch") 155 verifyExpectedError(t, nil, err, errdefs.ErrNotFound) 156 verifyDeleteFailureValues(t, pid, status, at) 157} 158 159func Test_hcsTask_DeleteExec_InitExecID_CreatedState_Success(t *testing.T) { 160 lt, init, second := setupTestHcsTask(t) 161 // remove the 2nd exec so we just check without it. 162 lt.execs.Delete(second.id) 163 164 // try to delete the init exec 165 pid, status, at, err := lt.DeleteExec(context.TODO(), "") 166 167 if err != nil { 168 t.Fatalf("expected nil err got: %v", err) 169 } 170 verifyDeleteSuccessValues(t, pid, status, at, init) 171} 172 173func Test_hcsTask_DeleteExec_InitExecID_RunningState_Error(t *testing.T) { 174 lt, init, second := setupTestHcsTask(t) 175 // remove the 2nd exec so we just check without it. 176 lt.execs.Delete(second.id) 177 178 // Start the init exec 179 init.Start(context.TODO()) 180 181 // try to delete the init exec 182 pid, status, at, err := lt.DeleteExec(context.TODO(), "") 183 184 verifyExpectedError(t, nil, err, errdefs.ErrFailedPrecondition) 185 verifyDeleteFailureValues(t, pid, status, at) 186} 187 188func Test_hcsTask_DeleteExec_InitExecID_ExitedState_Success(t *testing.T) { 189 lt, init, second := setupTestHcsTask(t) 190 // remove the 2nd exec so we just check without it. 191 lt.execs.Delete(second.id) 192 193 init.Kill(context.TODO(), 0xf) 194 195 // try to delete the init exec 196 pid, status, at, err := lt.DeleteExec(context.TODO(), "") 197 198 if err != nil { 199 t.Fatalf("expected nil err got: %v", err) 200 } 201 verifyDeleteSuccessValues(t, pid, status, at, init) 202} 203 204func Test_hcsTask_DeleteExec_InitExecID_2ndExec_CreatedState_Error(t *testing.T) { 205 lt, init, second := setupTestHcsTask(t) 206 207 // start the init exec (required to have 2nd exec) 208 init.Start(context.TODO()) 209 210 // try to delete the init exec 211 pid, status, at, err := lt.DeleteExec(context.TODO(), "") 212 213 verifyExpectedError(t, nil, err, errdefs.ErrFailedPrecondition) 214 verifyDeleteFailureValues(t, pid, status, at) 215 if second.state != shimExecStateExited { 216 t.Fatalf("2nd exec should be in exited state, got: %v", second.state) 217 } 218} 219 220func Test_hcsTask_DeleteExec_InitExecID_2ndExec_RunningState_Error(t *testing.T) { 221 lt, init, second := setupTestHcsTask(t) 222 223 // start the init exec (required to have 2nd exec) 224 init.Start(context.TODO()) 225 226 // put the 2nd exec into the running state 227 second.Start(context.TODO()) 228 229 // try to delete the init exec 230 pid, status, at, err := lt.DeleteExec(context.TODO(), "") 231 232 verifyExpectedError(t, nil, err, errdefs.ErrFailedPrecondition) 233 verifyDeleteFailureValues(t, pid, status, at) 234 if second.state != shimExecStateExited { 235 t.Fatalf("2nd exec should be in exited state, got: %v", second.state) 236 } 237} 238 239func Test_hcsTask_DeleteExec_InitExecID_2ndExec_ExitedState_Success(t *testing.T) { 240 lt, init, second := setupTestHcsTask(t) 241 242 // put the init exec into the exited state 243 init.Kill(context.TODO(), 0xf) 244 // put the 2nd exec into the exited state 245 second.Kill(context.TODO(), 0xf) 246 247 // try to delete the init exec 248 pid, status, at, err := lt.DeleteExec(context.TODO(), "") 249 250 if err != nil { 251 t.Fatalf("expected nil err got: %v", err) 252 } 253 verifyDeleteSuccessValues(t, pid, status, at, init) 254} 255 256func Test_hcsTask_DeleteExec_2ndExecID_CreatedState_Success(t *testing.T) { 257 lt, init, second := setupTestHcsTask(t) 258 259 // start the init exec (required to have 2nd exec) 260 init.Start(context.TODO()) 261 262 // try to delete the 2nd exec 263 pid, status, at, err := lt.DeleteExec(context.TODO(), second.id) 264 265 if err != nil { 266 t.Fatalf("expected nil err got: %v", err) 267 } 268 verifyDeleteSuccessValues(t, pid, status, at, second) 269} 270 271func Test_hcsTask_DeleteExec_2ndExecID_RunningState_Error(t *testing.T) { 272 lt, init, second := setupTestHcsTask(t) 273 274 // start the init exec (required to have 2nd exec) 275 init.Start(context.TODO()) 276 277 // put the 2nd exec into the running state 278 second.Start(context.TODO()) 279 280 // try to delete the 2nd exec 281 pid, status, at, err := lt.DeleteExec(context.TODO(), second.id) 282 283 verifyExpectedError(t, nil, err, errdefs.ErrFailedPrecondition) 284 verifyDeleteFailureValues(t, pid, status, at) 285} 286 287func Test_hcsTask_DeleteExec_2ndExecID_ExitedState_Success(t *testing.T) { 288 lt, init, second := setupTestHcsTask(t) 289 290 // start the init exec (required to have 2nd exec) 291 init.Kill(context.TODO(), 0xf) 292 293 // put the 2nd exec into the exited state 294 second.Kill(context.TODO(), 0xf) 295 296 // try to delete the 2nd exec 297 pid, status, at, err := lt.DeleteExec(context.TODO(), second.id) 298 299 if err != nil { 300 t.Fatalf("expected nil err got: %v", err) 301 } 302 verifyDeleteSuccessValues(t, pid, status, at, second) 303} 304