diff --git a/src/testium/api/console.py b/src/testium/api/console.py index 28ca177..4f4dc93 100755 --- a/src/testium/api/console.py +++ b/src/testium/api/console.py @@ -127,13 +127,11 @@ A {classname}.close() is missing somewhere in your code !'.format(classname=type # c = '' return c - # Upper bound (in characters) of the accumulated buffer tail scanned in - # regex mode, so cost/memory stay bounded on long-running streams. + # Max chars of the buffer tail scanned in regex mode (bounds cost/memory). REGEX_WINDOW = 65536 def _feed_match(self, data, search_deques, match_deques, matches): - """Append *data* to every rolling window and return the first matched - pattern string, or None if none completed on this character.""" + """Append *data* to each window; return the first matched pattern or None.""" matched = None for sd, md, m in zip(search_deques, match_deques, matches): sd.append(data) @@ -142,8 +140,7 @@ A {classname}.close() is missing somewhere in your code !'.format(classname=type return matched def _search_regex(self, read_data, compiled): - """Search the (bounded) tail of *read_data* with each compiled regex; - return the matched text of the first hit, or None.""" + """Search the buffer tail with each regex; return the first hit's text or None.""" tail = read_data[-self.REGEX_WINDOW:] for p in compiled: m = p.search(tail) @@ -171,8 +168,7 @@ A {classname}.close() is missing somewhere in your code !'.format(classname=type if not match: raise ETUMRuntimeError("'expected' pattern can not be empty") - # match may be a single string or a list/tuple of strings: the read - # succeeds as soon as ANY of them is seen in the stream. + # match: a string or list of strings; succeed as soon as any is seen. if isinstance(match, (list, tuple)): matches = [str(m) for m in match] else: @@ -195,8 +191,7 @@ A {classname}.close() is missing somewhere in your code !'.format(classname=type raise ETUMRuntimeError( "Invalid regular expression {!r}: {}".format(m, e)) from None else: - # One fixed-length rolling window per match pattern, compared - # against the corresponding pattern deque. + # One fixed-length rolling window per literal pattern. search_deques = [collections.deque(maxlen=len(m)) for m in matches] match_deques = [collections.deque(m) for m in matches] self._matched = None diff --git a/src/testium/interpreter/test_items/test_item.py b/src/testium/interpreter/test_items/test_item.py index 63ac2f3..4320da8 100644 --- a/src/testium/interpreter/test_items/test_item.py +++ b/src/testium/interpreter/test_items/test_item.py @@ -145,7 +145,7 @@ class TestItem: self._report_key = None self._reported = None self.status_queue = status_queue - self._execute_on_stop = False + self._execute_on_stop_raw = False self._post_eval = None self._store_result = None self._expected_result = None @@ -154,7 +154,7 @@ class TestItem: self._is_running = False self._is_breakpoint = False self._is_paused = False - self._stop_on_failure = False + self._stop_on_failure_raw = False self._doc = "" self._name = "" self.report = None @@ -197,13 +197,14 @@ class TestItem: self.skipped = False self._report_key = self._prms.getParam("key", default=None) - self._stop_on_failure = self._prms.getParam( - "stop_on_failure", default=False, processed=True + # Kept raw: expanded at run time by the matching properties. + self._stop_on_failure_raw = self._prms.getParam( + "stop_on_failure", default=False ) self._doc = self._prms.getParam("doc", default="", processed=True) # - self._execute_on_stop = self._prms.getParam( - "execute_on_stop", default=False, processed=True + self._execute_on_stop_raw = self._prms.getParam( + "execute_on_stop", default=False ) if "process_result" in dict_item: @@ -570,6 +571,20 @@ class TestItem: def setEnabled(self): self.enabled = True + def _eval_flag(self, raw): + """Run-time flag: bool as-is, otherwise expanded and coerced to bool.""" + if isinstance(raw, bool): + return raw + return eval_to_boolean(self._prms.expanse(raw)) + + @property + def _stop_on_failure(self): + return self._eval_flag(self._stop_on_failure_raw) + + @property + def _execute_on_stop(self): + return self._eval_flag(self._execute_on_stop_raw) + def executedOnStop(self): return self._execute_on_stop diff --git a/src/testium/interpreter/test_items/test_item_console.py b/src/testium/interpreter/test_items/test_item_console.py index 78d5fc2..7c349a7 100644 --- a/src/testium/interpreter/test_items/test_item_console.py +++ b/src/testium/interpreter/test_items/test_item_console.py @@ -88,7 +88,7 @@ class TestItemConsoleOpen(TestItemConsoleAction): telnet_host = self._prms.getParam( "telnet_host", required=True, processed=True ) - telnet_port = self._prms.getParam("telnet_port", default=69) + telnet_port = self._prms.getParam("telnet_port", default=69, processed=True) elif self._protocol == "ssh": if tm.OS() == "Windows": @@ -226,8 +226,7 @@ class TestItemConsoleOpen(TestItemConsoleAction): cons.open() self.result.set(TestValue.SUCCESS) except ETUMRuntimeError as e: - # Expected, user-facing console error (device missing, no permission, - # …): report a single clear line, no traceback. + # Expected console error (device missing, no permission…): one line. msg = "Impossible to open the console '{}': {}".format(cname, e._message) self.result.set(result=TestValue.FAILURE, message=msg) print(msg) diff --git a/src/testium/interpreter/test_items/test_item_cycle.py b/src/testium/interpreter/test_items/test_item_cycle.py index bc8ccb8..632e382 100644 --- a/src/testium/interpreter/test_items/test_item_cycle.py +++ b/src/testium/interpreter/test_items/test_item_cycle.py @@ -51,11 +51,8 @@ class TestItemCycle(TestItem): self._niter = None if "iterator" in dict_cycle: + # Kept raw: expanded at run time in execute(). self._iter = dict_cycle["iterator"] - - if isinstance(self._iter, str): - self._iter = self._prms.expanse(self._iter) - else: self._iter = None diff --git a/src/testium/interpreter/test_items/test_item_git.py b/src/testium/interpreter/test_items/test_item_git.py index e3ec57d..f984a5c 100644 --- a/src/testium/interpreter/test_items/test_item_git.py +++ b/src/testium/interpreter/test_items/test_item_git.py @@ -21,7 +21,8 @@ class TestItemGit(TestItem): super().__init__(dict_item, parent, status_queue, filename=filename) self._type = cst.TYPE_GIT self.is_container = False - self.repo = self._prms.getParamAll('repo', processed=True, required=True) + # Kept raw: each repo entry is expanded at run time in execute(). + self.repo = self._prms.getParamAll('repo', required=True) @test_run def execute(self): diff --git a/src/testium/interpreter/test_items/test_item_tested_references.py b/src/testium/interpreter/test_items/test_item_tested_references.py index 5dbf982..637f255 100644 --- a/src/testium/interpreter/test_items/test_item_tested_references.py +++ b/src/testium/interpreter/test_items/test_item_tested_references.py @@ -26,13 +26,14 @@ class TestItemTestedRefsDialog(TestItemDialogBase): self.is_container = False with item_load_context(self.cmd(), self.name(), self.seqFilename()): self._question = self._prms.getParam('question', required=True) - self._init_values = self._prms.getParamAll('reference', required=False, processed=True) + # Kept raw: expanded at run time in execute(). + self._init_values = self._prms.getParamAll('reference', required=False) self._auto_result = self._prms.getParam('auto_result', required=False, default=None) @test_run def execute(self): q = self._prms.expanse(self._question) - init_values = ','.join(self._init_values) + init_values = ','.join(self._prms.expanse(v) for v in self._init_values) if _is_text_mode(): print(f"References: {q}") rows = init_values.split(',') if init_values else ['']