@@ -1448,3 +1448,66 @@ def test_experiment_skip_status_at_exit(mock_get_runner, temp_dir):
14481448 with patch .object (exp , "status" ) as mock_status :
14491449 pass # Leaving the context triggers __exit__
14501450 mock_status .assert_not_called ()
1451+
1452+
1453+ def test_experiment_status_includes_handle (temp_dir ):
1454+ """status(return_dict=True) should include handle field added in diff."""
1455+ with Experiment ("test-exp" , base_dir = temp_dir ) as exp :
1456+ task = run .Partial (dummy_function , x = 1 , y = 2 )
1457+ job_id = exp .add (task , name = "job-status" )
1458+ # set job launched and handle
1459+ exp .jobs [0 ].launched = True
1460+ exp .jobs [0 ].handle = "handle-123"
1461+ exp .jobs [0 ].status = MagicMock (return_value = AppState .SUCCEEDED )
1462+
1463+ status_dict = exp .status (return_dict = True )
1464+ assert status_dict
1465+ assert status_dict [job_id ]["handle" ] == "handle-123"
1466+
1467+
1468+ def test_initialize_tunnels_extract_from_executors (temp_dir ):
1469+ """_initialize_tunnels(extract_from_executors=True) should add tunnels from slurm executors and call connect."""
1470+
1471+ # Fake Tunnel
1472+ class FakeTunnel :
1473+ def __init__ (self ):
1474+ self .key = "t1"
1475+ self .session = None
1476+ self .connected = False
1477+
1478+ def connect (self ):
1479+ self .connected = True
1480+ self .session = "sess"
1481+
1482+ def to_config (self ):
1483+ return run .Config (FakeTunnel )
1484+
1485+ # Fake SlurmExecutor
1486+ class FakeSlurmExecutor (LocalExecutor ):
1487+ def __init__ (self ):
1488+ super ().__init__ ()
1489+ self .tunnel = FakeTunnel ()
1490+
1491+ # override clone to avoid deep copy issues
1492+ def clone (self ):
1493+ return self
1494+
1495+ def to_config (self ):
1496+ # Minimal config stub acceptable for tests
1497+ return run .Config (FakeSlurmExecutor )
1498+
1499+ with patch ("nemo_run.run.experiment.SlurmExecutor" , FakeSlurmExecutor ):
1500+ with Experiment ("test-exp" , base_dir = temp_dir ) as exp :
1501+ # Create a Job manually to avoid executor.clone
1502+ from nemo_run .run .job import Job
1503+
1504+ job = Job (
1505+ id = "slurm-job" ,
1506+ task = run .Partial (dummy_function , x = 1 , y = 2 ),
1507+ executor = FakeSlurmExecutor (),
1508+ )
1509+ exp .jobs = [job ] # replace jobs list directly
1510+
1511+ # Should pull tunnel and connect
1512+ exp ._initialize_tunnels (extract_from_executors = True )
1513+ assert "t1" in exp .tunnels
0 commit comments