Skip to content

test_spam is not idempotent #169

@bnavigator

Description

@bnavigator

The test_spam example does not install into an isolated environment and fails if tested first on one python version and then on another:

[   43s] ____________________________ test_build_and_import _____________________________
[   43s] 
[   43s] virtual_env = PosixPath('/tmp/mesonpy-test-venv-e6z5h263/bin/python')
[   43s] tmp_dir_session = PosixPath('/tmp/pytest-of-abuild/pytest-17/test0/mesonpy-test-x0t_i2l1')
[   43s] 
[   43s]     @pytest.mark.skipif(platform.system() != 'Linux', reason='Unsupported on this platform for now')
[   43s]     @pytest.mark.skipif(sys.version_info < (3, 8), reason='Example only supports >=3.8')
[   43s]     @pytest.mark.skipif(platform.python_implementation() == 'PyPy', reason='PyPy bug on creating the venv')
[   43s]     def test_build_and_import(virtual_env, tmp_dir_session):
[   43s]         """Test that the wheel for the spam example builds, installs, and imports."""
[   43s]         wheel = build_project_wheel(
[   43s]             package=examples_dir / 'spam',
[   43s]             outdir=tmp_dir_session
[   43s]         )
[   43s]     
[   43s]         subprocess.check_call([virtual_env, '-m', 'pip', '-qqq', 'install', wheel])
[   43s] >       output, status = subprocess.check_output(
[   43s]             [virtual_env, '-c', f'import spam; print(spam.system("ls {wheel}"))']
[   43s]         ).decode().strip().split('\n')
[   43s] 
[   43s] tests/docs/examples/test_spam.py:23: 
[   43s] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
[   43s] /usr/lib64/python3.9/subprocess.py:424: in check_output
[   43s]     return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
[   43s] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
[   43s] 
[   43s] input = None, capture_output = False, timeout = None, check = True
[   43s] popenargs = ([PosixPath('/tmp/mesonpy-test-venv-e6z5h263/bin/python'), '-c', 'import spam; print(spam.system("ls /tmp/pytest-of-abuild/pytest-17/test0/mesonpy-test-x0t_i2l1/spam-0.0.1-py3-none-any.whl"))'],)
[   43s] kwargs = {'stdout': -1}
[   43s] process = <Popen: returncode: 1 args: [PosixPath('/tmp/mesonpy-test-venv-e6z5h263/bin/...>
[   43s] stdout = b'', stderr = None, retcode = 1
[   43s] 
[   43s]     def run(*popenargs,
[   43s]             input=None, capture_output=False, timeout=None, check=False, **kwargs):
[   43s]         """Run command with arguments and return a CompletedProcess instance.
[   43s]     
[   43s]         The returned instance will have attributes args, returncode, stdout and
[   43s]         stderr. By default, stdout and stderr are not captured, and those attributes
[   43s]         will be None. Pass stdout=PIPE and/or stderr=PIPE in order to capture them.
[   43s]     
[   43s]         If check is True and the exit code was non-zero, it raises a
[   43s]         CalledProcessError. The CalledProcessError object will have the return code
[   43s]         in the returncode attribute, and output & stderr attributes if those streams
[   43s]         were captured.
[   43s]     
[   43s]         If timeout is given, and the process takes too long, a TimeoutExpired
[   43s]         exception will be raised.
[   43s]     
[   43s]         There is an optional argument "input", allowing you to
[   43s]         pass bytes or a string to the subprocess's stdin.  If you use this argument
[   43s]         you may not also use the Popen constructor's "stdin" argument, as
[   43s]         it will be used internally.
[   43s]     
[   43s]         By default, all communication is in bytes, and therefore any "input" should
[   43s]         be bytes, and the stdout and stderr will be bytes. If in text mode, any
[   43s]         "input" should be a string, and stdout and stderr will be strings decoded
[   43s]         according to locale encoding, or by "encoding" if set. Text mode is
[   43s]         triggered by setting any of text, encoding, errors or universal_newlines.
[   43s]     
[   43s]         The other arguments are the same as for the Popen constructor.
[   43s]         """
[   43s]         if input is not None:
[   43s]             if kwargs.get('stdin') is not None:
[   43s]                 raise ValueError('stdin and input arguments may not both be used.')
[   43s]             kwargs['stdin'] = PIPE
[   43s]     
[   43s]         if capture_output:
[   43s]             if kwargs.get('stdout') is not None or kwargs.get('stderr') is not None:
[   43s]                 raise ValueError('stdout and stderr arguments may not be used '
[   43s]                                  'with capture_output.')
[   43s]             kwargs['stdout'] = PIPE
[   43s]             kwargs['stderr'] = PIPE
[   43s]     
[   43s]         with Popen(*popenargs, **kwargs) as process:
[   43s]             try:
[   43s]                 stdout, stderr = process.communicate(input, timeout=timeout)
[   43s]             except TimeoutExpired as exc:
[   43s]                 process.kill()
[   43s]                 if _mswindows:
[   43s]                     # Windows accumulates the output in a single blocking
[   43s]                     # read() call run on child threads, with the timeout
[   43s]                     # being done in a join() on those threads.  communicate()
[   43s]                     # _after_ kill() is required to collect that and add it
[   43s]                     # to the exception.
[   43s]                     exc.stdout, exc.stderr = process.communicate()
[   43s]                 else:
[   43s]                     # POSIX _communicate already populated the output so
[   43s]                     # far into the TimeoutExpired exception.
[   43s]                     process.wait()
[   43s]                 raise
[   43s]             except:  # Including KeyboardInterrupt, communicate handled that.
[   43s]                 process.kill()
[   43s]                 # We don't call process.wait() as .__exit__ does that for us.
[   43s]                 raise
[   43s]             retcode = process.poll()
[   43s]             if check and retcode:
[   43s] >               raise CalledProcessError(retcode, process.args,
[   43s]                                          output=stdout, stderr=stderr)
[   43s] E               subprocess.CalledProcessError: Command '[PosixPath('/tmp/mesonpy-test-venv-e6z5h263/bin/python'), '-c', 'import spam; print(spam.system("ls /tmp/pytest-of-abuild/pytest-17/test0/mesonpy-test-x0t_i2l1/spam-0.0.1-py3-none-any.whl"))']' returned non-zero exit status 1.
[   43s] 
[   43s] /usr/lib64/python3.9/subprocess.py:528: CalledProcessError
[   43s] ----------------------------- Captured stdout call -----------------------------
[   43s] + meson setup --native-file=/home/abuild/rpmbuild/BUILD/meson_python-0.10.0/docs/examples/spam/.mesonpy-native-file.ini -Ddebug=false -Doptimization=2 --prefix=/usr /home/abuild/rpmbuild/BUILD/meson_python-0.10.0/docs/examples/spam /home/abuild/rpmbuild/BUILD/meson_python-0.10.0/docs/examples/spam/build
[   43s] Directory already configured.
[   43s] 
[   43s] Just run your build command (e.g. ninja) and Meson will regenerate as necessary.
[   43s] If ninja fails, run "ninja reconfigure" or "meson --reconfigure"
[   43s] to force Meson to regenerate.
[   43s] 
[   43s] If build failures persist, run "meson setup --wipe" to rebuild from scratch
[   43s] using the same options as passed when configuring the build.
[   43s] To change option values, run "meson configure" instead.
[   43s] + meson compile
[   43s] [0/1] Regenerating build files.
[   43s] Cleaning... 2 files.
[   43s] The Meson build system
[   43s] Version: 0.63.2
[   43s] Source dir: /home/abuild/rpmbuild/BUILD/meson_python-0.10.0/docs/examples/spam
[   43s] Build dir: /home/abuild/rpmbuild/BUILD/meson_python-0.10.0/docs/examples/spam/build
[   43s] Build type: native build
[   43s] Project name: spam
[   43s] Project version: undefined
[   43s] C compiler for the host machine: cc (gcc 12.2.1 "cc (SUSE Linux) 12.2.1 20220830 [revision e927d1cf141f221c5a32574bde0913307e140984]")
[   43s] C linker for the host machine: cc ld.bfd 2.39.0.20220810-1
[   43s] Host machine cpu family: x86_64
[   43s] Host machine cpu: x86_64
[   43s] Program python found: YES (/usr/bin/python3.9)
[   43s] Found pkg-config: /usr/bin/pkg-config (1.8.0)
[   43s] Build targets in project: 1
[   43s] 
[   43s] spam undefined
[   43s] 
[   43s]   User defined options
[   43s]     Native files: /home/abuild/rpmbuild/BUILD/meson_python-0.10.0/docs/examples/spam/.mesonpy-native-file.ini
[   43s]     backend     : ninja
[   43s]     debug       : false
[   43s]     optimization: 2
[   43s]     prefix      : /usr
[   43s] 
[   43s] Found ninja-1.11.1 at /usr/bin/ninja
[   43s] [1/2] Compiling C object _spam.cpython-39-x86_64-linux-gnu.so.p/src_spammodule.c.o
[   43s] [2/2] Linking target _spam.cpython-39-x86_64-linux-gnu.so
[   43s] + meson install --destdir /home/abuild/rpmbuild/BUILD/meson_python-0.10.0/docs/examples/spam/.mesonpy-mhm9xzoo/install
[   43s] ninja: Entering directory `/home/abuild/rpmbuild/BUILD/meson_python-0.10.0/docs/examples/spam/build'
[   43s] ninja: no work to do.
[   43s] Installing _spam.cpython-39-x86_64-linux-gnu.so to /home/abuild/rpmbuild/BUILD/meson_python-0.10.0/docs/examples/spam/.mesonpy-mhm9xzoo/install/usr/lib64/python3.9/site-packages/spam
[   43s] Installing /home/abuild/rpmbuild/BUILD/meson_python-0.10.0/docs/examples/spam/src/__init__.py to /home/abuild/rpmbuild/BUILD/meson_python-0.10.0/docs/examples/spam/.mesonpy-mhm9xzoo/install/usr/lib/python3.9/site-packages/spam
[   43s] WARNING Using heuristics to map files to wheel, this may result in incorrect locations
[   43s] WARNING File could not be mapped to an equivalent wheel directory: /home/abuild/rpmbuild/BUILD/meson_python-0.10.0/docs/examples/spam/.mesonpy-mhm9xzoo/install/usr/lib64/python3.8/site-packages/spam/_spam.cpython-38-x86_64-linux-gnu.so (/usr/lib64/python3.8/site-packages/spam/_spam.cpython-38-x86_64-linux-gnu.so)
[   43s] Copying files to wheel...
[   43s] [0/0] spam/__init__.py
[   43s] ----------------------------- Captured stderr call -----------------------------
[   43s] Traceback (most recent call last):
[   43s]   File "<string>", line 1, in <module>
[   43s]   File "/tmp/mesonpy-test-venv-e6z5h263/lib64/python3.9/site-packages/spam/__init__.py", line 1, in <module>
[   43s]     from ._spam import system
[   43s] ModuleNotFoundError: No module named 'spam._spam'
[   43s] =========================== short test summary info ============================
[   43s] FAILED tests/docs/examples/test_spam.py::test_build_and_import - subprocess.C...
[   43s] =================== 1 failed, 51 passed, 1 xpassed in 18.95s ===================

Note the cp38 vs cp39 mismatch

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions