From 2d4797640a4f00beae2214413afcdd3b32fcb639 Mon Sep 17 00:00:00 2001 From: Richard Alpe Date: Mon, 11 May 2026 13:37:17 +0200 Subject: [PATCH 1/2] Don't include suites in overall test count (uniq_id) Suites are not tests. So they should not really be counted. I can't see anywhere the ID is used for suites other than in the printouts. Signed-off-by: Richard Alpe --- 9pm.py | 50 ++++++++++++++++++++++++++++++++---------------- report.py | 12 +++++++++--- self_test/run.py | 43 +++++++++++++++++++++-------------------- 3 files changed, 65 insertions(+), 40 deletions(-) diff --git a/9pm.py b/9pm.py index 93d6b4b..e832b95 100755 --- a/9pm.py +++ b/9pm.py @@ -16,7 +16,8 @@ import hashlib from datetime import datetime -TEST_CNT=0 +TEST_CNT = 0 +SUITE_CNT = 0 ROOT_PATH = os.path.dirname(os.path.realpath(__file__)) # TODO: proper argument strucutre DATABASE = "" @@ -39,9 +40,10 @@ class pcolor: faint = '\033[2m' def cprint(color, *args, **kwargs): + end = kwargs.pop('end', '\n') sys.stdout.write(color) - print(*args, **kwargs) - sys.stdout.write(pcolor.reset) + print(*args, **kwargs, end='') + sys.stdout.write(pcolor.reset + end) def vcprint(color, *args, **kwargs): global VERBOSE @@ -171,7 +173,7 @@ def run_test(args, test): name = test['name'] path = os.path.relpath(test['case'], ROOT_PATH) - print(f"\n{pcolor.blue}Starting test {test['uniq_id']} {name} ({path}){pcolor.reset}") + print(f"\n{pcolor.blue}Starting test: \"{test['uniq_id']} {name}\" ({path}){pcolor.reset}") if test['result'] == "skip": print(f"{pcolor.yellow}Skip test {name} (suite skip){pcolor.reset}") @@ -228,6 +230,11 @@ def prefix_name(name): TEST_CNT += 1 return str(TEST_CNT).zfill(4), slugify(name, lowercase=True) +def next_suite_num(): + global SUITE_CNT + SUITE_CNT += 1 + return SUITE_CNT + def gen_name(filepath): return os.path.basename(filepath) @@ -282,16 +289,8 @@ def parse_suite(suite_path, parent_suite_path, options, settings, name=None): suite['result'] = "pending" suite_dirname = os.path.dirname(suite_path) - if name: - uniq_id, uname = prefix_name(name) - suite['uniq_id'] = uniq_id - suite['unix_name'] = uniq_id + "-" + uname - suite['name'] = name - else: - uniq_id, uname = gen_unix_name(suite_path) - suite['uniq_id'] = uniq_id - suite['unix_name'] = uniq_id + "-" + uname - suite['name'] = gen_name(suite_path) + suite['name'] = name if name else gen_name(suite_path) + suite['suite_num'] = next_suite_num() if not os.path.isfile(suite_path): print(f"error, test suite not found {suite_path}") @@ -512,7 +511,10 @@ def print_result_tree(data, base): sign = "?" color = pcolor.yellow - print(f"{base}{prefix}{color}{sign} {test['uniq_id']} {test['name']}{pcolor.reset}") + if 'case' in test: + print(f"{base}{prefix}{color}{sign} {test['uniq_id']} {test['name']}{pcolor.reset}") + else: + print(f"{base}{prefix}{color}{sign} {test['name']}{pcolor.reset}") if 'suite' in test: print_result_tree(test, nextbase) @@ -530,12 +532,25 @@ def probe_suite(data): data['result'] = "noexec" +def count_suite_tree(data): + suites = 0 + tests = 0 + for node in data['suite']: + if 'suite' in node: + suites += 1 + s, t = count_suite_tree(node) + suites += s + tests += t + elif 'case' in node: + tests += 1 + return suites, tests + def run_suite(args, data, skip_suite): skip = False err = False if data['name'] != "command-line": - print(pcolor.blue + f"\nRunning suite {data['uniq_id']} {data['name']}" + pcolor.reset) + print(pcolor.blue + f"\nRunning suite {data['suite_num']}: {data['name']}" + pcolor.reset) for test in data['suite']: if 'suite' in test: @@ -828,6 +843,9 @@ def main(): suite = create_base_suite(args) probe_suite(suite) + n_suites, n_tests = count_suite_tree(suite) + print(f"\nStarting: {n_suites} suites with {n_tests} tests") + setup_env(args) skip, err = run_suite(args, suite, False) diff --git a/report.py b/report.py index f282520..2966c84 100755 --- a/report.py +++ b/report.py @@ -177,8 +177,10 @@ def _write_result_tree(self, data, depth): line = f"{indent}{stars} {self._resultfmt(test.get('result', 'unknown'))}" if 'outfile' in test: line += f" <>" - else: + elif test.get('uniq_id'): line += f" {test.get('uniq_id')} {test.get('name')}" + else: + line += f" {test.get('name')}" content.append(line) @@ -277,7 +279,9 @@ def _write_tree(self, data, depth): for test in data['suite']: mark = icon_map.get(test.get('result', ''), "") - line = f"{' ' * depth}- {mark} : {test.get('uniq_id')} {test.get('name')}" + uid = test.get('uniq_id') + uid_str = f" {uid}" if uid else "" + line = f"{' ' * depth}- {mark} :{uid_str} {test.get('name')}" content.append(line) if 'suite' in test: @@ -307,7 +311,9 @@ def _write_tree(self, data, depth): for test in data['suite']: result = test.get('result', 'UNKNOWN').upper() - line = f"{' ' * depth}- {result} : {test.get('uniq_id')} {test.get('name')}" + uid = test.get('uniq_id') + uid_str = f" {uid}" if uid else "" + line = f"{' ' * depth}- {result} :{uid_str} {test.get('name')}" content.append(line) if 'suite' in test: diff --git a/self_test/run.py b/self_test/run.py index f1aa669..0760367 100755 --- a/self_test/run.py +++ b/self_test/run.py @@ -119,9 +119,9 @@ def test_suites(self): "args": [], "tests": ["suites/suite.yaml"], "expected": [ + {"name": "0001-worker", "args": []}, {"name": "0002-worker", "args": []}, - {"name": "0003-worker", "args": []}, - {"name": "0004-worker1", "args": []}, + {"name": "0003-worker1", "args": []}, ], } ) @@ -132,9 +132,9 @@ def test_suites(self): "args": [], "tests": ["suites/names.yaml"], "expected": [ - {"name": "0002-my-worker", "args": []}, - {"name": "0003-worker", "args": []}, - {"name": "0004-my-worker1", "args": []}, + {"name": "0001-my-worker", "args": []}, + {"name": "0002-worker", "args": []}, + {"name": "0003-my-worker1", "args": []}, ], } ) @@ -144,9 +144,9 @@ def test_suites(self): "args": ["-o", "cmdline"], "tests": ["suites/options.yaml"], "expected": [ - {"name": "0002-worker", "args": ["cmdline"]}, - {"name": "0003-worker", "args": ["opt1", "opt2", "cmdline"]}, - {"name": "0004-worker", "args": [ + {"name": "0001-worker", "args": ["cmdline"]}, + {"name": "0002-worker", "args": ["opt1", "opt2", "cmdline"]}, + {"name": "0003-worker", "args": [ f"{os.path.join(self.script_dir, 'suites/foo')}", "cmdline"] }, ], @@ -159,10 +159,10 @@ def test_suites(self): "args": ["-o", "cmdline"], "tests": ["suites/top-options.yaml"], "expected": [ - {"name": "0002-worker", "args": ["top1", "cmdline"]}, - {"name": "0004-worker", "args": ["top2", "cmdline"]}, + {"name": "0001-worker", "args": ["top1", "cmdline"]}, + {"name": "0002-worker", "args": ["top2", "cmdline"]}, { - "name": "0005-worker", + "name": "0003-worker", "args": ["opt1", "opt2", "top2", "cmdline"], }, ], @@ -175,13 +175,13 @@ def test_suites(self): "args": [], "tests": ["suites/top-suite.yaml"], "expected": [ + {"name": "0001-worker", "args": []}, {"name": "0002-worker", "args": []}, + {"name": "0003-worker", "args": []}, {"name": "0004-worker", "args": []}, - {"name": "0006-worker", "args": []}, - {"name": "0007-worker", "args": []}, - {"name": "0008-worker1", "args": []}, - {"name": "0009-worker1", "args": []}, - {"name": "0010-worker1", "args": []}, + {"name": "0005-worker1", "args": []}, + {"name": "0006-worker1", "args": []}, + {"name": "0007-worker1", "args": []}, ], } ) @@ -319,13 +319,14 @@ def test_repeat_flag(self): "args": ["-r", "2"], "tests": ["suites/suite.yaml", "cases/worker1.py"], "expected": [ + {"name": "0001-worker", "args": []}, {"name": "0002-worker", "args": []}, - {"name": "0003-worker", "args": []}, + {"name": "0003-worker1", "args": []}, {"name": "0004-worker1", "args": []}, - {"name": "0007-worker", "args": []}, - {"name": "0008-worker", "args": []}, - {"name": "0009-worker1", "args": []}, - {"name": "0010-worker1", "args": []} + {"name": "0005-worker", "args": []}, + {"name": "0006-worker", "args": []}, + {"name": "0007-worker1", "args": []}, + {"name": "0008-worker1", "args": []} ], } ) From 4abf00f56b238ddd145ecb19404e8e258ec22258 Mon Sep 17 00:00:00 2001 From: Richard Alpe Date: Mon, 11 May 2026 14:47:05 +0200 Subject: [PATCH 2/2] Store unique test id as integer Pad it upon use and store it as integer. Signed-off-by: Richard Alpe --- 9pm.py | 12 ++++++------ report.py | 13 +++++++------ 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/9pm.py b/9pm.py index e832b95..2fe9431 100755 --- a/9pm.py +++ b/9pm.py @@ -173,7 +173,7 @@ def run_test(args, test): name = test['name'] path = os.path.relpath(test['case'], ROOT_PATH) - print(f"\n{pcolor.blue}Starting test: \"{test['uniq_id']} {name}\" ({path}){pcolor.reset}") + print(f"\n{pcolor.blue}Starting test {test['uniq_id']}: \"{test['uniq_id']:04d} {name}\" ({path}){pcolor.reset}") if test['result'] == "skip": print(f"{pcolor.yellow}Skip test {name} (suite skip){pcolor.reset}") @@ -228,7 +228,7 @@ def slugify(text, lowercase=True): def prefix_name(name): global TEST_CNT TEST_CNT += 1 - return str(TEST_CNT).zfill(4), slugify(name, lowercase=True) + return TEST_CNT, slugify(name, lowercase=True) def next_suite_num(): global SUITE_CNT @@ -324,12 +324,12 @@ def parse_suite(suite_path, parent_suite_path, options, settings, name=None): if 'name' in entry: uniq_id, uname = prefix_name(entry['name']) case['uniq_id'] = uniq_id - case['unix_name'] = uniq_id + "-" + uname + case['unix_name'] = f"{uniq_id:04d}-{uname}" case['name'] = entry['name'] else: uniq_id, uname = gen_unix_name(entry['case']) case['uniq_id'] = uniq_id - case['unix_name'] = uniq_id + "-" + uname + case['unix_name'] = f"{uniq_id:04d}-{uname}" case['name'] = gen_name(entry['case']) case['outfile'] = gen_outfile(case['unix_name']) @@ -512,7 +512,7 @@ def print_result_tree(data, base): color = pcolor.yellow if 'case' in test: - print(f"{base}{prefix}{color}{sign} {test['uniq_id']} {test['name']}{pcolor.reset}") + print(f"{base}{prefix}{color}{sign} {test['uniq_id']:04d} {test['name']}{pcolor.reset}") else: print(f"{base}{prefix}{color}{sign} {test['name']}{pcolor.reset}") @@ -789,7 +789,7 @@ def create_base_suite(args): test['case'] = fpath uniq_id, uname = gen_unix_name(filename) test['uniq_id'] = uniq_id - test['unix_name'] = uniq_id + "-" + uname + test['unix_name'] = f"{uniq_id:04d}-{uname}" test['name'] = gen_name(filename) test['outfile'] = gen_outfile(test['unix_name']) diff --git a/report.py b/report.py index 2966c84..da268b2 100755 --- a/report.py +++ b/report.py @@ -175,10 +175,11 @@ def _write_result_tree(self, data, depth): stars = '*' + '*' * depth line = f"{indent}{stars} {self._resultfmt(test.get('result', 'unknown'))}" + uid = test.get('uniq_id') if 'outfile' in test: - line += f" <>" - elif test.get('uniq_id'): - line += f" {test.get('uniq_id')} {test.get('name')}" + line += f" <>" + elif uid is not None: + line += f" {uid:04d} {test.get('name')}" else: line += f" {test.get('name')}" @@ -217,7 +218,7 @@ def _write_output_sections(self, data, depth, is_first=True): "\n==== Test Information", '[cols="1h,3"]', "|===", - f"| ID | `{test.get('uniq_id')}`", + f"| ID | `{test.get('uniq_id'):04d}`", f"| Name | `{test.get('name')}`" ]) @@ -280,7 +281,7 @@ def _write_tree(self, data, depth): for test in data['suite']: mark = icon_map.get(test.get('result', ''), "") uid = test.get('uniq_id') - uid_str = f" {uid}" if uid else "" + uid_str = f" {uid:04d}" if uid is not None else "" line = f"{' ' * depth}- {mark} :{uid_str} {test.get('name')}" content.append(line) @@ -312,7 +313,7 @@ def _write_tree(self, data, depth): for test in data['suite']: result = test.get('result', 'UNKNOWN').upper() uid = test.get('uniq_id') - uid_str = f" {uid}" if uid else "" + uid_str = f" {uid:04d}" if uid is not None else "" line = f"{' ' * depth}- {result} :{uid_str} {test.get('name')}" content.append(line)