diff --git a/munet/base.py b/munet/base.py index e77eb15..5c9cd2c 100644 --- a/munet/base.py +++ b/munet/base.py @@ -940,7 +940,15 @@ def _cmd_status_finish(self, p, c, ac, o, e, raises, warn): raise CalledProcessError(rc, ac, o, e) return rc, o, e - def _cmd_status(self, cmds, raises=False, warn=True, stdin=None, **kwargs): + def _cmd_status( + self, + cmds, + raises=False, + warn=True, + stdin=None, + output=True, + **kwargs + ): """Execute a command.""" timeout = None if "timeout" in kwargs: @@ -949,7 +957,11 @@ def _cmd_status(self, cmds, raises=False, warn=True, stdin=None, **kwargs): pinput, stdin = Commander._cmd_status_input(stdin) p, actual_cmd = self._popen("cmd_status", cmds, stdin=stdin, **kwargs) - o, e = p.communicate(pinput, timeout=timeout) + if output: + o, e = p.communicate(pinput, timeout=timeout) + else: + o = '' + e = '' return self._cmd_status_finish(p, cmds, actual_cmd, o, e, raises, warn) async def _async_cmd_status( diff --git a/munet/mutest/userapi.py b/munet/mutest/userapi.py index abc63af..24cfb11 100644 --- a/munet/mutest/userapi.py +++ b/munet/mutest/userapi.py @@ -431,6 +431,7 @@ def _command( self, target: str, cmd: str, + **kwargs, ) -> str: """Execute a ``cmd`` and return result. @@ -439,7 +440,7 @@ def _command( cmd: string to execut on the target. """ out = self.targets[target].cmd_nostatus( - cmd, stdin=subprocess.DEVNULL, warn=False + cmd, stdin=subprocess.DEVNULL, warn=False, **kwargs ) self.last = out = out.rstrip() report = out if out else "" @@ -742,20 +743,26 @@ def section(self, desc: str): self.oplogf(" section setting __in_section to True") self.__print_header(self.info.tag, desc, add_nl) - def step(self, target: str, cmd: str) -> str: + def step( + self, + target: str, + cmd: str, + output: bool = True, + ) -> str: """See :py:func:`~munet.mutest.userapi.step`. :meta private: """ self.logf( - "#%s.%s:%s:STEP:%s:%s", + "#%s.%s:%s:STEP:%s:%s:%s", self.tag, self.steps + 1, self.info.path, target, cmd, + output, ) - return self._command(target, cmd) + return self._command(target, cmd, output=output) def step_json(self, target: str, cmd: str) -> Union[list, dict]: """See :py:func:`~munet.mutest.userapi.step_json`. @@ -1007,17 +1014,18 @@ def get_target(name: str) -> Commander: return TestCase.g_tc.targets[name] -def step(target: str, cmd: str) -> str: +def step(target: str, cmd: str, output: bool = True) -> str: """Execute a ``cmd`` on a ``target`` and return the output. Args: target: the target to execute the ``cmd`` on. cmd: string to execute on the target. + output: if False, then DO NOT wait for output. Otherwise waits for ``cmd`` completion. Returns: Returns the ``str`` output of the ``cmd``. """ - return TestCase.g_tc.step(target, cmd) + return TestCase.g_tc.step(target, cmd, output) def step_json(target: str, cmd: str) -> Union[list, dict]: diff --git a/tests/mutest/mutest_step.py b/tests/mutest/mutest_step.py new file mode 100644 index 0000000..3578c26 --- /dev/null +++ b/tests/mutest/mutest_step.py @@ -0,0 +1,9 @@ +"""Test that out-of-order cmd execution is supported by step""" +from munet.mutest.userapi import wait_step, section, step + +section("Test the no-output arg in step") + +step('r1', 'touch test-file1; sleep 1; mv test-file1 test-file2', output=False) + +wait_step('r1', 'ls', 'test-file1', 'Saw test-file1', 2, 0.1) +wait_step('r1', 'ls', 'test-file2', 'Saw test-file2', 2, 0.1)