moonchen commented on code in PR #13540:
URL: https://github.com/apache/trafficserver/pull/13540#discussion_r3898261964
##########
tests/autest-parallel.py.in:
##########
@@ -227,6 +227,37 @@ def strip_ansi(text: str) -> str:
return ansi_escape.sub('', text)
+def parse_test_completion(line: str) -> Optional[Tuple[str, str]]:
+ """Extract a completed test name and status from an autest progress
line."""
+ clean = strip_ansi(line).strip()
+ marker = 'Running Test '
+ marker_pos = clean.rfind(marker)
+
+ if marker_pos < 0:
+ return None
+
+ completion = clean[marker_pos + len(marker):]
+ match = re.match(r'([^:\s]+):.*\b(Passed|Failed|Skipped)\s*$', completion,
re.IGNORECASE)
Review Comment:
AuTest 1.10.6 can finish a test as Unknown, Skipped, Passed, Warning,
Failed, or Exception, but this regex and parse_detached_test_status accept only
three. When Warning, Exception, or Unknown is skipped, last_completion is not
advanced, so that test runtime is added to the next recognized test and the
corrupted duration is saved for future partitioning. Please recognize all
terminal statuses here and update short_status accordingly.
##########
tests/autest-parallel.py.in:
##########
@@ -517,151 +548,150 @@ def run_worker(
existing = env.get('PYTHONPATH', '')
env['PYTHONPATH'] = ':'.join(pythonpath_dirs + ([existing] if existing
else []))
- if collect_timings:
- # Run tests one at a time to collect accurate timing
- all_output = []
- total_tests = len(tests)
- try:
- for idx, test in enumerate(tests, 1):
- test_name, duration, status, output = run_single_test(
- test, script_dir, sandbox, ats_bin, build_root,
extra_args, env)
- result.test_timings[test_name] = duration
- all_output.append(output)
-
- if status == "PASS":
- result.passed += 1
- elif status == "SKIP":
- result.skipped += 1
- else:
- result.failed += 1
- result.failed_tests.append(test_name)
+ # Keep all tests in one autest process so its shared port queue is not
+ # reset between tests. This is both faster and avoids reusing ports that a
+ # recently completed test may still hold.
+ cmd = [
+ 'uv',
+ 'run',
+ 'autest',
+ 'run',
+ '--directory',
+ '${CMAKE_GOLD_DIR}',
+ '--ats-bin',
+ ats_bin,
+ '--proxy-verifier-bin',
+ '${PROXY_VERIFIER_PATH}',
+ '--build-root',
+ build_root,
+ '--sandbox',
+ str(sandbox),
+ '--filters',
+ ]
+ cmd.extend(f'/{test}' for test in tests)
+ cmd.extend(extra_args)
- timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
- # Fixed-width format: date time status duration worker
progress test_name
- print(
- f"{timestamp} {status:4s} {duration:6.1f}s
Worker:{worker_id:2d} {idx:2d}/{total_tests:2d} {test}", flush=True)
- except KeyboardInterrupt:
- result.return_code = 130
+ 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)
- result.output = "\n".join(all_output)
- if result.return_code != 130:
- result.return_code = 0 if result.failed == 0 else 1
- else:
- # Run all tests in batch (faster but no per-test timing)
- cmd = [
- 'uv',
- 'run',
- 'autest',
- 'run',
- '--directory',
- '${CMAKE_GOLD_DIR}',
- '--ats-bin',
- ats_bin,
- '--proxy-verifier-bin',
- '${PROXY_VERIFIER_PATH}',
- '--build-root',
- build_root,
- '--sandbox',
- str(sandbox),
- ]
-
- # Add test filters
- cmd.append('--filters')
- cmd.extend(tests)
-
- # Add any extra arguments
- cmd.extend(extra_args)
-
- 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:
+ if verbose or collect_timings:
+ # Autest flushes each completed test line. Observe those lines to
+ # collect timings without changing how autest executes the batch.
+ proc = subprocess.Popen(
+ cmd,
+ cwd=script_dir,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT,
+ text=True,
+ env=env,
+ )
+ output_lines = []
+ last_completion = time.monotonic()
+ completed_count = 0
+ pending_test = None
+ try:
+ for line in proc.stdout:
Review Comment:
The timeout below only starts after stdout reaches EOF. If a test wedges
while keeping the pipe open, this blocking iteration never finishes;
collect-timings has therefore lost the previous 600-second per-test bound, and
as_completed waits forever as well. Please enforce a wall-clock timeout while
consuming stdout and terminate the child when it expires.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]