diff options
author | Nirbheek Chauhan <nirbheek@centricular.com> | 2022-01-16 16:01:33 +0530 |
---|---|---|
committer | Nirbheek Chauhan <nirbheek.chauhan@gmail.com> | 2022-01-16 23:42:19 +0530 |
commit | faf79f4539841cbf89fe8d53cf35aa91fd8273c9 (patch) | |
tree | d6d4eaf7caae6681714cc97c56dd2ff1b73e5329 | |
parent | 1cda222a1a5faf98bf5c72bc103307bf76f76f7f (diff) | |
download | meson-faf79f4539841cbf89fe8d53cf35aa91fd8273c9.zip meson-faf79f4539841cbf89fe8d53cf35aa91fd8273c9.tar.gz meson-faf79f4539841cbf89fe8d53cf35aa91fd8273c9.tar.bz2 |
Add a test for the --vsenv meson setup option
The tests and the unittests both unconditionally call setup_vsenv()
because all tests are run using the backend commands directly: ninja,
msbuild, etc.
There's no way to undo this vs env setup, so the only way to test that
--vsenv works is by:
1. Removing all paths in PATH that provide ninja
2. Changing setup_vsenv(force=True) to forcibly set-up a new vsenv
when MESON_FORCE_VSENV_FOR_UNITTEST is set
3. Mock-patching build_command, test_command, install_command to use
`meson` instead of `ninja`
4. Asserting that 'Activating VS' is in the output for all commands
5. Ensure that compilation works because ninja is picked up from the
vs env.
I manually checked that this test actually does fail when the previous
commit is reverted.
-rw-r--r-- | mesonbuild/mesonlib/vsenv.py | 19 | ||||
-rwxr-xr-x | run_tests.py | 7 | ||||
-rw-r--r-- | unittests/baseplatformtests.py | 6 | ||||
-rw-r--r-- | unittests/helpers.py | 16 | ||||
-rw-r--r-- | unittests/windowstests.py | 26 |
5 files changed, 57 insertions, 17 deletions
diff --git a/mesonbuild/mesonlib/vsenv.py b/mesonbuild/mesonlib/vsenv.py index 8563b7d..fcb0c42 100644 --- a/mesonbuild/mesonlib/vsenv.py +++ b/mesonbuild/mesonlib/vsenv.py @@ -26,15 +26,16 @@ def _setup_vsenv(force: bool) -> bool: return False if os.environ.get('OSTYPE') == 'cygwin': return False - if 'Visual Studio' in os.environ['PATH']: - return False - # VSINSTALL is set when running setvars from a Visual Studio installation - # Tested with Visual Studio 2012 and 2017 - if 'VSINSTALLDIR' in os.environ: - return False - # Check explicitly for cl when on Windows - if shutil.which('cl.exe'): - return False + if 'MESON_FORCE_VSENV_FOR_UNITTEST' not in os.environ: + if 'Visual Studio' in os.environ['PATH']: + return False + # VSINSTALL is set when running setvars from a Visual Studio installation + # Tested with Visual Studio 2012 and 2017 + if 'VSINSTALLDIR' in os.environ: + return False + # Check explicitly for cl when on Windows + if shutil.which('cl.exe'): + return False if not force: if shutil.which('cc'): return False diff --git a/run_tests.py b/run_tests.py index b6f8884..20edf93 100755 --- a/run_tests.py +++ b/run_tests.py @@ -261,11 +261,10 @@ def ensure_backend_detects_changes(backend: Backend) -> None: time.sleep(1) def run_mtest_inprocess(commandlist: T.List[str]) -> T.Tuple[int, str, str]: - stderr = StringIO() - stdout = StringIO() - with mock.patch.object(sys, 'stdout', stdout), mock.patch.object(sys, 'stderr', stderr): + out = StringIO() + with mock.patch.object(sys, 'stdout', out), mock.patch.object(sys, 'stderr', out): returncode = mtest.run_with_args(commandlist) - return returncode, stdout.getvalue(), stderr.getvalue() + return returncode, stdout.getvalue() def clear_meson_configure_class_caches() -> None: compilers.CCompiler.find_library_cache = {} diff --git a/unittests/baseplatformtests.py b/unittests/baseplatformtests.py index 2f8064e..cfc78ce 100644 --- a/unittests/baseplatformtests.py +++ b/unittests/baseplatformtests.py @@ -249,10 +249,10 @@ class BasePlatformTests(TestCase): def run_tests(self, *, inprocess=False, override_envvars=None): if not inprocess: - self._run(self.test_command, workdir=self.builddir, override_envvars=override_envvars) + return self._run(self.test_command, workdir=self.builddir, override_envvars=override_envvars) else: with mock.patch.dict(os.environ, override_envvars): - run_mtest_inprocess(['-C', self.builddir]) + return run_mtest_inprocess(['-C', self.builddir])[1] def install(self, *, use_destdir=True, override_envvars=None): if self.backend is not Backend.ninja: @@ -263,7 +263,7 @@ class BasePlatformTests(TestCase): override_envvars = destdir else: override_envvars.update(destdir) - self._run(self.install_command, workdir=self.builddir, override_envvars=override_envvars) + return self._run(self.install_command, workdir=self.builddir, override_envvars=override_envvars) def uninstall(self, *, override_envvars=None): self._run(self.uninstall_command, workdir=self.builddir, override_envvars=override_envvars) diff --git a/unittests/helpers.py b/unittests/helpers.py index b759dba..bf06bdc 100644 --- a/unittests/helpers.py +++ b/unittests/helpers.py @@ -5,11 +5,13 @@ import unittest import functools import re import typing as T +from pathlib import Path from contextlib import contextmanager from mesonbuild.compilers import detect_c_compiler, compiler_from_language from mesonbuild.mesonlib import ( - MachineChoice, is_osx, is_cygwin, EnvironmentException, OptionKey, MachineChoice + MachineChoice, is_osx, is_cygwin, EnvironmentException, OptionKey, MachineChoice, + OrderedSet ) from run_tests import get_fake_env @@ -170,3 +172,15 @@ def get_rpath(fname: str) -> T.Optional[str]: # don't check for, so clear those final = ':'.join([e for e in raw.split(':') if not e.startswith('/nix')]) return final + +def get_path_without_cmd(cmd: str, path: str) -> str: + pathsep = os.pathsep + paths = OrderedSet([Path(p).resolve() for p in path.split(pathsep)]) + while True: + full_path = shutil.which(cmd, path=path) + if full_path is None: + break + dirname = Path(full_path).resolve().parent + paths.discard(dirname) + path = pathsep.join([str(p) for p in paths]) + return path diff --git a/unittests/windowstests.py b/unittests/windowstests.py index bd75c74..d3ad932 100644 --- a/unittests/windowstests.py +++ b/unittests/windowstests.py @@ -373,3 +373,29 @@ class WindowsTests(BasePlatformTests): raise SkipTest('Not using MSVC') self.init(testdir, extra_args=['-Dtest-failure=true']) self.assertRaises(subprocess.CalledProcessError, self.build) + + @unittest.skipIf(is_cygwin(), "Needs visual studio") + def test_vsenv_option(self): + if self.backend is not Backend.ninja: + raise SkipTest('Only ninja backend is valid for test') + env = os.environ.copy() + env['MESON_FORCE_VSENV_FOR_UNITTEST'] = '1' + # Remove ninja from PATH to ensure that the one provided by Visual + # Studio is picked, as a regression test for + # https://github.com/mesonbuild/meson/issues/9774 + env['PATH'] = get_path_without_cmd('ninja', env['PATH']) + testdir = os.path.join(self.common_test_dir, '1 trivial') + out = self.init(testdir, extra_args=['--vsenv'], override_envvars=env) + self.assertIn('Activating VS', out) + self.assertRegex(out, 'Visual Studio environment is needed to run Ninja') + # All these directly call ninja with the full path, so we need to patch + # it out to use meson subcommands + with mock.patch.object(self, 'build_command', self.meson_command + ['compile']): + out = self.build(override_envvars=env) + self.assertIn('Activating VS', out) + with mock.patch.object(self, 'test_command', self.meson_command + ['test']): + out = self.run_tests(override_envvars=env) + self.assertIn('Activating VS', out) + with mock.patch.object(self, 'install_command', self.meson_command + ['install']): + out = self.install(override_envvars=env) + self.assertIn('Activating VS', out) |