Merge pull request #503 from nioncode/windows-parallel-test
Merge Windows parallel test fix.
This commit is contained in:
commit
5d53c6b741
|
@ -58,7 +58,6 @@ class Environment():
|
||||||
log_dir = 'meson-logs'
|
log_dir = 'meson-logs'
|
||||||
coredata_file = os.path.join(private_dir, 'coredata.dat')
|
coredata_file = os.path.join(private_dir, 'coredata.dat')
|
||||||
version_regex = '\d+(\.\d+)+(-[a-zA-Z0-9]+)?'
|
version_regex = '\d+(\.\d+)+(-[a-zA-Z0-9]+)?'
|
||||||
|
|
||||||
def __init__(self, source_dir, build_dir, main_script_file, options, original_cmd_line_args):
|
def __init__(self, source_dir, build_dir, main_script_file, options, original_cmd_line_args):
|
||||||
assert(os.path.isabs(main_script_file))
|
assert(os.path.isabs(main_script_file))
|
||||||
assert(not os.path.islink(main_script_file))
|
assert(not os.path.islink(main_script_file))
|
||||||
|
|
51
run_tests.py
51
run_tests.py
|
@ -42,6 +42,26 @@ class TestResult:
|
||||||
self.buildtime = buildtime
|
self.buildtime = buildtime
|
||||||
self.testtime = testtime
|
self.testtime = testtime
|
||||||
|
|
||||||
|
class AutoDeletedDir():
|
||||||
|
def __init__(self, dir):
|
||||||
|
self.dir = dir
|
||||||
|
def __enter__(self):
|
||||||
|
os.makedirs(self.dir, exist_ok=True)
|
||||||
|
return self.dir
|
||||||
|
def __exit__(self, type, value, traceback):
|
||||||
|
# On Windows, shutil.rmtree fails sometimes, because 'the directory is not empty'.
|
||||||
|
# Retrying fixes this.
|
||||||
|
# That's why we don't use tempfile.TemporaryDirectory, but wrap the deletion in the AutoDeletedDir class.
|
||||||
|
retries = 5
|
||||||
|
for i in range(0, retries):
|
||||||
|
try:
|
||||||
|
shutil.rmtree(self.dir)
|
||||||
|
return
|
||||||
|
except OSError:
|
||||||
|
if i == retries-1:
|
||||||
|
raise
|
||||||
|
time.sleep(0.1 * (2**i))
|
||||||
|
|
||||||
passing_tests = 0
|
passing_tests = 0
|
||||||
failing_tests = 0
|
failing_tests = 0
|
||||||
skipped_tests = 0
|
skipped_tests = 0
|
||||||
|
@ -197,22 +217,21 @@ def parse_test_args(testdir):
|
||||||
pass
|
pass
|
||||||
return args
|
return args
|
||||||
|
|
||||||
def run_test(skipped, testdir, extra_args, should_succeed):
|
def run_test(skipped, testdir, extra_args, flags, compile_commands, install_commands, should_succeed):
|
||||||
if skipped:
|
if skipped:
|
||||||
return None
|
return None
|
||||||
with tempfile.TemporaryDirectory(prefix='b ', dir='.') as build_dir:
|
with AutoDeletedDir(tempfile.mkdtemp(prefix='b ', dir='.')) as build_dir:
|
||||||
with tempfile.TemporaryDirectory(prefix='i ', dir=os.getcwd()) as install_dir:
|
with AutoDeletedDir(tempfile.mkdtemp(prefix='i ', dir=os.getcwd())) as install_dir:
|
||||||
try:
|
try:
|
||||||
return _run_test(testdir, build_dir, install_dir, extra_args, should_succeed)
|
return _run_test(testdir, build_dir, install_dir, extra_args, flags, compile_commands, install_commands, should_succeed)
|
||||||
finally:
|
finally:
|
||||||
mlog.shutdown() # Close the log file because otherwise Windows wets itself.
|
mlog.shutdown() # Close the log file because otherwise Windows wets itself.
|
||||||
|
|
||||||
def _run_test(testdir, test_build_dir, install_dir, extra_args, should_succeed):
|
def _run_test(testdir, test_build_dir, install_dir, extra_args, flags, compile_commands, install_commands, should_succeed):
|
||||||
global compile_commands
|
|
||||||
test_args = parse_test_args(testdir)
|
test_args = parse_test_args(testdir)
|
||||||
gen_start = time.time()
|
gen_start = time.time()
|
||||||
gen_command = [meson_command, '--prefix', '/usr', '--libdir', 'lib', testdir, test_build_dir]\
|
gen_command = [meson_command, '--prefix', '/usr', '--libdir', 'lib', testdir, test_build_dir]\
|
||||||
+ unity_flags + backend_flags + test_args + extra_args
|
+ flags + test_args + extra_args
|
||||||
(returncode, stdo, stde) = run_configure_inprocess(gen_command)
|
(returncode, stdo, stde) = run_configure_inprocess(gen_command)
|
||||||
gen_time = time.time() - gen_start
|
gen_time = time.time() - gen_start
|
||||||
if not should_succeed:
|
if not should_succeed:
|
||||||
|
@ -246,7 +265,6 @@ def _run_test(testdir, test_build_dir, install_dir, extra_args, should_succeed):
|
||||||
if returncode != 0:
|
if returncode != 0:
|
||||||
return TestResult('Running unit tests failed.', stdo, stde, gen_time, build_time, test_time)
|
return TestResult('Running unit tests failed.', stdo, stde, gen_time, build_time, test_time)
|
||||||
if len(install_commands) == 0:
|
if len(install_commands) == 0:
|
||||||
print("Skipping install test")
|
|
||||||
return TestResult('', '', '', gen_time, build_time, test_time)
|
return TestResult('', '', '', gen_time, build_time, test_time)
|
||||||
else:
|
else:
|
||||||
env = os.environ.copy()
|
env = os.environ.copy()
|
||||||
|
@ -309,20 +327,10 @@ def run_tests(extra_args):
|
||||||
# and getting it wrong by not doing logical number sorting.
|
# and getting it wrong by not doing logical number sorting.
|
||||||
(testnum, testbase) = os.path.split(t)[-1].split(' ', 1)
|
(testnum, testbase) = os.path.split(t)[-1].split(' ', 1)
|
||||||
testname = '%.3d %s' % (int(testnum), testbase)
|
testname = '%.3d %s' % (int(testnum), testbase)
|
||||||
# Windows errors out when calling result.result() below with
|
result = executor.submit(run_test, skipped, t, extra_args, unity_flags + backend_flags, compile_commands, install_commands, name != 'failing')
|
||||||
# a bizarre error about appending None to an array that comes
|
|
||||||
# from the standard library. This is probably either because I use
|
|
||||||
# XP or the Python version is old. Anyhow, fall back to immediate
|
|
||||||
# evaluation. This causes output not to be printed until the end,
|
|
||||||
# which is unfortunate but least it works.
|
|
||||||
if mesonlib.is_windows():
|
|
||||||
result = run_test(skipped, t, extra_args, name != 'failing')
|
|
||||||
else:
|
|
||||||
result = executor.submit(run_test, skipped, t, extra_args, name != 'failing')
|
|
||||||
futures.append((testname, t, result))
|
futures.append((testname, t, result))
|
||||||
for (testname, t, result) in futures:
|
for (testname, t, result) in futures:
|
||||||
if not mesonlib.is_windows(): # See above.
|
result = result.result()
|
||||||
result = result.result()
|
|
||||||
if result is None:
|
if result is None:
|
||||||
print('Skipping:', t)
|
print('Skipping:', t)
|
||||||
current_test = ET.SubElement(current_suite, 'testcase', {'name' : testname,
|
current_test = ET.SubElement(current_suite, 'testcase', {'name' : testname,
|
||||||
|
@ -331,7 +339,8 @@ def run_tests(extra_args):
|
||||||
global skipped_tests
|
global skipped_tests
|
||||||
skipped_tests += 1
|
skipped_tests += 1
|
||||||
else:
|
else:
|
||||||
print('Running test: ' + t)
|
without_install = "" if len(install_commands) > 0 else " (without install)"
|
||||||
|
print('Running test%s: %s' % (without_install, t))
|
||||||
conf_time += result.conftime
|
conf_time += result.conftime
|
||||||
build_time += result.buildtime
|
build_time += result.buildtime
|
||||||
test_time += result.testtime
|
test_time += result.testtime
|
||||||
|
|
Loading…
Reference in New Issue