feat: initialize XAS test console with native execution
This commit is contained in:
@@ -0,0 +1,102 @@
|
||||
"""Behavioral acceptance; Linux process tests also run on the target host."""
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
import signal
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import time
|
||||
import unittest
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
RUNNER = ROOT / "scripts" / "run_smoke.py"
|
||||
|
||||
|
||||
class RunnerTests(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.temp = tempfile.TemporaryDirectory()
|
||||
self.addCleanup(self.temp.cleanup)
|
||||
self.results = Path(self.temp.name)
|
||||
|
||||
def command(self, mode="success", run_id="test-1", timeout="3"):
|
||||
self.assertTrue(RUNNER.is_file(), "run_smoke.py is not implemented")
|
||||
return [sys.executable, "-u", str(RUNNER), "--mode", mode,
|
||||
"--run-id", run_id, "--timeout", timeout,
|
||||
"--results-root", str(self.results)]
|
||||
|
||||
def run_task(self, **kwargs):
|
||||
return subprocess.run(self.command(**kwargs), capture_output=True,
|
||||
text=True, timeout=12)
|
||||
|
||||
def summary(self, run_id="test-1"):
|
||||
return json.loads((self.results / run_id / "summary.json").read_text())
|
||||
|
||||
def test_success_streams_progress_and_records_synthetic_result(self):
|
||||
result = self.run_task()
|
||||
self.assertEqual(result.returncode, 0, result.stdout + result.stderr)
|
||||
summary = self.summary()
|
||||
self.assertEqual(summary["status"], "succeeded")
|
||||
self.assertEqual(summary["run_id"], "test-1")
|
||||
self.assertTrue(summary["synthetic"])
|
||||
self.assertEqual(summary["result"]["checks_passed"], 3)
|
||||
self.assertIn("progress=1/3", result.stdout)
|
||||
self.assertIn("progress=3/3", result.stdout)
|
||||
self.assertEqual(len(summary["source_sha256"]["smoke_task.py"]), 64)
|
||||
|
||||
def test_nonzero_exit_is_recorded_as_failure(self):
|
||||
result = self.run_task(mode="failure")
|
||||
self.assertNotEqual(result.returncode, 0)
|
||||
self.assertEqual(self.summary()["status"], "failed")
|
||||
self.assertEqual(self.summary()["exit_code"], 23)
|
||||
|
||||
def test_zero_exit_with_invalid_report_is_failure(self):
|
||||
result = self.run_task(mode="invalid-report")
|
||||
self.assertNotEqual(result.returncode, 0)
|
||||
self.assertEqual(self.summary()["status"], "invalid_result")
|
||||
|
||||
def test_reused_run_id_preserves_previous_result(self):
|
||||
self.assertEqual(self.run_task().returncode, 0)
|
||||
before = (self.results / "test-1" / "summary.json").read_bytes()
|
||||
self.assertNotEqual(self.run_task(mode="failure").returncode, 0)
|
||||
self.assertEqual((self.results / "test-1" / "summary.json").read_bytes(), before)
|
||||
|
||||
def test_invalid_inputs_do_not_create_run_directory(self):
|
||||
for kwargs in ({"run_id": "../escape"}, {"mode": "arbitrary"},
|
||||
{"timeout": "0"}, {"timeout": "31"}, {"timeout": "nan"}):
|
||||
with self.subTest(kwargs=kwargs):
|
||||
self.assertNotEqual(self.run_task(**kwargs).returncode, 0)
|
||||
self.assertEqual(list(self.results.iterdir()), [])
|
||||
|
||||
@unittest.skipUnless(sys.platform == "linux", "requires Linux process groups")
|
||||
def test_timeout_terminates_child_and_records_timeout(self):
|
||||
result = self.run_task(mode="wait", timeout="2")
|
||||
self.assertEqual(result.returncode, 124, result.stdout + result.stderr)
|
||||
summary = self.summary()
|
||||
self.assertEqual(summary["status"], "timed_out")
|
||||
self.assertFalse(Path(f'/proc/{summary["child_pid"]}').exists())
|
||||
|
||||
@unittest.skipUnless(sys.platform == "linux", "requires Linux process groups")
|
||||
def test_cancel_terminates_parent_and_child(self):
|
||||
proc = subprocess.Popen(self.command(mode="wait", timeout="15"),
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
|
||||
try:
|
||||
deadline = time.monotonic() + 4
|
||||
child_file = self.results / "test-1" / "child.pid"
|
||||
while not child_file.exists() and time.monotonic() < deadline:
|
||||
time.sleep(.05)
|
||||
self.assertTrue(child_file.exists(), "worker did not start")
|
||||
child_pid = int(child_file.read_text())
|
||||
os.kill(proc.pid, signal.SIGTERM)
|
||||
out, err = proc.communicate(timeout=4)
|
||||
self.assertEqual(proc.returncode, 130, out + err)
|
||||
self.assertEqual(self.summary()["status"], "cancelled")
|
||||
self.assertFalse(Path(f"/proc/{child_pid}").exists())
|
||||
finally:
|
||||
if proc.poll() is None:
|
||||
proc.kill()
|
||||
proc.communicate()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user