Merge pull request #7064 from dcbaker/gtest-protocol

Add support for Gtest as a test protocol
pull/7072/head
Jussi Pakkanen 5 years ago committed by GitHub
commit 4ea7c6ee12
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 13
      docs/markdown/Reference-manual.md
  2. 150
      docs/markdown/Unit-tests.md
  3. 6
      docs/markdown/snippets/gtest_protocol.md
  4. 61
      mesonbuild/backend/backends.py
  5. 8
      mesonbuild/build.py
  6. 9
      mesonbuild/interpreter.py
  7. 2
      mesonbuild/mintro.py
  8. 62
      mesonbuild/mtest.py
  9. 10
      run_unittests.py
  10. 4
      test cases/frameworks/2 gtest/meson.build

@ -1666,11 +1666,14 @@ test(..., env: nomalloc, ...)
before test is executed even if they have `build_by_default : false`.
Since 0.46.0
- `protocol` specifies how the test results are parsed and can be one
of `exitcode` (the executable's exit code is used by the test harness
to record the outcome of the test) or `tap` ([Test Anything
Protocol](https://www.testanything.org/)). For more on the Meson test
harness protocol read [Unit Tests](Unit-tests.md). Since 0.50.0
- `protocol` *(Since 0.50.0)* specifies how the test results are parsed and can
be one of `exitcode`, `tap`, or `gtest`. For more information about test
harness protocol read [Unit Tests](Unit-tests.md). The following values are
accepted:
- `exitcode`: the executable's exit code is used by the test harness
to record the outcome of the test)
- `tap` ([Test Anything Protocol](https://www.testanything.org/))
- `gtest`. *(Since 0.55.0)* for Google Tests.
- `priority` specifies the priority of a test. Tests with a
higher priority are *started* before tests with a lower priority.

@ -4,20 +4,24 @@ short-description: Meson's own unit-test system
# Unit tests
Meson comes with a fully functional unit test system. To use it simply build an executable and then use it in a test.
Meson comes with a fully functional unit test system. To use it simply build
an executable and then use it in a test.
```meson
e = executable('prog', 'testprog.c')
test('name of test', e)
```
You can add as many tests as you want. They are run with the command `ninja test`.
You can add as many tests as you want. They are run with the command `ninja
test`.
Meson captures the output of all tests and writes it in the log file `meson-logs/testlog.txt`.
Meson captures the output of all tests and writes it in the log file
`meson-logs/testlog.txt`.
## Test parameters
Some tests require the use of command line arguments or environment variables. These are simple to define.
Some tests require the use of command line arguments or environment
variables. These are simple to define.
```meson
test('command line test', exe, args : ['first', 'second'])
@ -29,38 +33,46 @@ Note how you need to specify multiple values as an array.
### MALLOC_PERTURB_
By default, environment variable
[`MALLOC_PERTURB_`](http://man7.org/linux/man-pages/man3/mallopt.3.html)
is set to a random value between 1..255. This can help find memory
leaks on configurations using glibc, including with non-GCC compilers.
This feature can be disabled as discussed in [test()](Reference-manual.md#test).
[`MALLOC_PERTURB_`](http://man7.org/linux/man-pages/man3/mallopt.3.html) is
set to a random value between 1..255. This can help find memory leaks on
configurations using glibc, including with non-GCC compilers. This feature
can be disabled as discussed in [test()](Reference-manual.md#test).
## Coverage
If you enable coverage measurements by giving Meson the command line flag
`-Db_coverage=true`, you can generate coverage reports after running the tests
(running the tests is required to gather the list of functions that get
called). Meson will autodetect what coverage generator tools you have installed
and will generate the corresponding targets. These targets are `coverage-xml`
and `coverage-text` which are both provided by [Gcovr](http://gcovr.com)
(version 3.3 or higher) and `coverage-html`, which requires
[Lcov](https://ltp.sourceforge.io/coverage/lcov.php) and
[GenHTML](https://linux.die.net/man/1/genhtml) or
[Gcovr](http://gcovr.com). As a convenience, a high-level `coverage` target is
also generated which will produce all 3 coverage report types, if possible.
The output of these commands is written to the log directory `meson-logs` in your build directory.
`-Db_coverage=true`, you can generate coverage reports after running the
tests (running the tests is required to gather the list of functions that get
called). Meson will autodetect what coverage generator tools you have
installed and will generate the corresponding targets. These targets are
`coverage-xml` and `coverage-text` which are both provided by
[Gcovr](http://gcovr.com) (version 3.3 or higher) and `coverage-html`, which
requires [Lcov](https://ltp.sourceforge.io/coverage/lcov.php) and
[GenHTML](https://linux.die.net/man/1/genhtml) or [Gcovr](http://gcovr.com).
As a convenience, a high-level `coverage` target is also generated which will
produce all 3 coverage report types, if possible.
The output of these commands is written to the log directory `meson-logs` in
your build directory.
## Parallelism
To reduce test times, Meson will by default run multiple unit tests in parallel. It is common to have some tests which can not be run in parallel because they require unique hold on some resource such as a file or a D-Bus name. You have to specify these tests with a keyword argument.
To reduce test times, Meson will by default run multiple unit tests in
parallel. It is common to have some tests which can not be run in parallel
because they require unique hold on some resource such as a file or a D-Bus
name. You have to specify these tests with a keyword argument.
```meson
test('unique test', t, is_parallel : false)
```
Meson will then make sure that no other unit test is running at the same time. Non-parallel tests take longer to run so it is recommended that you write your unit tests to be parallel executable whenever possible.
Meson will then make sure that no other unit test is running at the same
time. Non-parallel tests take longer to run so it is recommended that you
write your unit tests to be parallel executable whenever possible.
By default Meson uses as many concurrent processes as there are cores on the test machine. You can override this with the environment variable `MESON_TESTTHREADS` like this.
By default Meson uses as many concurrent processes as there are cores on the
test machine. You can override this with the environment variable
`MESON_TESTTHREADS` like this.
```console
$ MESON_TESTTHREADS=5 ninja test
@ -70,7 +82,10 @@ $ MESON_TESTTHREADS=5 ninja test
*(added in version 0.52.0)*
Tests can be assigned a priority that determines when a test is *started*. Tests with higher priority are started first, tests with lower priority started later. The default priority is 0, meson makes no guarantee on the ordering of tests with identical priority.
Tests can be assigned a priority that determines when a test is *started*.
Tests with higher priority are started first, tests with lower priority
started later. The default priority is 0, meson makes no guarantee on the
ordering of tests with identical priority.
```meson
test('started second', t, priority : 0)
@ -78,23 +93,37 @@ test('started third', t, priority : -50)
test('started first', t, priority : 1000)
```
Note that the test priority only affects the starting order of tests and subsequent tests are affected by how long it takes previous tests to complete. It is thus possible that a higher-priority test is still running when lower-priority tests with a shorter runtime have completed.
Note that the test priority only affects the starting order of tests and
subsequent tests are affected by how long it takes previous tests to
complete. It is thus possible that a higher-priority test is still running
when lower-priority tests with a shorter runtime have completed.
## Skipped tests and hard errors
Sometimes a test can only determine at runtime that it can not be run.
For the default `exitcode` testing protocol, the GNU standard approach in this case is to exit the program with error code 77. Meson will detect this and report these tests as skipped rather than failed. This behavior was added in version 0.37.0.
For the default `exitcode` testing protocol, the GNU standard approach in
this case is to exit the program with error code 77. Meson will detect this
and report these tests as skipped rather than failed. This behavior was added
in version 0.37.0.
For TAP-based tests, skipped tests should print a single line starting with `1..0 # SKIP`.
For TAP-based tests, skipped tests should print a single line starting with
`1..0 # SKIP`.
In addition, sometimes a test fails set up so that it should fail even if it is marked as an expected failure. The GNU standard approach in this case is to exit the program with error code 99. Again, Meson will detect this and report these tests as `ERROR`, ignoring the setting of `should_fail`. This behavior was added in version 0.50.0.
In addition, sometimes a test fails set up so that it should fail even if it
is marked as an expected failure. The GNU standard approach in this case is
to exit the program with error code 99. Again, Meson will detect this and
report these tests as `ERROR`, ignoring the setting of `should_fail`. This
behavior was added in version 0.50.0.
## Testing tool
The goal of the meson test tool is to provide a simple way to run tests in a variety of different ways. The tool is designed to be run in the build directory.
The goal of the meson test tool is to provide a simple way to run tests in a
variety of different ways. The tool is designed to be run in the build
directory.
The simplest thing to do is just to run all tests, which is equivalent to running `ninja test`.
The simplest thing to do is just to run all tests, which is equivalent to
running `ninja test`.
```console
$ meson test
@ -125,7 +154,8 @@ Tests belonging to a suite `suite` can be run as follows
$ meson test --suite (sub)project_name:suite
```
Since version *0.46*, `(sub)project_name` can be omitted if it is the top-level project.
Since version *0.46*, `(sub)project_name` can be omitted if it is the
top-level project.
Multiple suites are specified like:
@ -145,7 +175,8 @@ Sometimes you need to run the tests multiple times, which is done like this:
$ meson test --repeat=10
```
Invoking tests via a helper executable such as Valgrind can be done with the `--wrap` argument
Invoking tests via a helper executable such as Valgrind can be done with the
`--wrap` argument
```console
$ meson test --wrap=valgrind testname
@ -163,17 +194,25 @@ Meson also supports running the tests under GDB. Just doing this:
$ meson test --gdb testname
```
Meson will launch `gdb` all set up to run the test. Just type `run` in the GDB command prompt to start the program.
Meson will launch `gdb` all set up to run the test. Just type `run` in the
GDB command prompt to start the program.
The second use case is a test that segfaults only rarely. In this case you can invoke the following command:
The second use case is a test that segfaults only rarely. In this case you
can invoke the following command:
```console
$ meson test --gdb --repeat=10000 testname
```
This runs the test up to 10 000 times under GDB automatically. If the program crashes, GDB will halt and the user can debug the application. Note that testing timeouts are disabled in this case so `meson test` will not kill `gdb` while the developer is still debugging it. The downside is that if the test binary freezes, the test runner will wait forever.
This runs the test up to 10 000 times under GDB automatically. If the program
crashes, GDB will halt and the user can debug the application. Note that
testing timeouts are disabled in this case so `meson test` will not kill
`gdb` while the developer is still debugging it. The downside is that if the
test binary freezes, the test runner will wait forever.
Sometimes, the GDB binary is not in the PATH variable or the user wants to use a GDB replacement. Therefore, the invoked GDB program can be specified *(added 0.52.0)*:
Sometimes, the GDB binary is not in the PATH variable or the user wants to
use a GDB replacement. Therefore, the invoked GDB program can be specified
*(added 0.52.0)*:
```console
$ meson test --gdb --gdb-path /path/to/gdb testname
@ -183,12 +222,41 @@ $ meson test --gdb --gdb-path /path/to/gdb testname
$ meson test --print-errorlogs
```
Meson will report the output produced by the failing tests along with other useful information as the environmental variables. This is useful, for example, when you run the tests on Travis-CI, Jenkins and the like.
Meson will report the output produced by the failing tests along with other
useful information as the environmental variables. This is useful, for
example, when you run the tests on Travis-CI, Jenkins and the like.
For further information see the command line help of Meson by running `meson test -h`.
For further information see the command line help of Meson by running `meson
test -h`.
## Legacy notes
If `meson test` does not work for you, you likely have a old version of Meson.
In that case you should call `mesontest` instead. If `mesontest` doesn't work
either you have a very old version prior to 0.37.0 and should upgrade.
If `meson test` does not work for you, you likely have a old version of
Meson. In that case you should call `mesontest` instead. If `mesontest`
doesn't work either you have a very old version prior to 0.37.0 and should
upgrade.
## Test outputs
Meson will write several different files with detailed results of running
tests. These will be written into $builddir/meson-logs/
### testlog.json
This is not a proper json file, but a file containing one valid json object
per line. This is file is designed so each line is streamed out as each test
is run, so it can be read as a stream while the test harness is running
### testlog.junit.xml
This is a valid JUnit XML description of all tests run. It is not streamed
out, and is written only once all tests complete running.
When tests use the `tap` protocol each test will be recorded as a testsuite
container, with each case named by the number of the result.
When tests use the `gtest` protocol meson will inject arguments to the test
to generate it's own JUnit XML, which meson will include as part of this XML
file.
*New in 0.55.0*

@ -0,0 +1,6 @@
## Test protocol for gtest
Due to the popularity of Gtest (google test) among C and C++ developers meson
now supports a special protocol for gtest. With this protocol meson injects
arguments to gtests to output JUnit, reads that JUnit, and adds the output to
the JUnit it generates.

@ -12,23 +12,54 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import os, pickle, re
from collections import OrderedDict
from functools import lru_cache
import enum
import json
import os
import pickle
import re
import shlex
import subprocess
import textwrap
import typing as T
from .. import build
from .. import dependencies
from .. import mesonlib
from .. import mlog
import json
import subprocess
from ..mesonlib import MachineChoice, MesonException, OrderedSet, OptionOverrideProxy
from ..mesonlib import classify_unity_sources, unholder
from ..mesonlib import File
from ..compilers import CompilerArgs, VisualStudioLikeCompiler
from ..interpreter import Interpreter
from collections import OrderedDict
import shlex
from functools import lru_cache
import typing as T
from ..mesonlib import (
File, MachineChoice, MesonException, OrderedSet, OptionOverrideProxy,
classify_unity_sources, unholder
)
if T.TYPE_CHECKING:
from ..interpreter import Interpreter
class TestProtocol(enum.Enum):
EXITCODE = 0
TAP = 1
GTEST = 2
@classmethod
def from_str(cls, string: str) -> 'TestProtocol':
if string == 'exitcode':
return cls.EXITCODE
elif string == 'tap':
return cls.TAP
elif string == 'gtest':
return cls.GTEST
raise MesonException('unknown test format {}'.format(string))
def __str__(self) -> str:
if self is self.EXITCODE:
return 'exitcode'
elif self is self.GTEST:
return 'gtest'
return 'tap'
class CleanTrees:
@ -83,11 +114,11 @@ class ExecutableSerialisation:
class TestSerialisation:
def __init__(self, name: str, project: str, suite: str, fname: T.List[str],
is_cross_built: bool, exe_wrapper: T.Optional[build.Executable],
is_cross_built: bool, exe_wrapper: T.Optional[dependencies.ExternalProgram],
needs_exe_wrapper: bool, is_parallel: bool, cmd_args: T.List[str],
env: build.EnvironmentVariables, should_fail: bool,
timeout: T.Optional[int], workdir: T.Optional[str],
extra_paths: T.List[str], protocol: str, priority: int):
extra_paths: T.List[str], protocol: TestProtocol, priority: int):
self.name = name
self.project_name = project
self.suite = suite
@ -107,7 +138,7 @@ class TestSerialisation:
self.priority = priority
self.needs_exe_wrapper = needs_exe_wrapper
def get_backend_from_name(backend: str, build: T.Optional[build.Build] = None, interpreter: T.Optional[Interpreter] = None) -> T.Optional['Backend']:
def get_backend_from_name(backend: str, build: T.Optional[build.Build] = None, interpreter: T.Optional['Interpreter'] = None) -> T.Optional['Backend']:
if backend == 'ninja':
from . import ninjabackend
return ninjabackend.NinjaBackend(build, interpreter)
@ -134,7 +165,7 @@ def get_backend_from_name(backend: str, build: T.Optional[build.Build] = None, i
# This class contains the basic functionality that is needed by all backends.
# Feel free to move stuff in and out of it as you see fit.
class Backend:
def __init__(self, build: T.Optional[build.Build], interpreter: T.Optional[Interpreter]):
def __init__(self, build: T.Optional[build.Build], interpreter: T.Optional['Interpreter']):
# Make it possible to construct a dummy backend
# This is used for introspection without a build directory
if build is None:

@ -12,12 +12,14 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import copy, os, re
from collections import OrderedDict, defaultdict
import itertools, pathlib
from functools import lru_cache
import copy
import hashlib
import itertools, pathlib
import os
import pickle
from functools import lru_cache
import re
import typing as T
from . import environment

@ -33,6 +33,7 @@ from .interpreterbase import FeatureNew, FeatureDeprecated, FeatureNewKwargs
from .interpreterbase import ObjectHolder
from .modules import ModuleReturnValue
from .cmake import CMakeInterpreter
from .backend.backends import TestProtocol
from pathlib import Path, PurePath
import os
@ -979,7 +980,7 @@ class Test(InterpreterObject):
self.should_fail = should_fail
self.timeout = timeout
self.workdir = workdir
self.protocol = protocol
self.protocol = TestProtocol.from_str(protocol)
self.priority = priority
def get_exe(self):
@ -3821,6 +3822,8 @@ This will become a hard error in the future.''' % kwargs['input'], location=self
@FeatureNewKwargs('test', '0.52.0', ['priority'])
@permittedKwargs(permitted_kwargs['test'])
def func_test(self, node, args, kwargs):
if kwargs.get('protocol') == 'gtest':
FeatureNew('"gtest" protocol for tests', '0.55.0').use(self.subproject)
self.add_test(node, args, kwargs, True)
def unpack_env_kwarg(self, kwargs) -> build.EnvironmentVariables:
@ -3872,8 +3875,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'):
raise InterpreterException('Protocol must be "exitcode" or "tap".')
if protocol not in {'exitcode', 'tap', 'gtest'}:
raise InterpreterException('Protocol must be "exitcode", "tap", or "gtest".')
suite = []
prj = self.subproject if self.is_subproject() else self.build.project_name
for s in mesonlib.stringlistify(kwargs.get('suite', '')):

@ -328,7 +328,7 @@ def get_test_list(testdata) -> T.List[T.Dict[str, T.Union[str, int, T.List[str],
to['suite'] = t.suite
to['is_parallel'] = t.is_parallel
to['priority'] = t.priority
to['protocol'] = t.protocol
to['protocol'] = str(t.protocol)
result.append(to)
return result

@ -43,6 +43,7 @@ from . import environment
from . import mlog
from .dependencies import ExternalProgram
from .mesonlib import MesonException, get_wine_shortpath, split_args
from .backend.backends import TestProtocol
if T.TYPE_CHECKING:
from .backend.backends import TestSerialisation
@ -94,6 +95,9 @@ def add_arguments(parser: argparse.ArgumentParser) -> None:
parser.add_argument('--wrapper', default=None, dest='wrapper', type=split_args,
help='wrapper to run tests with (e.g. Valgrind)')
parser.add_argument('-C', default='.', dest='wd',
# https://github.com/python/typeshed/issues/3107
# https://github.com/python/mypy/issues/7177
type=os.path.abspath, # type: ignore
help='directory to cd into before running')
parser.add_argument('--suite', default=[], dest='include_suites', action='append', metavar='SUITE',
help='Only run tests belonging to the given suite.')
@ -348,6 +352,19 @@ class JunitBuilder:
def log(self, name: str, 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'])
# GTest can inject invalid attributes
for case in suite.findall('.//testcase[@result]'):
del case.attrib['result']
for case in suite.findall('.//testcase[@timestamp]'):
del case.attrib['timestamp']
self.root.append(suite)
return
# In this case we have a test binary with multiple results.
# We want to record this so that each result is recorded
# separately
@ -428,11 +445,25 @@ class JunitBuilder:
class TestRun:
@classmethod
def make_gtest(cls, test: 'TestSerialisation', test_env: T.Dict[str, str],
returncode: int, starttime: float, duration: float,
stdo: T.Optional[str], stde: T.Optional[str],
cmd: T.Optional[T.List[str]]) -> 'TestRun':
filename = '{}.xml'.format(test.name)
if test.workdir:
filename = os.path.join(test.workdir, filename)
tree = et.parse(filename)
return cls.make_exitcode(
test, test_env, returncode, starttime, duration, stdo, stde, cmd,
junit=tree)
@classmethod
def make_exitcode(cls, test: 'TestSerialisation', test_env: T.Dict[str, str],
returncode: int, starttime: float, duration: float,
stdo: T.Optional[str], stde: T.Optional[str],
cmd: T.Optional[T.List[str]]) -> 'TestRun':
cmd: T.Optional[T.List[str]], **kwargs) -> 'TestRun':
if returncode == GNU_SKIP_RETURNCODE:
res = TestResult.SKIP
elif returncode == GNU_ERROR_RETURNCODE:
@ -441,15 +472,15 @@ class TestRun:
res = TestResult.EXPECTEDFAIL if bool(returncode) else TestResult.UNEXPECTEDPASS
else:
res = TestResult.FAIL if bool(returncode) else TestResult.OK
return cls(test, test_env, res, [], returncode, starttime, duration, stdo, stde, cmd)
return cls(test, test_env, res, [], returncode, starttime, duration, stdo, stde, cmd, **kwargs)
@classmethod
def make_tap(cls, test: 'TestSerialisation', test_env: T.Dict[str, str],
returncode: int, starttime: float, duration: float,
stdo: str, stde: str,
cmd: T.Optional[T.List[str]]) -> 'TestRun':
res = None # T.Optional[TestResult]
results = [] # T.List[TestResult]
res = None # type: T.Optional[TestResult]
results = [] # type: T.List[TestResult]
failed = False
for i in TAPParser(io.StringIO(stdo)).parse():
@ -485,7 +516,7 @@ class TestRun:
res: TestResult, results: T.List[TestResult], returncode:
int, starttime: float, duration: float,
stdo: T.Optional[str], stde: T.Optional[str],
cmd: T.Optional[T.List[str]]):
cmd: T.Optional[T.List[str]], *, junit: T.Optional[et.ElementTree] = None):
assert isinstance(res, TestResult)
self.res = res
self.results = results # May be an empty list
@ -498,6 +529,7 @@ class TestRun:
self.env = test_env
self.should_fail = test.should_fail
self.project = test.project_name
self.junit = junit
def get_log(self) -> str:
res = '--- command ---\n'
@ -544,9 +576,7 @@ def write_json_log(jsonlogfile: T.TextIO, test_name: str, result: TestRun) -> No
jsonlogfile.write(json.dumps(jresult) + '\n')
def run_with_mono(fname: str) -> bool:
if fname.endswith('.exe') and not (is_windows() or is_cygwin()):
return True
return False
return fname.endswith('.exe') and not (is_windows() or is_cygwin())
def load_benchmarks(build_dir: str) -> T.List['TestSerialisation']:
datafile = Path(build_dir) / 'meson-private' / 'meson_benchmark_setup.dat'
@ -633,7 +663,7 @@ class SingleTestRunner:
if not self.options.verbose:
stdout = tempfile.TemporaryFile("wb+")
stderr = tempfile.TemporaryFile("wb+") if self.options.split else stdout
if self.test.protocol == 'tap' and stderr is stdout:
if self.test.protocol is TestProtocol.TAP and stderr is stdout:
stdout = tempfile.TemporaryFile("wb+")
# Let gdb handle ^C instead of us
@ -653,7 +683,14 @@ class SingleTestRunner:
# errors avoid not being able to use the terminal.
os.setsid() # type: ignore
p = subprocess.Popen(cmd,
extra_cmd = [] # type: T.List[str]
if self.test.protocol is TestProtocol.GTEST:
gtestname = '{}.xml'.format(self.test.name)
if self.test.workdir:
gtestname = '{}:{}'.format(self.test.workdir, self.test.name)
extra_cmd.append('--gtest_output=xml:{}'.format(gtestname))
p = subprocess.Popen(cmd + extra_cmd,
stdout=stdout,
stderr=stderr,
env=self.env,
@ -743,8 +780,10 @@ class SingleTestRunner:
if timed_out:
return TestRun(self.test, self.test_env, TestResult.TIMEOUT, [], p.returncode, starttime, duration, stdo, stde, cmd)
else:
if self.test.protocol == 'exitcode':
if self.test.protocol is TestProtocol.EXITCODE:
return TestRun.make_exitcode(self.test, self.test_env, p.returncode, starttime, duration, stdo, stde, cmd)
elif self.test.protocol is TestProtocol.GTEST:
return TestRun.make_gtest(self.test, self.test_env, p.returncode, starttime, duration, stdo, stde, cmd)
else:
if self.options.verbose:
print(stdo, end='')
@ -1162,7 +1201,6 @@ def run(options: argparse.Namespace) -> int:
if not exe.found():
print('Could not find requested program: {!r}'.format(check_bin))
return 1
options.wd = os.path.abspath(options.wd)
if not options.list and not options.no_rebuild:
if not rebuild_all(options.wd):

@ -4625,8 +4625,7 @@ recommended as it is not supported on some platforms''')
schema = et.XMLSchema(et.parse(str(Path(__file__).parent / 'data' / 'schema.xsd')))
testdir = os.path.join(self.common_test_dir, case)
self.init(testdir)
self.init(case)
self.run_tests()
junit = et.parse(str(Path(self.builddir) / 'meson-logs' / 'testlog.junit.xml'))
@ -4636,10 +4635,13 @@ recommended as it is not supported on some platforms''')
self.fail(e.error_log)
def test_junit_valid_tap(self):
self._test_junit('213 tap tests')
self._test_junit(os.path.join(self.common_test_dir, '213 tap tests'))
def test_junit_valid_exitcode(self):
self._test_junit('44 test args')
self._test_junit(os.path.join(self.common_test_dir, '44 test args'))
def test_junit_valid_gtest(self):
self._test_junit(os.path.join(self.framework_test_dir, '2 gtest'))
def test_link_language_linker(self):
# TODO: there should be some way to query how we're linking things

@ -8,7 +8,7 @@ endif
gtest_nomain = dependency('gtest', main : false, method : 'system')
e = executable('testprog', 'test.cc', dependencies : gtest)
test('gtest test', e)
test('gtest test', e, protocol : 'gtest')
e = executable('testprog_nomain', 'test_nomain.cc', dependencies : gtest_nomain)
test('gtest nomain test', e)
test('gtest nomain test', e, protocol : 'gtest')

Loading…
Cancel
Save