From 8581503a9cc133df5380f14228ff2675d6261ae3 Mon Sep 17 00:00:00 2001 From: ActivePeter <1020401660@qq.com> Date: Wed, 24 Jun 2026 16:43:18 +0800 Subject: [PATCH] test --- .github/workflows/all_test.yml | 13 +- fluxon_test_stack/ci_test_list.yaml | 60 ++++++++ fluxon_test_stack/test_runner.py | 65 ++++++++ .../tests/test_ci_2_virt_node_contract.py | 50 +++++++ .../tests/test_runner_contract.py | 23 +++ .../test_test_runner_testbed_contract.py | 19 +++ .../test_top_attention_ctrl_c_contract.py | 108 ++++++++++++++ ...test_top_attention_mq_variants_contract.py | 140 ++++++++++++++++++ .../top_attention_test_index/_common.py | 23 ++- .../top_attention_test_index/_ctrl_c_kv.py | 25 +++- .../top_attention_test_index/_ctrl_c_mq.py | 25 +++- .../top_attention_test_index/_mq_mpmc.py | 25 +++- .../_mq_mpmc_bench.py | 25 +++- .../top_attention_test_index/_mq_mpsc.py | 25 +++- 14 files changed, 616 insertions(+), 10 deletions(-) create mode 100644 fluxon_test_stack/tests/test_top_attention_ctrl_c_contract.py create mode 100644 fluxon_test_stack/tests/test_top_attention_mq_variants_contract.py diff --git a/.github/workflows/all_test.yml b/.github/workflows/all_test.yml index 9e729ef..6c7aee1 100644 --- a/.github/workflows/all_test.yml +++ b/.github/workflows/all_test.yml @@ -66,6 +66,10 @@ jobs: # - ci_top_attention_doc_page_build validates doc build through the prebuilt Docker image. # - ci_top_attention_bin_kvtest keeps the Rust kv_test entry under the testbed scene contract. # - ci_top_attention_mq_core keeps MQ correctness coverage inside the same CI testbed contract. + # - ci_top_attention_mq_mpsc / ci_top_attention_mq_mpmc / ci_top_attention_mq_mpmc_bench + # keep the API channel and heavier MPMC bench-style coverage in the same CI contract. + # - ci_top_attention_ctrl_c_kv / ci_top_attention_ctrl_c_mq keep signal-exit coverage + # under the runner-native CI scene model instead of ad hoc side entrypoints. suite["scenes"] = { key: value for key, value in suite["scenes"].items() @@ -73,6 +77,11 @@ jobs: "ci_top_attention_doc_page_build", "ci_top_attention_bin_kvtest", "ci_top_attention_mq_core", + "ci_top_attention_mq_mpsc", + "ci_top_attention_mq_mpmc", + "ci_top_attention_mq_mpmc_bench", + "ci_top_attention_ctrl_c_kv", + "ci_top_attention_ctrl_c_mq", ) } @@ -95,8 +104,10 @@ jobs: # Scale selection: # - Keep the original per-scene scales from ci_test_list.yaml. # - ci_top_attention_doc_page_build stays on n1_kvowner_dram_3gib. + # - ci_top_attention_ctrl_c_kv stays on n1_kvowner_dram_3gib. # - ci_top_attention_bin_kvtest stays on n1_kvowner_dram_20gib. - # - ci_top_attention_mq_core stays on n1_kvowner_dram_20gib. + # - ci_top_attention_mq_core / ci_top_attention_mq_mpsc / ci_top_attention_mq_mpmc / + # ci_top_attention_mq_mpmc_bench / ci_top_attention_ctrl_c_mq stay on n1_kvowner_dram_20gib. out_path.write_text( yaml.safe_dump(suite, sort_keys=False, allow_unicode=False), diff --git a/fluxon_test_stack/ci_test_list.yaml b/fluxon_test_stack/ci_test_list.yaml index 6a3c56b..184d50c 100644 --- a/fluxon_test_stack/ci_test_list.yaml +++ b/fluxon_test_stack/ci_test_list.yaml @@ -37,6 +37,46 @@ scenes: scales: [n1_kvowner_dram_20gib] profiles: [fluxon_tcp] + ci_top_attention_mq_mpsc: + ci: + subject: mq + runtime_contract: cluster_kv_owner + select: + scales: [n1_kvowner_dram_20gib] + profiles: [fluxon_tcp] + + ci_top_attention_mq_mpmc: + ci: + subject: mq + runtime_contract: cluster_kv_owner + select: + scales: [n1_kvowner_dram_20gib] + profiles: [fluxon_tcp] + + ci_top_attention_mq_mpmc_bench: + ci: + subject: mq + runtime_contract: cluster_kv_owner + select: + scales: [n1_kvowner_dram_20gib] + profiles: [fluxon_tcp] + + ci_top_attention_ctrl_c_kv: + ci: + subject: rust + runtime_contract: rust_self_managed + select: + scales: [n1_kvowner_dram_3gib] + profiles: [fluxon_tcp] + + ci_top_attention_ctrl_c_mq: + ci: + subject: mq + runtime_contract: cluster_kv_owner + select: + scales: [n1_kvowner_dram_20gib] + profiles: [fluxon_tcp] + kv_read_heavy_zipf: test_stack: mode: KVSTORE @@ -320,6 +360,11 @@ profiles: ci_top_attention_bin_kvtest: kv_test_rounds: all ci_top_attention_mq_core: {} + ci_top_attention_mq_mpsc: {} + ci_top_attention_mq_mpmc: {} + ci_top_attention_mq_mpmc_bench: {} + ci_top_attention_ctrl_c_kv: {} + ci_top_attention_ctrl_c_mq: {} runtime_contracts: cluster_kv_owner: &cluster_kv_owner_runtime base_runtime: @@ -466,6 +511,11 @@ profiles: ci_top_attention_bin_kvtest: kv_test_rounds: all ci_top_attention_mq_core: {} + ci_top_attention_mq_mpsc: {} + ci_top_attention_mq_mpmc: {} + ci_top_attention_mq_mpmc_bench: {} + ci_top_attention_ctrl_c_kv: {} + ci_top_attention_ctrl_c_mq: {} test_stack: <<: *common_test_stack_runtime fluxon_sockudo_ws: @@ -479,6 +529,11 @@ profiles: ci_top_attention_bin_kvtest: kv_test_rounds: all ci_top_attention_mq_core: {} + ci_top_attention_mq_mpsc: {} + ci_top_attention_mq_mpmc: {} + ci_top_attention_mq_mpmc_bench: {} + ci_top_attention_ctrl_c_kv: {} + ci_top_attention_ctrl_c_mq: {} test_stack: <<: *common_test_stack_runtime fluxon_tcp: @@ -492,6 +547,11 @@ profiles: ci_top_attention_bin_kvtest: kv_test_rounds: all ci_top_attention_mq_core: {} + ci_top_attention_mq_mpsc: {} + ci_top_attention_mq_mpmc: {} + ci_top_attention_mq_mpmc_bench: {} + ci_top_attention_ctrl_c_kv: {} + ci_top_attention_ctrl_c_mq: {} test_stack: <<: *common_test_stack_runtime redis_sharded: diff --git a/fluxon_test_stack/test_runner.py b/fluxon_test_stack/test_runner.py index d8cd1c9..478787a 100644 --- a/fluxon_test_stack/test_runner.py +++ b/fluxon_test_stack/test_runner.py @@ -402,6 +402,11 @@ def _runner_native_ci_scene_ids() -> Tuple[str, ...]: "ci_top_attention_doc_page_build", "ci_top_attention_bin_kvtest", "ci_top_attention_mq_core", + "ci_top_attention_mq_mpsc", + "ci_top_attention_mq_mpmc", + "ci_top_attention_mq_mpmc_bench", + "ci_top_attention_ctrl_c_kv", + "ci_top_attention_ctrl_c_mq", ) @@ -7039,6 +7044,66 @@ def _runner_native_ci_commands_for_case(case: _ResolvedCase, *, ctx: str) -> Lis "timeout_seconds": 21600, } ] + if scene_id == "ci_top_attention_mq_mpsc": + return [ + { + "id": "top_attention_mq_mpsc", + "command": ( + "__RUN_DIR__/venv/bin/python3 -u " + "__RUN_DIR__/src/fluxon_test_stack/top_attention_test_index/_mq_mpsc.py " + "--case-config __RUN_DIR__/configs/ci_scene_config.yaml" + ), + "timeout_seconds": 21600, + } + ] + if scene_id == "ci_top_attention_mq_mpmc": + return [ + { + "id": "top_attention_mq_mpmc", + "command": ( + "__RUN_DIR__/venv/bin/python3 -u " + "__RUN_DIR__/src/fluxon_test_stack/top_attention_test_index/_mq_mpmc.py " + "--case-config __RUN_DIR__/configs/ci_scene_config.yaml" + ), + "timeout_seconds": 21600, + } + ] + if scene_id == "ci_top_attention_mq_mpmc_bench": + return [ + { + "id": "top_attention_mq_mpmc_bench", + "command": ( + "__RUN_DIR__/venv/bin/python3 -u " + "__RUN_DIR__/src/fluxon_test_stack/top_attention_test_index/_mq_mpmc_bench.py " + "--case-config __RUN_DIR__/configs/ci_scene_config.yaml" + ), + "timeout_seconds": 21600, + } + ] + if scene_id == "ci_top_attention_ctrl_c_kv": + return [ + { + "id": "top_attention_ctrl_c_kv", + "command": ( + "__RUN_DIR__/venv/bin/python3 -u " + "__RUN_DIR__/src/fluxon_test_stack/top_attention_test_index/_ctrl_c_kv.py " + "--case-config __RUN_DIR__/configs/ci_scene_config.yaml" + ), + "timeout_seconds": 10800, + } + ] + if scene_id == "ci_top_attention_ctrl_c_mq": + return [ + { + "id": "top_attention_ctrl_c_mq", + "command": ( + "__RUN_DIR__/venv/bin/python3 -u " + "__RUN_DIR__/src/fluxon_test_stack/top_attention_test_index/_ctrl_c_mq.py " + "--case-config __RUN_DIR__/configs/ci_scene_config.yaml" + ), + "timeout_seconds": 21600, + } + ] raise ValueError(f"{ctx} unsupported runner-native CI scene: {scene_id!r}") diff --git a/fluxon_test_stack/tests/test_ci_2_virt_node_contract.py b/fluxon_test_stack/tests/test_ci_2_virt_node_contract.py index 4392be6..c81e632 100644 --- a/fluxon_test_stack/tests/test_ci_2_virt_node_contract.py +++ b/fluxon_test_stack/tests/test_ci_2_virt_node_contract.py @@ -30,6 +30,11 @@ class TestCi2VirtNodeContract(unittest.TestCase): _KVTEST_SCENE_ID = "ci_top_attention_bin_kvtest" _DOC_SCENE_ID = "ci_top_attention_doc_page_build" _MQ_SCENE_ID = "ci_top_attention_mq_core" + _MQ_MPSC_SCENE_ID = "ci_top_attention_mq_mpsc" + _MQ_MPMC_SCENE_ID = "ci_top_attention_mq_mpmc" + _MQ_MPMC_BENCH_SCENE_ID = "ci_top_attention_mq_mpmc_bench" + _CTRL_C_KV_SCENE_ID = "ci_top_attention_ctrl_c_kv" + _CTRL_C_MQ_SCENE_ID = "ci_top_attention_ctrl_c_mq" def test_generated_suite_is_public_dual_local_nodes_ci_only(self) -> None: suite_cfg = _ENTRY._load_yaml_mapping(_ENTRY.DEFAULT_SUITE_PATH, ctx="suite") @@ -148,6 +153,51 @@ def test_generated_suite_supports_mq_core_ci_scene(self) -> None: ) self.assertEqual(set(generated["scales"].keys()), {"n1_kvowner_dram_20gib"}) + def test_generated_suite_supports_extra_ci_scenes(self) -> None: + suite_cfg = _ENTRY._load_yaml_mapping(_ENTRY.DEFAULT_SUITE_PATH, ctx="suite") + scene_ids = [ + self._MQ_MPSC_SCENE_ID, + self._MQ_MPMC_SCENE_ID, + self._MQ_MPMC_BENCH_SCENE_ID, + self._CTRL_C_KV_SCENE_ID, + self._CTRL_C_MQ_SCENE_ID, + ] + generated = _ENTRY._rewrite_suite_for_local_dual_nodes( + suite_cfg=suite_cfg, + scene_ids=scene_ids, + primary_node_name="local-node-a", + secondary_node_name="local-node-b", + host_ip="10.1.1.119", + wheel_name="fluxon-0.2.1-cp38-abi3-manylinux_2_28_x86_64.whl", + controller_port=19080, + ) + + self.assertEqual(set(generated["scenes"].keys()), set(scene_ids)) + self.assertEqual( + generated["scenes"][self._CTRL_C_KV_SCENE_ID]["ci"]["runtime_contract"], + "rust_self_managed", + ) + self.assertEqual( + generated["scenes"][self._CTRL_C_MQ_SCENE_ID]["ci"]["runtime_contract"], + "cluster_kv_owner", + ) + self.assertEqual( + generated["scenes"][self._MQ_MPSC_SCENE_ID]["ci"]["subject"], + "mq", + ) + self.assertEqual( + generated["scenes"][self._MQ_MPMC_SCENE_ID]["ci"]["subject"], + "mq", + ) + self.assertEqual( + generated["scenes"][self._MQ_MPMC_BENCH_SCENE_ID]["ci"]["subject"], + "mq", + ) + self.assertEqual( + set(generated["scales"].keys()), + {"n1_kvowner_dram_3gib", "n1_kvowner_dram_20gib"}, + ) + def test_generated_suite_preserves_source_scene_configs(self) -> None: suite_cfg = _ENTRY._load_yaml_mapping(_ENTRY.DEFAULT_SUITE_PATH, ctx="suite") suite_cfg["profiles"]["fluxon_tcp"]["runtime"]["ci"]["scene_configs"][self._KVTEST_SCENE_ID]["kv_test_rounds"] = "p2p_only" diff --git a/fluxon_test_stack/tests/test_runner_contract.py b/fluxon_test_stack/tests/test_runner_contract.py index 7c8fddd..018e489 100644 --- a/fluxon_test_stack/tests/test_runner_contract.py +++ b/fluxon_test_stack/tests/test_runner_contract.py @@ -63,6 +63,10 @@ def _build_checks(selected_test_id: Optional[str]) -> List[Tuple[str, Callable[[ "ci_top_attention_mq_core_uses_cluster_kv_owner_runtime", test_ci_top_attention_mq_core_uses_cluster_kv_owner_runtime, ), + ( + "ci_top_attention_extra_runner_native_scenes_are_registered", + test_ci_top_attention_extra_runner_native_scenes_are_registered, + ), ] if selected_test_id is None: return checks @@ -291,5 +295,24 @@ def test_ci_top_attention_mq_core_uses_cluster_kv_owner_runtime() -> None: print("PASS: test_ci_top_attention_mq_core_uses_cluster_kv_owner_runtime") +def test_ci_top_attention_extra_runner_native_scenes_are_registered() -> None: + expected = { + "ci_top_attention_mq_mpsc", + "ci_top_attention_mq_mpmc", + "ci_top_attention_mq_mpmc_bench", + "ci_top_attention_ctrl_c_kv", + "ci_top_attention_ctrl_c_mq", + } + actual = set(_TEST_RUNNER._runner_native_ci_scene_ids()) + missing = sorted(expected - actual) + if missing: + print( + "FAIL: test_ci_top_attention_extra_runner_native_scenes_are_registered - " + f"missing scenes: {missing!r}" + ) + return + print("PASS: test_ci_top_attention_extra_runner_native_scenes_are_registered") + + if __name__ == "__main__": raise SystemExit(main()) diff --git a/fluxon_test_stack/tests/test_test_runner_testbed_contract.py b/fluxon_test_stack/tests/test_test_runner_testbed_contract.py index 34bf640..60ee5ee 100644 --- a/fluxon_test_stack/tests/test_test_runner_testbed_contract.py +++ b/fluxon_test_stack/tests/test_test_runner_testbed_contract.py @@ -238,6 +238,25 @@ def test_top_attention_mq_core_ci_execution_plan_is_runner_native(self) -> None: ) self.assertIn("--case-config __RUN_DIR__/configs/ci_scene_config.yaml", planned[0].ci_commands[0]["command"]) + def test_top_attention_extra_ci_execution_plans_are_runner_native(self) -> None: + suite_cfg = yaml.safe_load((_RUNNER.RUNNER_REPO_ROOT / "fluxon_test_stack" / "ci_test_list.yaml").read_text(encoding="utf-8")) + suite = _RUNNER._parse_suite_config(suite_cfg) + cases = _RUNNER._expand_cases(suite) + expected = { + "ci_top_attention_mq_mpsc": ("top_attention_mq_mpsc", "_mq_mpsc.py"), + "ci_top_attention_mq_mpmc": ("top_attention_mq_mpmc", "_mq_mpmc.py"), + "ci_top_attention_mq_mpmc_bench": ("top_attention_mq_mpmc_bench", "_mq_mpmc_bench.py"), + "ci_top_attention_ctrl_c_kv": ("top_attention_ctrl_c_kv", "_ctrl_c_kv.py"), + "ci_top_attention_ctrl_c_mq": ("top_attention_ctrl_c_mq", "_ctrl_c_mq.py"), + } + for scene_id, (command_id, script_name) in expected.items(): + case = next(item for item in cases if item.scene_id == scene_id and item.profile_id == "fluxon_tcp") + planned = _RUNNER._build_ci_execution_plan(case, suite) + self.assertEqual(len(planned), 1) + self.assertEqual(planned[0].ci_commands[0]["id"], command_id) + self.assertIn(script_name, planned[0].ci_commands[0]["command"]) + self.assertIn("--case-config __RUN_DIR__/configs/ci_scene_config.yaml", planned[0].ci_commands[0]["command"]) + def test_doc_page_ci_execution_plan_uses_online_docker_image(self) -> None: suite_cfg = yaml.safe_load((_RUNNER.RUNNER_REPO_ROOT / "fluxon_test_stack" / "ci_test_list.yaml").read_text(encoding="utf-8")) suite = _RUNNER._parse_suite_config(suite_cfg) diff --git a/fluxon_test_stack/tests/test_top_attention_ctrl_c_contract.py b/fluxon_test_stack/tests/test_top_attention_ctrl_c_contract.py new file mode 100644 index 0000000..c664b23 --- /dev/null +++ b/fluxon_test_stack/tests/test_top_attention_ctrl_c_contract.py @@ -0,0 +1,108 @@ +#!/usr/bin/env python3 + +from __future__ import annotations + +import importlib.util +import sys +import tempfile +import unittest +from pathlib import Path +from unittest import mock + +import yaml + + +REPO_ROOT = Path(__file__).resolve().parents[2] +INDEX_ROOT = REPO_ROOT / "fluxon_test_stack" / "top_attention_test_index" + + +def _load_module(filename: str, module_name: str): + module_path = INDEX_ROOT / filename + module_dir = module_path.parent + sys.path.insert(0, str(module_dir)) + try: + spec = importlib.util.spec_from_file_location(module_name, module_path) + assert spec is not None and spec.loader is not None + mod = importlib.util.module_from_spec(spec) + sys.modules[spec.name] = mod + spec.loader.exec_module(mod) + return mod, module_path + finally: + if sys.path and sys.path[0] == str(module_dir): + sys.path.pop(0) + + +class TestTopAttentionCtrlCContract(unittest.TestCase): + def _write_case_config(self, root: Path, *, scene_id: str) -> Path: + cfg_dir = root / "configs" + cfg_dir.mkdir(parents=True, exist_ok=True) + case_cfg = cfg_dir / "ci_scene_config.yaml" + case_cfg.write_text( + yaml.safe_dump( + { + "case": { + "scene_id": scene_id, + "scale_id": "n1_kvowner_dram_20gib", + "profile_id": "fluxon_tcp_thread", + "case_id": f"{scene_id}__n1_kvowner_dram_20gib__fluxon_tcp_thread", + }, + "scene_config": {}, + "scene_runtime": { + "etcd": {"ip": "127.0.0.1", "port": 19180}, + "greptime": {"ip": "127.0.0.1", "port": 19190}, + }, + }, + sort_keys=False, + ), + encoding="utf-8", + ) + return case_cfg + + def test_ctrl_c_kv_accepts_case_config_and_runs_single_test(self) -> None: + entry, module_path = _load_module("_ctrl_c_kv.py", "fluxon_test_stack_top_attention_ctrl_c_kv_contract") + with tempfile.TemporaryDirectory() as td: + case_cfg = self._write_case_config(Path(td), scene_id="ci_top_attention_ctrl_c_kv") + with mock.patch.object(entry, "run_python_file", return_value=0) as run_python_file: + with mock.patch.object( + sys, + "argv", + [str(module_path), "--python", "/tmp/venv/bin/python3", "--case-config", str(case_cfg)], + ): + rc = entry.main() + self.assertEqual(rc, 0) + self.assertEqual( + list(run_python_file.call_args.args), + [ + "Flat index entry for existing KV/runtime Ctrl-C shutdown coverage.", + "fluxon_py/tests/test_process_runner.py", + ["TestProcessRunner.test_wait_subproc_or_ctrlc_retires_children_on_sigterm"], + ], + ) + self.assertEqual(run_python_file.call_args.kwargs["passthrough"], []) + self.assertEqual(run_python_file.call_args.kwargs["python"], "/tmp/venv/bin/python3") + + def test_ctrl_c_mq_accepts_case_config_and_runs_python_file(self) -> None: + entry, module_path = _load_module("_ctrl_c_mq.py", "fluxon_test_stack_top_attention_ctrl_c_mq_contract") + with tempfile.TemporaryDirectory() as td: + case_cfg = self._write_case_config(Path(td), scene_id="ci_top_attention_ctrl_c_mq") + with mock.patch.object(entry, "run_python_file", return_value=0) as run_python_file: + with mock.patch.object( + sys, + "argv", + [str(module_path), "--python", "/tmp/venv/bin/python3", "--case-config", str(case_cfg)], + ): + rc = entry.main() + self.assertEqual(rc, 0) + self.assertEqual( + list(run_python_file.call_args.args), + [ + "Flat index entry for existing MQ Ctrl-C integration coverage.", + "fluxon_py/tests/test_mq/test_example_ctrl_c_exit.py", + ], + ) + self.assertEqual(run_python_file.call_args.kwargs["passthrough"], []) + self.assertEqual(run_python_file.call_args.kwargs["python"], "/tmp/venv/bin/python3") + + +if __name__ == "__main__": + raise SystemExit(unittest.main()) diff --git a/fluxon_test_stack/tests/test_top_attention_mq_variants_contract.py b/fluxon_test_stack/tests/test_top_attention_mq_variants_contract.py new file mode 100644 index 0000000..985ad38 --- /dev/null +++ b/fluxon_test_stack/tests/test_top_attention_mq_variants_contract.py @@ -0,0 +1,140 @@ +#!/usr/bin/env python3 + +from __future__ import annotations + +import importlib.util +import sys +import tempfile +import unittest +from pathlib import Path +from unittest import mock + +import yaml + + +REPO_ROOT = Path(__file__).resolve().parents[2] +INDEX_ROOT = REPO_ROOT / "fluxon_test_stack" / "top_attention_test_index" + + +def _load_module(filename: str, module_name: str): + module_path = INDEX_ROOT / filename + module_dir = module_path.parent + sys.path.insert(0, str(module_dir)) + try: + spec = importlib.util.spec_from_file_location(module_name, module_path) + assert spec is not None and spec.loader is not None + mod = importlib.util.module_from_spec(spec) + sys.modules[spec.name] = mod + spec.loader.exec_module(mod) + return mod, module_path + finally: + if sys.path and sys.path[0] == str(module_dir): + sys.path.pop(0) + + +class TestTopAttentionMqVariantsContract(unittest.TestCase): + def _write_case_config(self, root: Path, *, scene_id: str) -> Path: + cfg_dir = root / "configs" + cfg_dir.mkdir(parents=True, exist_ok=True) + case_cfg = cfg_dir / "ci_scene_config.yaml" + case_cfg.write_text( + yaml.safe_dump( + { + "case": { + "scene_id": scene_id, + "scale_id": "n1_kvowner_dram_20gib", + "profile_id": "fluxon_tcp_thread", + "case_id": f"{scene_id}__n1_kvowner_dram_20gib__fluxon_tcp_thread", + }, + "scene_config": {}, + "scene_runtime": { + "etcd": {"ip": "127.0.0.1", "port": 19180}, + "greptime": {"ip": "127.0.0.1", "port": 19190}, + }, + }, + sort_keys=False, + ), + encoding="utf-8", + ) + return case_cfg + + def test_mq_mpsc_accepts_case_config_and_runs_pytest_target(self) -> None: + entry, module_path = _load_module("_mq_mpsc.py", "fluxon_test_stack_top_attention_mq_mpsc_contract") + with tempfile.TemporaryDirectory() as td: + case_cfg = self._write_case_config(Path(td), scene_id="ci_top_attention_mq_mpsc") + with mock.patch.object(entry, "run_pytest", return_value=0) as run_pytest: + with mock.patch.object( + sys, + "argv", + [str(module_path), "--python", "/tmp/venv/bin/python3", "--case-config", str(case_cfg)], + ): + rc = entry.main() + self.assertEqual(rc, 0) + self.assertEqual( + list(run_pytest.call_args.args), + [ + "Flat index entry for MPSC API channel tests.", + ["fluxon_py/tests/test_api_chan_mpsc/test_api_chan_mpsc_base.py"], + ], + ) + self.assertEqual(run_pytest.call_args.kwargs["passthrough"], []) + self.assertEqual(run_pytest.call_args.kwargs["python"], "/tmp/venv/bin/python3") + + def test_mq_mpmc_accepts_case_config_and_runs_pytest_targets(self) -> None: + entry, module_path = _load_module("_mq_mpmc.py", "fluxon_test_stack_top_attention_mq_mpmc_contract") + with tempfile.TemporaryDirectory() as td: + case_cfg = self._write_case_config(Path(td), scene_id="ci_top_attention_mq_mpmc") + with mock.patch.object(entry, "run_pytest", return_value=0) as run_pytest: + with mock.patch.object( + sys, + "argv", + [str(module_path), "--python", "/tmp/venv/bin/python3", "--case-config", str(case_cfg)], + ): + rc = entry.main() + self.assertEqual(rc, 0) + self.assertEqual( + list(run_pytest.call_args.args), + [ + "Flat index entry for MPMC API channel tests.", + [ + "fluxon_py/tests/test_api_chan_mpmc/test_api_chan_mpmc_base.py", + "fluxon_py/tests/test_api_chan_mpmc/test_api_chan_mpmc_quick_and_weighted_consume.py", + "fluxon_py/tests/test_api_chan_mpmc/test_ready_channels_access.py", + "fluxon_py/tests/test_api_chan_mpmc/test_rebind_client.py", + ], + ], + ) + self.assertEqual(run_pytest.call_args.kwargs["passthrough"], []) + self.assertEqual(run_pytest.call_args.kwargs["python"], "/tmp/venv/bin/python3") + + def test_mq_mpmc_bench_accepts_case_config_and_runs_pytest_targets(self) -> None: + entry, module_path = _load_module( + "_mq_mpmc_bench.py", + "fluxon_test_stack_top_attention_mq_mpmc_bench_contract", + ) + with tempfile.TemporaryDirectory() as td: + case_cfg = self._write_case_config(Path(td), scene_id="ci_top_attention_mq_mpmc_bench") + with mock.patch.object(entry, "run_pytest", return_value=0) as run_pytest: + with mock.patch.object( + sys, + "argv", + [str(module_path), "--python", "/tmp/venv/bin/python3", "--case-config", str(case_cfg)], + ): + rc = entry.main() + self.assertEqual(rc, 0) + self.assertEqual( + list(run_pytest.call_args.args), + [ + "Flat index entry for heavier MPMC benchmark-style tests.", + [ + "fluxon_py/tests/test_api_chan_mpmc/test_mpmc_simple_bench.py", + "fluxon_py/tests/test_api_chan_mpmc/test_mpmc_simple_bench2.py", + ], + ], + ) + self.assertEqual(run_pytest.call_args.kwargs["passthrough"], []) + self.assertEqual(run_pytest.call_args.kwargs["python"], "/tmp/venv/bin/python3") + + +if __name__ == "__main__": + raise SystemExit(unittest.main()) diff --git a/fluxon_test_stack/top_attention_test_index/_common.py b/fluxon_test_stack/top_attention_test_index/_common.py index 3991aa7..f8bac17 100755 --- a/fluxon_test_stack/top_attention_test_index/_common.py +++ b/fluxon_test_stack/top_attention_test_index/_common.py @@ -32,13 +32,28 @@ def parse_python_passthrough(description: str) -> tuple[str, list[str]]: return args.python, passthrough -def run_pytest(description: str, paths: Iterable[str]) -> int: - python, passthrough = parse_python_passthrough(description) +def run_pytest( + description: str, + paths: Iterable[str], + *, + passthrough: Iterable[str] = (), + python: str | None = None, +) -> int: + if python is None: + python = parse_python_passthrough(description)[0] return call([python, "-m", "pytest", *paths, *passthrough]) -def run_python_file(description: str, path: str, extra_args: Iterable[str] = ()) -> int: - python, passthrough = parse_python_passthrough(description) +def run_python_file( + description: str, + path: str, + extra_args: Iterable[str] = (), + *, + passthrough: Iterable[str] = (), + python: str | None = None, +) -> int: + if python is None: + python = parse_python_passthrough(description)[0] return call([python, "-u", str(REPO_ROOT / path), *extra_args, *passthrough]) diff --git a/fluxon_test_stack/top_attention_test_index/_ctrl_c_kv.py b/fluxon_test_stack/top_attention_test_index/_ctrl_c_kv.py index f3e5e75..ff68841 100755 --- a/fluxon_test_stack/top_attention_test_index/_ctrl_c_kv.py +++ b/fluxon_test_stack/top_attention_test_index/_ctrl_c_kv.py @@ -1,17 +1,40 @@ #!/usr/bin/env python3 from __future__ import annotations -from _common import run_python_file +import argparse +import os +from pathlib import Path +import sys + +from _common import load_case_config_payload, run_python_file TEST_REQUIREMENTS = ["ops"] +SCENE_ID = "ci_top_attention_ctrl_c_kv" def main() -> int: + parser = argparse.ArgumentParser( + description="Flat index entry for existing KV/runtime Ctrl-C shutdown coverage." + ) + parser.add_argument( + "--python", + default=os.environ.get("PYTHON", sys.executable), + help="Python executable used for the delegated command.", + ) + parser.add_argument( + "--case-config", + help="Canonical CI case config YAML emitted by test_runner.", + ) + args, passthrough = parser.parse_known_args() + if args.case_config: + load_case_config_payload(Path(args.case_config).resolve(), expected_scene_id=SCENE_ID) return run_python_file( "Flat index entry for existing KV/runtime Ctrl-C shutdown coverage.", "fluxon_py/tests/test_process_runner.py", ["TestProcessRunner.test_wait_subproc_or_ctrlc_retires_children_on_sigterm"], + passthrough=passthrough, + python=args.python, ) diff --git a/fluxon_test_stack/top_attention_test_index/_ctrl_c_mq.py b/fluxon_test_stack/top_attention_test_index/_ctrl_c_mq.py index 3e56e8a..641bc23 100755 --- a/fluxon_test_stack/top_attention_test_index/_ctrl_c_mq.py +++ b/fluxon_test_stack/top_attention_test_index/_ctrl_c_mq.py @@ -1,16 +1,39 @@ #!/usr/bin/env python3 from __future__ import annotations -from _common import run_python_file +import argparse +import os +from pathlib import Path +import sys + +from _common import load_case_config_payload, run_python_file TEST_REQUIREMENTS = ["etcd", "fluxon-pyo3", "fluxon-release", "greptime", "ops", "submodules"] +SCENE_ID = "ci_top_attention_ctrl_c_mq" def main() -> int: + parser = argparse.ArgumentParser( + description="Flat index entry for existing MQ Ctrl-C integration coverage." + ) + parser.add_argument( + "--python", + default=os.environ.get("PYTHON", sys.executable), + help="Python executable used for the delegated command.", + ) + parser.add_argument( + "--case-config", + help="Canonical CI case config YAML emitted by test_runner.", + ) + args, passthrough = parser.parse_known_args() + if args.case_config: + load_case_config_payload(Path(args.case_config).resolve(), expected_scene_id=SCENE_ID) return run_python_file( "Flat index entry for existing MQ Ctrl-C integration coverage.", "fluxon_py/tests/test_mq/test_example_ctrl_c_exit.py", + passthrough=passthrough, + python=args.python, ) diff --git a/fluxon_test_stack/top_attention_test_index/_mq_mpmc.py b/fluxon_test_stack/top_attention_test_index/_mq_mpmc.py index 0b3db0e..6782474 100755 --- a/fluxon_test_stack/top_attention_test_index/_mq_mpmc.py +++ b/fluxon_test_stack/top_attention_test_index/_mq_mpmc.py @@ -1,13 +1,34 @@ #!/usr/bin/env python3 from __future__ import annotations -from _common import run_pytest +import argparse +import os +from pathlib import Path +import sys + +from _common import load_case_config_payload, run_pytest TEST_REQUIREMENTS = ["etcd", "kv-cluster", "ops"] +SCENE_ID = "ci_top_attention_mq_mpmc" def main() -> int: + parser = argparse.ArgumentParser( + description="Flat index entry for MPMC API channel tests." + ) + parser.add_argument( + "--python", + default=os.environ.get("PYTHON", sys.executable), + help="Python executable used for the delegated command.", + ) + parser.add_argument( + "--case-config", + help="Canonical CI case config YAML emitted by test_runner.", + ) + args, passthrough = parser.parse_known_args() + if args.case_config: + load_case_config_payload(Path(args.case_config).resolve(), expected_scene_id=SCENE_ID) return run_pytest( "Flat index entry for MPMC API channel tests.", [ @@ -16,6 +37,8 @@ def main() -> int: "fluxon_py/tests/test_api_chan_mpmc/test_ready_channels_access.py", "fluxon_py/tests/test_api_chan_mpmc/test_rebind_client.py", ], + passthrough=passthrough, + python=args.python, ) diff --git a/fluxon_test_stack/top_attention_test_index/_mq_mpmc_bench.py b/fluxon_test_stack/top_attention_test_index/_mq_mpmc_bench.py index 8c6501b..d554c5f 100755 --- a/fluxon_test_stack/top_attention_test_index/_mq_mpmc_bench.py +++ b/fluxon_test_stack/top_attention_test_index/_mq_mpmc_bench.py @@ -1,19 +1,42 @@ #!/usr/bin/env python3 from __future__ import annotations -from _common import run_pytest +import argparse +import os +from pathlib import Path +import sys + +from _common import load_case_config_payload, run_pytest TEST_REQUIREMENTS = ["etcd", "kv-cluster", "ops"] +SCENE_ID = "ci_top_attention_mq_mpmc_bench" def main() -> int: + parser = argparse.ArgumentParser( + description="Flat index entry for heavier MPMC benchmark-style tests." + ) + parser.add_argument( + "--python", + default=os.environ.get("PYTHON", sys.executable), + help="Python executable used for the delegated command.", + ) + parser.add_argument( + "--case-config", + help="Canonical CI case config YAML emitted by test_runner.", + ) + args, passthrough = parser.parse_known_args() + if args.case_config: + load_case_config_payload(Path(args.case_config).resolve(), expected_scene_id=SCENE_ID) return run_pytest( "Flat index entry for heavier MPMC benchmark-style tests.", [ "fluxon_py/tests/test_api_chan_mpmc/test_mpmc_simple_bench.py", "fluxon_py/tests/test_api_chan_mpmc/test_mpmc_simple_bench2.py", ], + passthrough=passthrough, + python=args.python, ) diff --git a/fluxon_test_stack/top_attention_test_index/_mq_mpsc.py b/fluxon_test_stack/top_attention_test_index/_mq_mpsc.py index 3ff94ef..bb8819d 100755 --- a/fluxon_test_stack/top_attention_test_index/_mq_mpsc.py +++ b/fluxon_test_stack/top_attention_test_index/_mq_mpsc.py @@ -1,16 +1,39 @@ #!/usr/bin/env python3 from __future__ import annotations -from _common import run_pytest +import argparse +import os +from pathlib import Path +import sys + +from _common import load_case_config_payload, run_pytest TEST_REQUIREMENTS = ["etcd", "kv-cluster", "ops"] +SCENE_ID = "ci_top_attention_mq_mpsc" def main() -> int: + parser = argparse.ArgumentParser( + description="Flat index entry for MPSC API channel tests." + ) + parser.add_argument( + "--python", + default=os.environ.get("PYTHON", sys.executable), + help="Python executable used for the delegated command.", + ) + parser.add_argument( + "--case-config", + help="Canonical CI case config YAML emitted by test_runner.", + ) + args, passthrough = parser.parse_known_args() + if args.case_config: + load_case_config_payload(Path(args.case_config).resolve(), expected_scene_id=SCENE_ID) return run_pytest( "Flat index entry for MPSC API channel tests.", ["fluxon_py/tests/test_api_chan_mpsc/test_api_chan_mpsc_base.py"], + passthrough=passthrough, + python=args.python, )