This is an automated email from the ASF dual-hosted git repository. bcall pushed a commit to branch parallel-autest in repository https://gitbox.apache.org/repos/asf/trafficserver.git
commit e1318fcd9352d141046b03b06f6df442ba94d6e5 Author: Bryan Call <[email protected]> AuthorDate: Sat Feb 7 20:38:51 2026 -0800 Improve verbose mode for interactive use - In batch mode with -v, stream autest output in real-time using Popen instead of subprocess.run, showing "Running Test..." lines as they happen - Print test list preview per worker during partitioning (-v) - Show timestamps and skipped counts in worker completion messages - Print first 5 test names per worker at batch start (-v) --- tests/autest-parallel.py | 64 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 50 insertions(+), 14 deletions(-) diff --git a/tests/autest-parallel.py b/tests/autest-parallel.py index 9500b1aba8..fad0d057c2 100755 --- a/tests/autest-parallel.py +++ b/tests/autest-parallel.py @@ -477,18 +477,44 @@ def run_worker( timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") print(f"{timestamp} Worker:{worker_id:2d} Starting batch of {len(tests)} tests (port offset {port_offset})", flush=True) + if verbose: + print(f" Worker:{worker_id:2d} Tests: {', '.join(tests[:5])}" + f"{'...' if len(tests) > 5 else ''}", flush=True) try: - proc = subprocess.run( - cmd, - cwd=script_dir, - capture_output=True, - text=True, - env=env, - timeout=3600 # 1 hour timeout per worker - ) - result.output = proc.stdout + proc.stderr - result.return_code = proc.returncode + if verbose: + # Stream output in real-time so the user sees test progress + proc = subprocess.Popen( + cmd, + cwd=script_dir, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + text=True, + env=env, + ) + output_lines = [] + for line in proc.stdout: + output_lines.append(line) + # Print lines that show test progress + clean = strip_ansi(line).strip() + if clean.startswith('Running Test') or 'Passed' in clean or 'Failed' in clean: + if clean.startswith('Running Test'): + ts = datetime.now().strftime("%H:%M:%S") + print(f" [{ts}] Worker:{worker_id:2d} {clean}", flush=True) + proc.wait(timeout=3600) + result.output = ''.join(output_lines) + result.return_code = proc.returncode + else: + proc = subprocess.run( + cmd, + cwd=script_dir, + capture_output=True, + text=True, + env=env, + timeout=3600 # 1 hour timeout per worker + ) + result.output = proc.stdout + proc.stderr + result.return_code = proc.returncode # Parse results parsed = parse_autest_output(result.output) @@ -504,7 +530,7 @@ def run_worker( # autest likely errored at setup (e.g., missing proxy verifier). # Count all tests as failed to avoid false positives. total_ran = result.passed + result.failed + result.skipped - if total_ran == 0 and proc.returncode != 0: + if total_ran == 0 and (hasattr(proc, 'returncode') and proc.returncode != 0): result.failed = len(tests) result.failed_tests = list(tests) @@ -767,11 +793,18 @@ Examples: print(f"Using timing-based load balancing") if args.verbose: for i, load in enumerate(expected_loads): - print(f" Worker {i}: {len(partitions[i])} tests, ~{load:.1f}s expected") + tests_preview = ', '.join(partitions[i][:3]) + suffix = f", ... (+{len(partitions[i])-3} more)" if len(partitions[i]) > 3 else "" + print(f" Worker {i}: {len(partitions[i])} tests, ~{load:.1f}s expected [{tests_preview}{suffix}]") else: # Fall back to simple round-robin partitioning partitions = partition_tests(parallel_tests, num_jobs) print(f"Using round-robin partitioning") + if args.verbose: + for i in range(len(partitions)): + tests_preview = ', '.join(partitions[i][:3]) + suffix = f", ... (+{len(partitions[i])-3} more)" if len(partitions[i]) > 3 else "" + print(f" Worker {i}: {len(partitions[i])} tests [{tests_preview}{suffix}]") else: partitions = [] @@ -819,8 +852,11 @@ Examples: result = future.result() results.append(result) status = "PASS" if result.failed == 0 else "FAIL" - print(f"[Worker {worker_id}] Completed: {result.passed} passed, " - f"{result.failed} failed ({result.duration:.1f}s) [{status}]") + ts = datetime.now().strftime("%H:%M:%S") + parts = [f"{result.passed} passed", f"{result.failed} failed"] + if result.skipped > 0: + parts.append(f"{result.skipped} skipped") + print(f"[{ts}] Worker:{worker_id:2d} Done: {', '.join(parts)} ({result.duration:.1f}s) [{status}]") except Exception as e: print(f"[Worker {worker_id}] Error: {e}", file=sys.stderr) results.append(TestResult(
