aboutsummaryrefslogtreecommitdiff
path: root/mesonbuild/mtest.py
diff options
context:
space:
mode:
Diffstat (limited to 'mesonbuild/mtest.py')
-rw-r--r--mesonbuild/mtest.py56
1 files changed, 33 insertions, 23 deletions
diff --git a/mesonbuild/mtest.py b/mesonbuild/mtest.py
index 34e4943..c754309 100644
--- a/mesonbuild/mtest.py
+++ b/mesonbuild/mtest.py
@@ -353,12 +353,12 @@ class JunitBuilder:
'testsuites', tests='0', errors='0', failures='0')
self.suites = {} # type: T.Dict[str, et.Element]
- def log(self, name: str, test: 'TestRun') -> None:
+ def log(self, test: 'TestRun') -> None:
"""Log a single test case."""
if test.junit is not None:
for suite in test.junit.findall('.//testsuite'):
# Assume that we don't need to merge anything here...
- suite.attrib['name'] = '{}.{}.{}'.format(test.project, name, suite.attrib['name'])
+ suite.attrib['name'] = '{}.{}.{}'.format(test.project, test.name, suite.attrib['name'])
# GTest can inject invalid attributes
for case in suite.findall('.//testcase[@result]'):
@@ -372,7 +372,7 @@ class JunitBuilder:
# We want to record this so that each result is recorded
# separately
if test.results:
- suitename = '{}.{}'.format(test.project, name)
+ suitename = '{}.{}'.format(test.project, test.name)
assert suitename not in self.suites, 'duplicate suite'
suite = self.suites[suitename] = et.Element(
@@ -420,7 +420,7 @@ class JunitBuilder:
suite = self.suites[test.project]
suite.attrib['tests'] = str(int(suite.attrib['tests']) + 1)
- testcase = et.SubElement(suite, 'testcase', name=name, classname=name)
+ testcase = et.SubElement(suite, 'testcase', name=test.name, classname=test.name)
if test.res is TestResult.SKIP:
et.SubElement(testcase, 'skipped')
suite.attrib['skipped'] = str(int(suite.attrib['skipped']) + 1)
@@ -451,10 +451,14 @@ class JunitBuilder:
class TestRun:
+ TEST_NUM = 0
- def __init__(self, test: TestSerialisation, test_env: T.Dict[str, str]):
+ def __init__(self, test: TestSerialisation, test_env: T.Dict[str, str],
+ name: str):
self.res = TestResult.PENDING
self.test = test
+ self._num = None # type: T.Optional[int]
+ self.name = name
self.results = list() # type: T.List[TestResult]
self.returncode = 0
self.starttime = None # type: T.Optional[float]
@@ -529,6 +533,13 @@ class TestRun:
self.complete(res, results, returncode, stdo, stde, cmd)
+ @property
+ def num(self) -> int:
+ if self._num is None:
+ TestRun.TEST_NUM += 1
+ self._num = TestRun.TEST_NUM
+ return self._num
+
def complete(self, res: TestResult, results: T.List[TestResult],
returncode: int,
stdo: T.Optional[str], stde: T.Optional[str],
@@ -574,8 +585,8 @@ def decode(stream: T.Union[None, bytes]) -> str:
except UnicodeDecodeError:
return stream.decode('iso-8859-1', errors='ignore')
-def write_json_log(jsonlogfile: T.TextIO, test_name: str, result: TestRun) -> None:
- jresult = {'name': test_name,
+def write_json_log(jsonlogfile: T.TextIO, result: TestRun) -> None:
+ jresult = {'name': result.name,
'stdout': result.stdo,
'result': result.res.value,
'starttime': result.starttime,
@@ -647,12 +658,13 @@ async def complete_all(futures: T.Iterable[asyncio.Future]) -> None:
class SingleTestRunner:
def __init__(self, test: TestSerialisation, test_env: T.Dict[str, str],
- env: T.Dict[str, str], options: argparse.Namespace):
+ env: T.Dict[str, str], name: str,
+ options: argparse.Namespace):
self.test = test
self.test_env = test_env
self.env = env
self.options = options
- self.runobj = TestRun(test, test_env)
+ self.runobj = TestRun(test, test_env, name)
def _get_cmd(self) -> T.Optional[T.List[str]]:
if self.test.fname[0].endswith('.jar'):
@@ -915,7 +927,7 @@ class TestHarness:
options.wrapper = current.exe_wrapper
return current.env.get_env(os.environ.copy())
- def get_test_runner(self, test: TestSerialisation) -> SingleTestRunner:
+ def get_test_runner(self, test: TestSerialisation, name: str) -> SingleTestRunner:
options = deepcopy(self.options)
if not options.setup:
options.setup = self.build_data.test_setup_default_name
@@ -928,7 +940,7 @@ class TestHarness:
if (test.is_cross_built and test.needs_exe_wrapper and
test.exe_runner and test.exe_runner.found()):
env['MESON_EXE_WRAPPER'] = join_args(test.exe_runner.get_command())
- return SingleTestRunner(test, test_env, env, options)
+ return SingleTestRunner(test, test_env, env, name, options)
def process_test_result(self, result: TestRun) -> None:
if result.res is TestResult.TIMEOUT:
@@ -947,17 +959,16 @@ class TestHarness:
sys.exit('Unknown test result encountered: {}'.format(result.res))
def print_stats(self, test_count: int, name_max_len: int,
- tests: T.List[TestSerialisation],
- name: str, result: TestRun, i: int) -> None:
+ result: TestRun) -> None:
ok_statuses = (TestResult.OK, TestResult.EXPECTEDFAIL)
bad_statuses = (TestResult.FAIL, TestResult.TIMEOUT, TestResult.INTERRUPT,
TestResult.UNEXPECTEDPASS, TestResult.ERROR)
result_str = '{num:{numlen}}/{testcount} {name:{name_max_len}} {res:{reslen}} {dur:.2f}s'.format(
numlen=len(str(test_count)),
- num=i,
+ num=result.num,
testcount=test_count,
name_max_len=name_max_len,
- name=name,
+ name=result.name,
reslen=TestResult.maxlen(),
res=result.res.value,
dur=result.duration)
@@ -979,9 +990,9 @@ class TestHarness:
if self.logfile:
self.logfile.write(result_str)
if self.jsonlogfile:
- write_json_log(self.jsonlogfile, name, result)
+ write_json_log(self.jsonlogfile, result)
if self.junit:
- self.junit.log(name, result)
+ self.junit.log(result)
def print_summary(self) -> None:
# Prepend a list of failures
@@ -1201,14 +1212,13 @@ class TestHarness:
self.build_data = build.load(os.getcwd())
interrupted = False
- async def run_test(test: SingleTestRunner,
- name: str, index: int) -> None:
+ async def run_test(test: SingleTestRunner) -> None:
async with semaphore:
if interrupted or (self.options.repeat > 1 and self.fail_count):
return
res = await test.run()
self.process_test_result(res)
- self.print_stats(test_count, name_max_len, tests, name, res, index)
+ self.print_stats(test_count, name_max_len, res)
def test_done(f: asyncio.Future) -> None:
if not f.cancelled():
@@ -1253,13 +1263,13 @@ class TestHarness:
asyncio.get_event_loop().add_signal_handler(signal.SIGTERM, sigterm_handler)
try:
for _ in range(self.options.repeat):
- for i, test in enumerate(tests, 1):
+ for test in tests:
visible_name = self.get_pretty_suite(test)
- single_test = self.get_test_runner(test)
+ single_test = self.get_test_runner(test, visible_name)
if not test.is_parallel or single_test.options.gdb:
await complete_all(futures)
- future = asyncio.ensure_future(run_test(single_test, visible_name, i))
+ future = asyncio.ensure_future(run_test(single_test))
futures.append(future)
running_tests[future] = visible_name
future.add_done_callback(test_done)