@@ -1354,6 +1354,50 @@ test "tick: startup timeout transitions to restarting" {
13541354 try std .testing .expectEqual (@as (? std_compat .process .Child .Id , null ), inst .pid );
13551355}
13561356
1357+ test "tick: starting portless instance transitions to running" {
1358+ const builtin = @import ("builtin" );
1359+ if (comptime builtin .os .tag == .windows ) return error .SkipZigTest ;
1360+
1361+ const allocator = std .testing .allocator ;
1362+ var fixture = try test_helpers .TempPaths .init (allocator );
1363+ defer fixture .deinit ();
1364+
1365+ var mgr = Manager .init (allocator , fixture .paths );
1366+ defer mgr .deinit ();
1367+
1368+ const spawned = try process .spawn (allocator , .{
1369+ .binary = "/bin/sleep" ,
1370+ .argv = &.{"60" },
1371+ });
1372+
1373+ const key = try std .fmt .allocPrint (allocator , "{s}/{s}" , .{ "comp" , "agent-mode" });
1374+ try mgr .instances .put (key , .{
1375+ .component = "comp" ,
1376+ .name = "agent-mode" ,
1377+ .status = .starting ,
1378+ .pid = spawned .pid ,
1379+ .child = spawned .child ,
1380+ .port = 0 ,
1381+ .restart_count = 2 ,
1382+ .starting_since = std_compat .time .milliTimestamp () - 1_000 ,
1383+ });
1384+
1385+ mgr .tick ();
1386+
1387+ const inst_ptr = mgr .instances .getPtr ("comp/agent-mode" ).? ;
1388+ try std .testing .expectEqual (Status .running , inst_ptr .status );
1389+ try std .testing .expectEqual (spawned .pid , inst_ptr .pid .? );
1390+ try std .testing .expectEqual (@as (u32 , 0 ), inst_ptr .restart_count );
1391+ try std .testing .expect (inst_ptr .last_health_ok != null );
1392+ try std .testing .expect (inst_ptr .last_health_check != null );
1393+
1394+ if (inst_ptr .child ) | * child | {
1395+ process .terminate (child .id ) catch {};
1396+ _ = child .wait () catch {};
1397+ inst_ptr .child = null ;
1398+ }
1399+ }
1400+
13571401test "tick: health failure threshold transitions to restarting" {
13581402 const builtin = @import ("builtin" );
13591403 if (comptime builtin .os .tag == .windows ) return error .SkipZigTest ;
@@ -1395,6 +1439,52 @@ test "tick: health failure threshold transitions to restarting" {
13951439 try std .testing .expectEqual (@as (u32 , 0 ), inst .health_consecutive_failures );
13961440}
13971441
1442+ test "tick: running portless instance skips health check mutations" {
1443+ const builtin = @import ("builtin" );
1444+ if (comptime builtin .os .tag == .windows ) return error .SkipZigTest ;
1445+
1446+ const allocator = std .testing .allocator ;
1447+ var fixture = try test_helpers .TempPaths .init (allocator );
1448+ defer fixture .deinit ();
1449+
1450+ var mgr = Manager .init (allocator , fixture .paths );
1451+ defer mgr .deinit ();
1452+
1453+ const spawned = try process .spawn (allocator , .{
1454+ .binary = "/bin/sleep" ,
1455+ .argv = &.{"60" },
1456+ });
1457+
1458+ const last_health_check = std_compat .time .milliTimestamp () - 60_000 ;
1459+ const last_health_ok = std_compat .time .milliTimestamp () - 30_000 ;
1460+ const key = try std .fmt .allocPrint (allocator , "{s}/{s}" , .{ "comp" , "portless-running" });
1461+ try mgr .instances .put (key , .{
1462+ .component = "comp" ,
1463+ .name = "portless-running" ,
1464+ .status = .running ,
1465+ .pid = spawned .pid ,
1466+ .child = spawned .child ,
1467+ .port = 0 ,
1468+ .last_health_check = last_health_check ,
1469+ .last_health_ok = last_health_ok ,
1470+ .health_consecutive_failures = 2 ,
1471+ });
1472+
1473+ mgr .tick ();
1474+
1475+ const inst_ptr = mgr .instances .getPtr ("comp/portless-running" ).? ;
1476+ try std .testing .expectEqual (Status .running , inst_ptr .status );
1477+ try std .testing .expectEqual (last_health_check , inst_ptr .last_health_check .? );
1478+ try std .testing .expectEqual (last_health_ok , inst_ptr .last_health_ok .? );
1479+ try std .testing .expectEqual (@as (u32 , 2 ), inst_ptr .health_consecutive_failures );
1480+
1481+ if (inst_ptr .child ) | * child | {
1482+ process .terminate (child .id ) catch {};
1483+ _ = child .wait () catch {};
1484+ inst_ptr .child = null ;
1485+ }
1486+ }
1487+
13981488test "tick: restarting with binary_path spawns new process" {
13991489 const builtin = @import ("builtin" );
14001490 if (comptime builtin .os .tag == .windows ) return error .SkipZigTest ;
0 commit comments