test: Remove polling loop from test_runner

This commit is contained in:
MarcoFalke committed 2025-09-03 10:30:16 +02:00
1 parent fd813bf863
commit fa4885ef2f
1 file changed
+46 -33
+46 -33
View File
@@ -14,6 +14,7 @@ For a description of arguments recognized by test scripts, see
import argparse import argparse
from collections import deque from collections import deque
from concurrent import futures
import configparser import configparser
import csv import csv
import datetime import datetime
@@ -703,15 +704,15 @@ class TestHandler:
""" """
Trigger the test scripts passed in via the list. Trigger the test scripts passed in via the list.
""" """
def __init__(self, *, num_tests_parallel, tests_dir, tmpdir, test_list, flags, use_term_control): def __init__(self, *, num_tests_parallel, tests_dir, tmpdir, test_list, flags, use_term_control):
assert num_tests_parallel >= 1 assert num_tests_parallel >= 1
self.executor = futures.ThreadPoolExecutor(max_workers=num_tests_parallel)
self.num_jobs = num_tests_parallel self.num_jobs = num_tests_parallel
self.tests_dir = tests_dir self.tests_dir = tests_dir
self.tmpdir = tmpdir self.tmpdir = tmpdir
self.test_list = test_list self.test_list = test_list
self.flags = flags self.flags = flags
self.jobs = [] self.jobs = {}
self.use_term_control = use_term_control self.use_term_control = use_term_control
def done(self): def done(self):
@@ -728,47 +729,59 @@ class TestHandler:
test_argv = test.split() test_argv = test.split()
testdir = "{}/{}_{}".format(self.tmpdir, re.sub(".py$", "", test_argv[0]), portseed) testdir = "{}/{}_{}".format(self.tmpdir, re.sub(".py$", "", test_argv[0]), portseed)
tmpdir_arg = ["--tmpdir={}".format(testdir)] tmpdir_arg = ["--tmpdir={}".format(testdir)]
self.jobs.append((test,
time.time(), def proc_wait(task):
subprocess.Popen([sys.executable, self.tests_dir + test_argv[0]] + test_argv[1:] + self.flags + portseed_arg + tmpdir_arg, task[2].wait()
text=True, return task
stdout=log_stdout,
stderr=log_stderr), task = [
testdir, test,
log_stdout, time.time(),
log_stderr)) subprocess.Popen(
[sys.executable, self.tests_dir + test_argv[0]] + test_argv[1:] + self.flags + portseed_arg + tmpdir_arg,
text=True,
stdout=log_stdout,
stderr=log_stderr,
),
testdir,
log_stdout,
log_stderr,
]
fut = self.executor.submit(proc_wait, task)
self.jobs[fut] = test
if not self.jobs: if not self.jobs:
raise IndexError('pop from empty list') raise IndexError('pop from empty list')
# Print remaining running jobs when all jobs have been started. # Print remaining running jobs when all jobs have been started.
if not self.test_list: if not self.test_list:
print("Remaining jobs: [{}]".format(", ".join(j[0] for j in self.jobs))) print("Remaining jobs: [{}]".format(", ".join(sorted(self.jobs.values()))))
dot_count = 0 dot_count = 0
while True: while True:
# Return all procs that have finished, if any. Otherwise sleep until there is one. # Return all procs that have finished, if any. Otherwise sleep until there is one.
time.sleep(.5) procs = futures.wait(self.jobs.keys(), timeout=.5, return_when=futures.FIRST_COMPLETED)
self.jobs = {fut: self.jobs[fut] for fut in procs.not_done}
ret = [] ret = []
for job in self.jobs: for job in procs.done:
(name, start_time, proc, testdir, log_out, log_err) = job (name, start_time, proc, testdir, log_out, log_err) = job.result()
if proc.poll() is not None:
log_out.seek(0), log_err.seek(0) log_out.seek(0), log_err.seek(0)
[stdout, stderr] = [log_file.read().decode('utf-8') for log_file in (log_out, log_err)] [stdout, stderr] = [log_file.read().decode('utf-8') for log_file in (log_out, log_err)]
log_out.close(), log_err.close() log_out.close(), log_err.close()
skip_reason = None skip_reason = None
if proc.returncode == TEST_EXIT_PASSED and stderr == "": if proc.returncode == TEST_EXIT_PASSED and stderr == "":
status = "Passed" status = "Passed"
elif proc.returncode == TEST_EXIT_SKIPPED: elif proc.returncode == TEST_EXIT_SKIPPED:
status = "Skipped" status = "Skipped"
skip_reason = re.search(r"Test Skipped: (.*)", stdout).group(1) skip_reason = re.search(r"Test Skipped: (.*)", stdout).group(1)
else: else:
status = "Failed" status = "Failed"
self.jobs.remove(job)
if self.use_term_control: if self.use_term_control:
clearline = '\r' + (' ' * dot_count) + '\r' clearline = '\r' + (' ' * dot_count) + '\r'
print(clearline, end='', flush=True) print(clearline, end='', flush=True)
dot_count = 0 dot_count = 0
ret.append((TestResult(name, status, int(time.time() - start_time)), testdir, stdout, stderr, skip_reason)) ret.append((TestResult(name, status, int(time.time() - start_time)), testdir, stdout, stderr, skip_reason))
if ret: if ret:
return ret return ret
if self.use_term_control: if self.use_term_control: