Verify sequential raid requests in budget scenario
This commit is contained in:
@@ -262,17 +262,31 @@ expect.feedback = "Тор-М2 развёрнут (integrated, multi)"
|
||||
command = "airdef deploy s400"
|
||||
expect.feedback = "С-400 развёрнут (integrated, multi)"
|
||||
|
||||
# Two maximum supported waves are issued before simulation advances, so
|
||||
# their 160 airborne units overlap while 64 defensive systems track them.
|
||||
[[step]]
|
||||
command = "airdef wave mix 80 4000"
|
||||
|
||||
# The next raid can only be ordered after the first plan is complete.
|
||||
[[step]]
|
||||
command = "airdef wave kh101 80 4000"
|
||||
|
||||
[[step]]
|
||||
ticks = 450
|
||||
frames = 225
|
||||
expect.chat = ["Противник готовит налёт: ищет площадки, местность подгружается", "Площадок за пределами загруженной карты: 1: оттуда пуск без площадки, с высоты полёта", "ВОЗДУШНАЯ ТРЕВОГА: налёт, 80 целей (один сектор)"]
|
||||
|
||||
[[step]]
|
||||
command = "airdef wave kh101 80 4000"
|
||||
expect.chat = []
|
||||
|
||||
[[step]]
|
||||
ticks = 600
|
||||
frames = 300
|
||||
expect.chat = ["Противник готовит налёт: ищет площадки, местность подгружается", "Площадок за пределами загруженной карты: 1: оттуда пуск без площадки, с высоты полёта", "ВОЗДУШНАЯ ТРЕВОГА: налёт, 80 целей (один сектор)"]
|
||||
|
||||
[[step]]
|
||||
command = "airdef stats"
|
||||
expect.feedback = "В воздухе: 12, ракет: 0, ПВО: 64, сбито: 0, поражений: 0, разбились о препятствия: 0; удары по ПУ: пущено 0, уничтожено 0, подавлено 0, промахов 0, сбито ПВО 0; мир: 0 секций (0 КБ), запросов 652, неизвестно 0, лучей 5642 (ударов 0, неизв. 5642), клеток 5642; взрывы в блоках: 0 (подтверждено 0, без перемен 0, нет чанка 0), чужих ответов 0"
|
||||
|
||||
[[step]]
|
||||
ticks = 400
|
||||
frames = 200
|
||||
|
||||
[[step]]
|
||||
command = "airdef clear"
|
||||
|
||||
+13
-6
@@ -167,10 +167,10 @@ def test_budgets():
|
||||
"scenario": "tests/budgets/wasm_budget.toml",
|
||||
"status": "failed",
|
||||
"exit_code": None,
|
||||
"scenario_counts": {"scripts": 1, "steps": None, "raids": 2,
|
||||
"max_units_per_raid": 80, "raid_units": 160,
|
||||
"air_defense_units": None, "layout_unit_limit": None,
|
||||
"frames": 300, "ticks": 602},
|
||||
"scenario_counts": {"scripts": 1, "steps": None, "raid_requests": None,
|
||||
"raid_units_requested": None, "air_defense_units": None,
|
||||
"layout_unit_limit": None, "frames": None, "ticks": None,
|
||||
"accepted_raids_observed": None, "peak_airborne_observed": None},
|
||||
"runtime_limits": {"source": "horizon/crates/horizon-mods/src/runtime.rs",
|
||||
"metering": "source_configured; measured_per_scenario: unavailable"},
|
||||
}
|
||||
@@ -206,8 +206,15 @@ def test_budgets():
|
||||
wasmtime = re.search(r'\[\[package\]\]\s*name = "wasmtime"\s*version = "([^"]+)"', lock_text)
|
||||
report["wasmtime_version"] = wasmtime.group(1) if wasmtime else None
|
||||
fixture = ROOT / "airdef-mod" / "tests" / "budgets" / "wasm_budget.toml"
|
||||
report["scenario_counts"]["steps"] = len(re.findall(r"(?m)^\[\[step\]\]$", fixture.read_text()))
|
||||
report["scenario_counts"]["air_defense_units"] = len(re.findall(r'(?m)^command = "airdef deploy [^"]+"', fixture.read_text()))
|
||||
fixture_text = fixture.read_text()
|
||||
counts = report["scenario_counts"]
|
||||
counts["steps"] = len(re.findall(r"(?m)^\[\[step\]\]$", fixture_text))
|
||||
counts["air_defense_units"] = len(re.findall(r'(?m)^command = "airdef deploy [^"]+"', fixture_text))
|
||||
requests = re.findall(r'(?m)^command = "airdef wave \S+ (\d+)(?: [^"]*)?"', fixture_text)
|
||||
counts["raid_requests"] = len(requests)
|
||||
counts["raid_units_requested"] = sum(map(int, requests))
|
||||
for field in ("ticks", "frames"):
|
||||
counts[field] = sum(map(int, re.findall(rf"(?m)^{field}\s*=\s*(\d+)\s*$", fixture_text)))
|
||||
report["scenario_sha256"] = hashlib.sha256(fixture.read_bytes()).hexdigest()
|
||||
|
||||
mod()
|
||||
|
||||
@@ -94,6 +94,21 @@ class BudgetReportFailureTests(unittest.TestCase):
|
||||
self.assertEqual(report["status"], "failed")
|
||||
return report
|
||||
|
||||
def test_counts_are_requests_and_derived_from_fixture(self):
|
||||
(self.mod_root / "tests/budgets/wasm_budget.toml").write_text(
|
||||
'[[step]]\ncommand = "airdef deploy s400"\n'
|
||||
'[[step]]\ncommand = "airdef wave kh101 80 4000"\n'
|
||||
'[[step]]\nticks = 450\nframes = 225\n'
|
||||
'[[step]]\ncommand = "airdef wave mix 40 1500"\n'
|
||||
)
|
||||
with mock.patch.object(airdef, "mod", side_effect=SystemExit("stop after provenance")):
|
||||
counts = self.invoke_and_require_failure()["scenario_counts"]
|
||||
self.assertEqual((counts["steps"], counts["air_defense_units"]), (4, 1))
|
||||
self.assertEqual((counts["raid_requests"], counts["raid_units_requested"]), (2, 120))
|
||||
self.assertEqual((counts["ticks"], counts["frames"]), (450, 225))
|
||||
self.assertIsNone(counts["accepted_raids_observed"])
|
||||
self.assertIsNone(counts["peak_airborne_observed"])
|
||||
|
||||
def test_early_system_exit_writes_report_and_skips_backend(self):
|
||||
backend = mock.Mock()
|
||||
with mock.patch.object(airdef, "mod", side_effect=SystemExit("synthetic build failure")), \
|
||||
|
||||
Reference in New Issue
Block a user