aboutsummaryrefslogtreecommitdiff
path: root/mesonbuild
diff options
context:
space:
mode:
Diffstat (limited to 'mesonbuild')
-rw-r--r--mesonbuild/backend/backends.py5
-rw-r--r--mesonbuild/interpreter.py4
-rw-r--r--mesonbuild/mtest.py39
3 files changed, 46 insertions, 2 deletions
diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py
index ec3aca6..9bb870c 100644
--- a/mesonbuild/backend/backends.py
+++ b/mesonbuild/backend/backends.py
@@ -46,6 +46,7 @@ class TestProtocol(enum.Enum):
EXITCODE = 0
TAP = 1
GTEST = 2
+ RUST = 3
@classmethod
def from_str(cls, string: str) -> 'TestProtocol':
@@ -55,6 +56,8 @@ class TestProtocol(enum.Enum):
return cls.TAP
elif string == 'gtest':
return cls.GTEST
+ elif string == 'rust':
+ return cls.RUST
raise MesonException('unknown test format {}'.format(string))
def __str__(self) -> str:
@@ -62,6 +65,8 @@ class TestProtocol(enum.Enum):
return 'exitcode'
elif self is self.GTEST:
return 'gtest'
+ elif self is self.RUST:
+ return 'rust'
return 'tap'
diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py
index c20c205..0c6bb99 100644
--- a/mesonbuild/interpreter.py
+++ b/mesonbuild/interpreter.py
@@ -4159,8 +4159,8 @@ This will become a hard error in the future.''' % kwargs['input'], location=self
if not isinstance(timeout, int):
raise InterpreterException('Timeout must be an integer.')
protocol = kwargs.get('protocol', 'exitcode')
- if protocol not in {'exitcode', 'tap', 'gtest'}:
- raise InterpreterException('Protocol must be "exitcode", "tap", or "gtest".')
+ if protocol not in {'exitcode', 'tap', 'gtest', 'rust'}:
+ raise InterpreterException('Protocol must be one of "exitcode", "tap", "gtest", or "rust".')
suite = []
prj = self.subproject if self.is_subproject() else self.build.project_name
for s in mesonlib.stringlistify(kwargs.get('suite', '')):
diff --git a/mesonbuild/mtest.py b/mesonbuild/mtest.py
index c31ad1a..9db271e 100644
--- a/mesonbuild/mtest.py
+++ b/mesonbuild/mtest.py
@@ -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
@@ -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:
@@ -1069,6 +1106,8 @@ class SingleTestRunner:
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='')