diff options
Diffstat (limited to 'run_meson_command_tests.py')
-rwxr-xr-x | run_meson_command_tests.py | 186 |
1 files changed, 186 insertions, 0 deletions
diff --git a/run_meson_command_tests.py b/run_meson_command_tests.py new file mode 100755 index 000000000..6efd911b5 --- /dev/null +++ b/run_meson_command_tests.py @@ -0,0 +1,186 @@ +#!/usr/bin/env python3 + +# Copyright 2018 The Meson development team +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os +import tempfile +import unittest +import subprocess +from pathlib import Path + +from mesonbuild.mesonlib import windows_proof_rmtree, python_command, is_windows + +# Find the meson.py adjacent to us +meson_py = Path(__file__).resolve().parent / 'meson.py' +if not meson_py.is_file(): + raise RuntimeError("meson.py not found: test must only run from git") + +def get_pypath(): + import sysconfig + pypath = sysconfig.get_path('purelib', vars={'base': ''}) + # Ensure that / is the path separator and not \, then strip / + return Path(pypath).as_posix().strip('/') + +def get_pybindir(): + import sysconfig + # 'Scripts' on Windows and 'bin' on other platforms including MSYS + return sysconfig.get_path('scripts', vars={'base': ''}).strip('\\/') + +class CommandTests(unittest.TestCase): + ''' + Test that running meson in various ways works as expected by checking the + value of mesonlib.meson_command that was set during configuration. + ''' + + def setUp(self): + super().setUp() + self.orig_env = os.environ.copy() + self.orig_dir = os.getcwd() + os.environ['MESON_COMMAND_TESTS'] = '1' + self.tmpdir = Path(tempfile.mkdtemp()).resolve() + self.src_root = Path(__file__).resolve().parent + self.testdir = str(self.src_root / 'test cases/common/1 trivial') + self.meson_args = ['--backend=ninja'] + + def tearDown(self): + try: + windows_proof_rmtree(str(self.tmpdir)) + except FileNotFoundError: + pass + os.environ.clear() + os.environ.update(self.orig_env) + os.chdir(str(self.orig_dir)) + super().tearDown() + + def _run(self, command, workdir=None): + ''' + Run a command while printing the stdout and stderr to stdout, + and also return a copy of it + ''' + # If this call hangs CI will just abort. It is very hard to distinguish + # between CI issue and test bug in that case. Set timeout and fail loud + # instead. + p = subprocess.run(command, stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, env=os.environ.copy(), + universal_newlines=True, cwd=workdir, timeout=60 * 5) + print(p.stdout) + if p.returncode != 0: + raise subprocess.CalledProcessError(p.returncode, command) + return p.stdout + + def assertMesonCommandIs(self, line, cmd): + self.assertTrue(line.startswith('meson_command '), msg=line) + self.assertEqual(line, 'meson_command is {!r}'.format(cmd)) + + def test_meson_uninstalled(self): + # This is what the meson command must be for all these cases + resolved_meson_command = python_command + [str(self.src_root / 'meson.py')] + # Absolute path to meson.py + os.chdir('/') + builddir = str(self.tmpdir / 'build1') + meson_py = str(self.src_root / 'meson.py') + meson_setup = [meson_py, 'setup'] + meson_command = python_command + meson_setup + self.meson_args + stdo = self._run(meson_command + [self.testdir, builddir]) + self.assertMesonCommandIs(stdo.split('\n')[0], resolved_meson_command) + # ./meson.py + os.chdir(str(self.src_root)) + builddir = str(self.tmpdir / 'build2') + meson_py = './meson.py' + meson_setup = [meson_py, 'setup'] + meson_command = python_command + meson_setup + self.meson_args + stdo = self._run(meson_command + [self.testdir, builddir]) + self.assertMesonCommandIs(stdo.split('\n')[0], resolved_meson_command) + # Symlink to meson.py + if is_windows(): + # Symlinks require admin perms + return + os.chdir(str(self.src_root)) + builddir = str(self.tmpdir / 'build3') + # Create a symlink to meson.py in bindir, and add it to PATH + bindir = (self.tmpdir / 'bin') + bindir.mkdir() + (bindir / 'meson').symlink_to(self.src_root / 'meson.py') + os.environ['PATH'] = str(bindir) + os.pathsep + os.environ['PATH'] + # See if it works! + meson_py = 'meson' + meson_setup = [meson_py, 'setup'] + meson_command = meson_setup + self.meson_args + stdo = self._run(meson_command + [self.testdir, builddir]) + self.assertMesonCommandIs(stdo.split('\n')[0], resolved_meson_command) + + def test_meson_installed(self): + # Install meson + prefix = self.tmpdir / 'prefix' + pylibdir = prefix / get_pypath() + bindir = prefix / get_pybindir() + pylibdir.mkdir(parents=True) + os.environ['PYTHONPATH'] = str(pylibdir) + os.environ['PATH'] = str(bindir) + os.pathsep + os.environ['PATH'] + self._run(python_command + ['setup.py', 'install', '--prefix', str(prefix)]) + self.assertTrue(pylibdir.is_dir()) + self.assertTrue(bindir.is_dir()) + # Run `meson` + os.chdir('/') + if is_windows(): + resolved_meson_command = python_command + [str(bindir / 'meson.py')] + else: + resolved_meson_command = python_command + [str(bindir / 'meson')] + # The python configuration on appveyor does not register .py as + # a valid extension, so we cannot run `meson` on Windows. + builddir = str(self.tmpdir / 'build1') + meson_setup = ['meson', 'setup'] + meson_command = meson_setup + self.meson_args + stdo = self._run(meson_command + [self.testdir, builddir]) + self.assertMesonCommandIs(stdo.split('\n')[0], resolved_meson_command) + # Run `/path/to/meson` + builddir = str(self.tmpdir / 'build2') + if is_windows(): + # Cannot run .py directly because of the appveyor configuration, + # and the script is named meson.py, not meson + meson_setup = python_command + [str(bindir / 'meson.py'), 'setup'] + else: + meson_setup = [str(bindir / 'meson'), 'setup'] + meson_command = meson_setup + self.meson_args + stdo = self._run(meson_command + [self.testdir, builddir]) + self.assertMesonCommandIs(stdo.split('\n')[0], resolved_meson_command) + # Run `python3 -m mesonbuild.mesonmain` + resolved_meson_command = python_command + ['-m', 'mesonbuild.mesonmain'] + builddir = str(self.tmpdir / 'build3') + meson_setup = ['-m', 'mesonbuild.mesonmain', 'setup'] + meson_command = python_command + meson_setup + self.meson_args + stdo = self._run(meson_command + [self.testdir, builddir]) + self.assertMesonCommandIs(stdo.split('\n')[0], resolved_meson_command) + if is_windows(): + # Next part requires a shell + return + # `meson` is a wrapper to `meson.real` + resolved_meson_command = python_command + [str(bindir / 'meson.real')] + builddir = str(self.tmpdir / 'build4') + (bindir / 'meson').rename(bindir / 'meson.real') + wrapper = (bindir / 'meson') + with open(wrapper, 'w') as f: + f.write('#!/bin/sh\n\nmeson.real "$@"') + wrapper.chmod(0o755) + meson_setup = [str(wrapper), 'setup'] + meson_command = meson_setup + self.meson_args + stdo = self._run(meson_command + [self.testdir, builddir]) + self.assertMesonCommandIs(stdo.split('\n')[0], resolved_meson_command) + + def test_meson_exe_windows(self): + raise unittest.SkipTest('NOT IMPLEMENTED') + +if __name__ == '__main__': + unittest.main(buffer=True) |