|
| 1 | +"""Regression tests for fake exporter service orchestration.""" |
| 2 | + |
| 3 | +import tempfile |
| 4 | +import unittest |
| 5 | +from unittest.mock import patch |
| 6 | + |
| 7 | +from experiment_utils.services.fake_exporters import RustExporterService |
| 8 | + |
| 9 | + |
| 10 | +class FakeExporterArgs: |
| 11 | + def get_node_range(self, include_coordinator=True): |
| 12 | + return [1, 2] if not include_coordinator else [0, 1, 2] |
| 13 | + |
| 14 | + def get_coordinator_node(self): |
| 15 | + return 0 |
| 16 | + |
| 17 | + |
| 18 | +class FakeExporterProvider: |
| 19 | + def get_home_dir(self): |
| 20 | + return "/tmp" |
| 21 | + |
| 22 | + |
| 23 | +class RustExporterContainerBatchingTest(unittest.TestCase): |
| 24 | + def test_container_batches_are_sequential_per_node(self): |
| 25 | + """Keep Docker startup bounded per node while retaining cross-node fan-out.""" |
| 26 | + service = RustExporterService( |
| 27 | + provider=FakeExporterProvider(), |
| 28 | + args=FakeExporterArgs(), |
| 29 | + use_container=True, |
| 30 | + ) |
| 31 | + config = { |
| 32 | + "num_ports_per_server": 8, |
| 33 | + "dataset": "demo", |
| 34 | + "start_port": 50000, |
| 35 | + "synthetic_data_value_scale": 1, |
| 36 | + "num_labels": 1, |
| 37 | + "num_values_per_label": 2, |
| 38 | + "metric_type": "gauge", |
| 39 | + } |
| 40 | + rounds = [] |
| 41 | + |
| 42 | + def record_round(_provider, node_commands, **kwargs): |
| 43 | + rounds.append((list(node_commands), kwargs)) |
| 44 | + |
| 45 | + # Regression coverage for Roborev 139: submitting all per-node batches |
| 46 | + # together allows multiple batches to overlap on the same Docker daemon. |
| 47 | + with patch( |
| 48 | + "experiment_utils.services.fake_exporters." |
| 49 | + "execute_fake_exporter_commands_in_parallel", |
| 50 | + side_effect=record_round, |
| 51 | + ): |
| 52 | + with tempfile.TemporaryDirectory() as local_experiment_dir: |
| 53 | + service._start_containerized( |
| 54 | + config=config, |
| 55 | + experiment_output_dir="", |
| 56 | + local_experiment_dir=local_experiment_dir, |
| 57 | + ) |
| 58 | + |
| 59 | + self.assertEqual(len(rounds), 2) |
| 60 | + self.assertEqual( |
| 61 | + [ |
| 62 | + [node_idx for node_idx, _ in node_commands] |
| 63 | + for node_commands, _ in rounds |
| 64 | + ], |
| 65 | + [[1, 2], [1, 2]], |
| 66 | + ) |
| 67 | + self.assertEqual( |
| 68 | + [ |
| 69 | + [command.count("docker run") for _, command in node_commands] |
| 70 | + for node_commands, _ in rounds |
| 71 | + ], |
| 72 | + [[5, 5], [3, 3]], |
| 73 | + ) |
| 74 | + self.assertTrue(all(kwargs["wait"] for _, kwargs in rounds)) |
| 75 | + |
| 76 | + |
| 77 | +if __name__ == "__main__": |
| 78 | + unittest.main() |
0 commit comments