From 86ed6b62ca00d4c771fcc927fe5359c1700363b5 Mon Sep 17 00:00:00 2001 From: Nikita Pivoev Date: Wed, 13 May 2026 13:07:22 +0300 Subject: [PATCH] main: add configurable fault injection interval --- libkirk/main.py | 22 ++++++++++++++++++++++ libkirk/session.py | 13 ++++++++++--- libkirk/sut.py | 12 +++++++++--- libkirk/tests/test_main.py | 10 ++++++++++ 4 files changed, 51 insertions(+), 6 deletions(-) diff --git a/libkirk/main.py b/libkirk/main.py index b416b1a..94825db 100644 --- a/libkirk/main.py +++ b/libkirk/main.py @@ -199,6 +199,21 @@ def _finjection_config(value: str) -> int: return max(0, min(100, ret)) +def _finterval_config(value: str) -> int: + """ + Return interval of fault injection. + """ + if not value: + return 1 + + try: + ret = int(value) + except TypeError as err: + raise argparse.ArgumentTypeError("Invalid number") from err + + return max(1, ret) + + def _get_skip_tests(skip_tests: str, skip_file: str) -> str: """ Return the skipped tests regexp. @@ -361,6 +376,7 @@ async def session_run() -> None: randomize=args.randomize, runtime=args.runtime, fault_prob=args.fault_injection, + fault_interval=args.fault_interval, ) except asyncio.CancelledError: await session.stop() @@ -518,6 +534,12 @@ def run(cmd_args: Optional[List[str]] = None) -> None: default=0, help="Probability of failure (0-100)", ) + exec_opts.add_argument( + "--fault-interval", + type=_finterval_config, + default=1, + help="Fault injection interval (default: 1)", + ) exec_opts.add_argument( "--optimize-sut", "-O", diff --git a/libkirk/session.py b/libkirk/session.py index f51c3ac..ffcee90 100644 --- a/libkirk/session.py +++ b/libkirk/session.py @@ -403,7 +403,11 @@ async def _run_scheduler(self, suites_obj: List[Suite], runtime: float) -> None: except asyncio.TimeoutError: await self._scheduler.stop() - async def _apply_fault_injection(self, fault_prob: int) -> None: + async def _apply_fault_injection( + self, + fault_prob: int, + fault_interval: int = 1, + ) -> None: """ Check if we can apply fault injection configuration and eventually does it. @@ -415,7 +419,7 @@ async def _apply_fault_injection(self, fault_prob: int) -> None: warn_msg = "Run as root to use kernel fault injection" else: if await self._sut.is_fault_injection_enabled(): - await self._sut.setup_fault_injection(fault_prob) + await self._sut.setup_fault_injection(fault_prob, fault_interval) else: if fault_prob != 0: warn_msg = "Fault injection is not enabled. Running tests normally" @@ -436,6 +440,7 @@ async def run( randomize: bool = False, runtime: float = 0, fault_prob: int = 0, + fault_interval: int = 1, ) -> None: """ Run a new session and store results inside a JSON file. @@ -460,6 +465,8 @@ async def run( :type runtime: float :param fault_prob: Fault injection probability. :type fault_prob: int + :param fault_interval: Fault injection interval. + :type fault_interval: int """ async with self._run_lock: await libkirk.events.fire("session_started", suites, self._tmpdir.abspath) @@ -477,7 +484,7 @@ async def run( await self._exec_command(command) if fault_prob != 0: - await self._apply_fault_injection(fault_prob) + await self._apply_fault_injection(fault_prob, fault_interval) if suites: suites_obj = await self._read_suites( diff --git a/libkirk/sut.py b/libkirk/sut.py index 20b1052..f80b43f 100644 --- a/libkirk/sut.py +++ b/libkirk/sut.py @@ -370,18 +370,24 @@ async def is_fault_injection_enabled(self) -> bool: return True - async def setup_fault_injection(self, prob: int) -> None: + async def setup_fault_injection( + self, + prob: int, + interval: int = 1, + ) -> None: """ Configure kernel fault injection. When prob is zero, the fault injection is set to default values. - :param prob: Fault probabilty in between 0-100. + :param prob: Fault probability in between 0-100. :type prob: int + :param interval: Fault interval. + :type interval: int """ if not await self.is_running(): raise SUTError("SUT is not running") - interval = 1 if prob == 0 else 100 + interval = 1 if prob == 0 else interval times = 1 if prob == 0 else -1 async def _set_value(value: int, path: str) -> None: diff --git a/libkirk/tests/test_main.py b/libkirk/tests/test_main.py index 8fb5ba3..5e44f5a 100644 --- a/libkirk/tests/test_main.py +++ b/libkirk/tests/test_main.py @@ -110,6 +110,16 @@ def test_finjection_config_over_100(self): def test_finjection_config_negative(self): assert libkirk.main._finjection_config("-5") == 0 + + def test_finterval_config_empty(self): + assert libkirk.main._finterval_config("") == 1 + + def test_finterval_config_negative(self): + assert libkirk.main._finterval_config("-5") == 1 + + @pytest.mark.parametrize("val", ("1", "20", "100", "2000")) + def test_finterval_config(self, val): + assert libkirk.main._finterval_config(val) == int(val) def test_get_skip_tests_empty(self): assert libkirk.main._get_skip_tests("", "") == ""