@@ -64,7 +64,7 @@ type fakeDevcontainerCLI struct {
64
64
upErr error
65
65
upErrC chan error // If set, send to return err, close to return upErr.
66
66
execErr error
67
- execErrC chan error // If set, send to return err, close to return execErr.
67
+ execErrC chan func ( cmd string , args ... string ) error // If set, send fn to return err, nil or close to return execErr.
68
68
}
69
69
70
70
func (f * fakeDevcontainerCLI ) Up (ctx context.Context , _ , _ string , _ ... agentcontainers.DevcontainerCLIUpOptions ) (string , error ) {
@@ -81,14 +81,14 @@ func (f *fakeDevcontainerCLI) Up(ctx context.Context, _, _ string, _ ...agentcon
81
81
return f .upID , f .upErr
82
82
}
83
83
84
- func (f * fakeDevcontainerCLI ) Exec (ctx context.Context , _ , _ string , _ string , _ []string , _ ... agentcontainers.DevcontainerCLIExecOptions ) error {
84
+ func (f * fakeDevcontainerCLI ) Exec (ctx context.Context , _ , _ string , cmd string , args []string , _ ... agentcontainers.DevcontainerCLIExecOptions ) error {
85
85
if f .execErrC != nil {
86
86
select {
87
87
case <- ctx .Done ():
88
88
return ctx .Err ()
89
- case err , ok := <- f .execErrC :
90
- if ok {
91
- return err
89
+ case fn , ok := <- f .execErrC :
90
+ if ok && fn != nil {
91
+ return fn ( cmd , args ... )
92
92
}
93
93
}
94
94
}
@@ -1239,16 +1239,17 @@ func TestAPI(t *testing.T) {
1239
1239
}
1240
1240
1241
1241
var (
1242
- ctx = testutil .Context (t , testutil .WaitMedium )
1243
- logger = slog .Make ()
1244
- mClock = quartz .NewMock (t )
1245
- mCCLI = acmock .NewMockContainerCLI (gomock .NewController (t ))
1246
- fakeSAC = & fakeSubAgentClient {
1242
+ ctx = testutil .Context (t , testutil .WaitMedium )
1243
+ errTestTermination = xerrors .New ("test termination" )
1244
+ logger = slogtest .Make (t , & slogtest.Options {IgnoredErrorIs : []error {errTestTermination }}).Leveled (slog .LevelDebug )
1245
+ mClock = quartz .NewMock (t )
1246
+ mCCLI = acmock .NewMockContainerCLI (gomock .NewController (t ))
1247
+ fakeSAC = & fakeSubAgentClient {
1247
1248
createErrC : make (chan error , 1 ),
1248
1249
deleteErrC : make (chan error , 1 ),
1249
1250
}
1250
1251
fakeDCCLI = & fakeDevcontainerCLI {
1251
- execErrC : make (chan error , 1 ),
1252
+ execErrC : make (chan func ( cmd string , args ... string ) error , 1 ),
1252
1253
}
1253
1254
1254
1255
testContainer = codersdk.WorkspaceAgentContainer {
@@ -1264,8 +1265,6 @@ func TestAPI(t *testing.T) {
1264
1265
}
1265
1266
)
1266
1267
1267
- defer close (fakeDCCLI .execErrC )
1268
-
1269
1268
coderBin , err := os .Executable ()
1270
1269
require .NoError (t , err )
1271
1270
@@ -1287,23 +1286,31 @@ func TestAPI(t *testing.T) {
1287
1286
api := agentcontainers .NewAPI (logger ,
1288
1287
agentcontainers .WithClock (mClock ),
1289
1288
agentcontainers .WithContainerCLI (mCCLI ),
1289
+ agentcontainers .WithWatcher (watcher .NewNoop ()),
1290
1290
agentcontainers .WithSubAgentClient (fakeSAC ),
1291
1291
agentcontainers .WithSubAgentURL ("test-subagent-url" ),
1292
1292
agentcontainers .WithDevcontainerCLI (fakeDCCLI ),
1293
1293
)
1294
1294
defer api .Close ()
1295
1295
1296
- // Allow initial agent creation to succeed.
1296
+ // Close before api.Close() defer to avoid deadlock after test.
1297
+ defer close (fakeSAC .createErrC )
1298
+ defer close (fakeSAC .deleteErrC )
1299
+ defer close (fakeDCCLI .execErrC )
1300
+
1301
+ // Allow initial agent creation and injection to succeed.
1297
1302
testutil .RequireSend (ctx , t , fakeSAC .createErrC , nil )
1303
+ testutil .RequireSend (ctx , t , fakeDCCLI .execErrC , func (cmd string , args ... string ) error {
1304
+ assert .Equal (t , "pwd" , cmd )
1305
+ assert .Empty (t , args )
1306
+ return nil
1307
+ }) // Exec pwd.
1298
1308
1299
1309
// Make sure the ticker function has been registered
1300
1310
// before advancing the clock.
1301
1311
tickerTrap .MustWait (ctx ).MustRelease (ctx )
1302
1312
tickerTrap .Close ()
1303
1313
1304
- // Pre-populate for next iteration (also verify previous consumption).
1305
- testutil .RequireSend (ctx , t , fakeSAC .createErrC , nil )
1306
-
1307
1314
// Ensure we only inject the agent once.
1308
1315
for i := range 3 {
1309
1316
_ , aw := mClock .AdvanceNext ()
@@ -1318,6 +1325,8 @@ func TestAPI(t *testing.T) {
1318
1325
assert .Len (t , fakeSAC .deleted , 0 )
1319
1326
}
1320
1327
1328
+ t .Log ("Agent injected successfully, now testing cleanup and reinjection..." )
1329
+
1321
1330
// Expect the agent to be reinjected.
1322
1331
gomock .InOrder (
1323
1332
mCCLI .EXPECT ().DetectArchitecture (gomock .Any (), "test-container-id" ).Return (runtime .GOARCH , nil ),
@@ -1329,17 +1338,36 @@ func TestAPI(t *testing.T) {
1329
1338
)
1330
1339
1331
1340
// Terminate the agent and verify it is deleted.
1332
- testutil .RequireSend (ctx , t , fakeDCCLI .execErrC , nil )
1341
+ testutil .RequireSend (ctx , t , fakeDCCLI .execErrC , func (_ string , args ... string ) error {
1342
+ if len (args ) > 0 {
1343
+ assert .Equal (t , "agent" , args [0 ])
1344
+ } else {
1345
+ assert .Fail (t , `want "agent" command argument` )
1346
+ }
1347
+ return errTestTermination
1348
+ })
1333
1349
1334
1350
// Allow cleanup to proceed.
1335
- testutil .RequireSend (ctx , t , fakeSAC .deleteErrC , xerrors .New ("test termination" ))
1351
+ testutil .RequireSend (ctx , t , fakeSAC .deleteErrC , nil )
1352
+
1353
+ t .Log ("Waiting for agent recreation..." )
1354
+
1355
+ // Allow agent recreation and reinjection to succeed.
1356
+ testutil .RequireSend (ctx , t , fakeSAC .createErrC , nil )
1357
+ testutil .RequireSend (ctx , t , fakeDCCLI .execErrC , func (cmd string , args ... string ) error {
1358
+ assert .Equal (t , "pwd" , cmd )
1359
+ assert .Empty (t , args )
1360
+ return nil
1361
+ }) // Exec pwd.
1336
1362
1337
1363
// Wait until the agent recreation is started.
1338
1364
for len (fakeSAC .createErrC ) > 0 {
1339
1365
_ , aw := mClock .AdvanceNext ()
1340
1366
aw .MustWait (ctx )
1341
1367
}
1342
1368
1369
+ t .Log ("Agent recreated successfully." )
1370
+
1343
1371
// Verify agent was deleted.
1344
1372
require .Len (t , fakeSAC .deleted , 1 )
1345
1373
assert .Equal (t , fakeSAC .created [0 ].ID , fakeSAC .deleted [0 ])
0 commit comments