diff options
author | Jussi Pakkanen <jpakkane@gmail.com> | 2021-01-06 00:05:48 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-01-06 00:05:48 +0000 |
commit | c9d9dacdbc9fad31f00f871b24ec6b99a611ff5e (patch) | |
tree | 07ea0773d50c41e3e87081e1be6095a7788da9df /mesonbuild/mtest.py | |
parent | f9dd75f213b1c3a7ab397133b6a157ddba511d90 (diff) | |
parent | 827fa95de1c619b51457c5a04297b6ce9adc2177 (diff) | |
download | meson-c9d9dacdbc9fad31f00f871b24ec6b99a611ff5e.zip meson-c9d9dacdbc9fad31f00f871b24ec6b99a611ff5e.tar.gz meson-c9d9dacdbc9fad31f00f871b24ec6b99a611ff5e.tar.bz2 |
Merge pull request #7860 from dcbaker/wip/2020-10/rust-module
Add a rust module
Diffstat (limited to 'mesonbuild/mtest.py')
-rw-r--r-- | mesonbuild/mtest.py | 73 |
1 files changed, 56 insertions, 17 deletions
diff --git a/mesonbuild/mtest.py b/mesonbuild/mtest.py index 7e3ebea..9db271e 100644 --- a/mesonbuild/mtest.py +++ b/mesonbuild/mtest.py @@ -595,17 +595,17 @@ class JunitBuilder(TestLogger): 'testsuite', name=suitename, tests=str(len(test.results)), - errors=str(sum(1 for r in test.results if r in + errors=str(sum(1 for r in test.results.values() if r in {TestResult.INTERRUPT, TestResult.ERROR})), - failures=str(sum(1 for r in test.results if r in + failures=str(sum(1 for r in test.results.values() if r in {TestResult.FAIL, TestResult.UNEXPECTEDPASS, TestResult.TIMEOUT})), - skipped=str(sum(1 for r in test.results if r is TestResult.SKIP)), + skipped=str(sum(1 for r in test.results.values() if r is TestResult.SKIP)), ) - for i, result in enumerate(test.results): + for i, result in test.results.items(): # Both name and classname are required. Set them both to the # number of the test in a TAP test, as TAP doesn't give names. - testcase = et.SubElement(suite, 'testcase', name=str(i), classname=str(i)) + testcase = et.SubElement(suite, 'testcase', name=i, classname=i) if result is TestResult.SKIP: et.SubElement(testcase, 'skipped') elif result is TestResult.ERROR: @@ -666,6 +666,28 @@ class JunitBuilder(TestLogger): tree.write(f, encoding='utf-8', xml_declaration=True) +def parse_rust_test(stdout: str) -> T.Dict[str, TestResult]: + """Parse the output of rust tests.""" + res = {} # type; T.Dict[str, TestResult] + + def parse_res(res: str) -> TestResult: + if res == 'ok': + return TestResult.OK + elif res == 'ignored': + return TestResult.SKIP + elif res == 'FAILED': + return TestResult.FAIL + raise MesonException('Unsupported output from rust test: {}'.format(res)) + + for line in stdout.splitlines(): + if line.startswith('test ') and not line.startswith('test result'): + _, name, _, result = line.split(' ') + name = name.replace('::', '.') + res[name] = parse_res(result) + + return res + + class TestRun: TEST_NUM = 0 @@ -675,7 +697,7 @@ class TestRun: self.test = test self._num = None # type: T.Optional[int] self.name = name - self.results = list() # type: T.List[TestResult] + self.results: T.Dict[str, TestResult] = {} self.returncode = 0 self.starttime = None # type: T.Optional[float] self.duration = None # type: T.Optional[float] @@ -713,23 +735,23 @@ class TestRun: res = TestResult.EXPECTEDFAIL if bool(returncode) else TestResult.UNEXPECTEDPASS else: res = TestResult.FAIL if bool(returncode) else TestResult.OK - self.complete(res, [], returncode, stdo, stde, cmd, **kwargs) + self.complete(res, {}, returncode, stdo, stde, cmd, **kwargs) def complete_tap(self, returncode: int, stdo: str, stde: str, cmd: T.List[str]) -> None: res = None # type: T.Optional[TestResult] - results = [] # type: T.List[TestResult] + results = {} # type: T.Dict[str, TestResult] failed = False - for i in TAPParser(io.StringIO(stdo)).parse(): + for n, i in enumerate(TAPParser(io.StringIO(stdo)).parse()): if isinstance(i, TAPParser.Bailout): - results.append(TestResult.ERROR) + results[str(n)] = TestResult.ERROR failed = True elif isinstance(i, TAPParser.Test): - results.append(i.result) + results[str(n)] = i.result if i.result not in {TestResult.OK, TestResult.EXPECTEDFAIL, TestResult.SKIP}: failed = True elif isinstance(i, TAPParser.Error): - results.append(TestResult.ERROR) + results[str(n)] = TestResult.ERROR stde += '\nTAP parsing error: ' + i.message failed = True @@ -739,7 +761,7 @@ class TestRun: if res is None: # Now determine the overall result of the test based on the outcome of the subcases - if all(t is TestResult.SKIP for t in results): + if all(t is TestResult.SKIP for t in results.values()): # This includes the case where num_tests is zero res = TestResult.SKIP elif self.should_fail: @@ -749,6 +771,21 @@ class TestRun: self.complete(res, results, returncode, stdo, stde, cmd) + def complete_rust(self, returncode: int, stdo: str, stde: str, cmd: T.List[str]) -> None: + results = parse_rust_test(stdo) + + failed = TestResult.FAIL in results.values() + # Now determine the overall result of the test based on the outcome of the subcases + if all(t is TestResult.SKIP for t in results.values()): + # This includes the case where num_tests is zero + res = TestResult.SKIP + elif self.should_fail: + res = TestResult.EXPECTEDFAIL if failed else TestResult.UNEXPECTEDPASS + else: + res = TestResult.FAIL if failed else TestResult.OK + + self.complete(res, results, returncode, stdo, stde, cmd) + @property def num(self) -> int: if self._num is None: @@ -756,13 +793,13 @@ class TestRun: self._num = TestRun.TEST_NUM return self._num - def complete(self, res: TestResult, results: T.List[TestResult], + def complete(self, res: TestResult, results: T.Dict[str, TestResult], returncode: int, stdo: T.Optional[str], stde: T.Optional[str], cmd: T.List[str], *, junit: T.Optional[et.ElementTree] = None) -> None: assert isinstance(res, TestResult) self.res = res - self.results = results + self.results = results # May be empty self.returncode = returncode self.duration = time.time() - self.starttime self.stdo = stdo @@ -906,7 +943,7 @@ class SingleTestRunner: self.runobj.start() if cmd is None: skip_stdout = 'Not run because can not execute cross compiled binaries.' - self.runobj.complete(TestResult.SKIP, [], GNU_SKIP_RETURNCODE, skip_stdout, None, None) + self.runobj.complete(TestResult.SKIP, {}, GNU_SKIP_RETURNCODE, skip_stdout, None, None) else: wrap = TestHarness.get_wrapper(self.options) if self.options.gdb: @@ -1063,12 +1100,14 @@ class SingleTestRunner: stdo = "" stde = additional_error if result: - self.runobj.complete(result, [], returncode, stdo, stde, cmd) + self.runobj.complete(result, {}, returncode, stdo, stde, cmd) else: if self.test.protocol is TestProtocol.EXITCODE: self.runobj.complete_exitcode(returncode, stdo, stde, cmd) elif self.test.protocol is TestProtocol.GTEST: self.runobj.complete_gtest(returncode, stdo, stde, cmd) + elif self.test.protocol is TestProtocol.RUST: + return self.runobj.complete_rust(returncode, stdo, stde, cmd) else: if self.options.verbose: print(stdo, end='') |