Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test_pdb_continue_with_recursive_debug randomly fails #11411

Open
mtelka opened this issue Sep 7, 2023 · 0 comments
Open

test_pdb_continue_with_recursive_debug randomly fails #11411

mtelka opened this issue Sep 7, 2023 · 0 comments
Labels
type: bug problem that needs to be addressed type: selftests a problem in the tests of pytest

Comments

@mtelka
Copy link

mtelka commented Sep 7, 2023

I see random failures of test_pdb_continue_with_recursive_debug. Below we see one failure, but the number of failures varies from zero to three.

$ tox --current-env --no-provision --recreate -e py39 -- testing/test_debugging.py::TestPDB::test_pdb_continue_with_recursive_debug
py39: remove tox env folder $(BUILD_DIR)/.tox/py39
py39: commands[0]> pytest testing/test_debugging.py::TestPDB::test_pdb_continue_with_recursive_debug
============================= test session starts ==============================
platform sunos5 -- Python 3.9.16, pytest-7.4.1, pluggy-1.3.0 -- /usr/bin/python3.9
cachedir: .tox/py39/.pytest_cache
hypothesis profile 'default' -> database=DirectoryBasedExampleDatabase('$(BUILD_DIR)/.hypothesis/examples')
rootdir: $(BUILD_DIR)
configfile: pyproject.toml
plugins: anyio-3.7.1, flake8-1.1.1, mypy-plugins-3.0.0, datadir-1.4.1, mock-3.11.1, custom-exit-code-0.3.0, console-scripts-1.4.1, socket-0.6.0, xdist-3.2.1, time-machine-2.12.0, perf-0.12.0, forked-1.6.0, shell-utilities-1.8.0, env-1.0.1, lazy-fixture-0.6.3, backports.unittest-mock-1.5.1, freezegun-0.4.2, timeout-2.0.2, regressions-2.5.0, helpers-namespace-2021.12.29, typeguard-4.1.3, subtests-0.10.0, rerunfailures-12.0, pytest_freezer-0.4.8, subprocess-1.5.0, skip-markers-1.4.1, pyfakefs-5.2.4, enabler-2.3.1, black-multipy-1.0.1, hypothesis-6.84.1, Faker-19.3.1, kgb-7.1.1, teamcity-messages-1.32, expect-1.1.0, travis-fold-1.3.0, pytest_httpserver-1.0.8, jaraco.test-5.3.0
collecting ... collected 3 items

testing/test_debugging.py::TestPDB::test_pdb_continue_with_recursive_debug[] PASSED [ 33%]
testing/test_debugging.py::TestPDB::test_pdb_continue_with_recursive_debug[-s] FAILED [ 66%]
testing/test_debugging.py::TestPDB::test_pdb_continue_with_recursive_debug[-p no:capture] PASSED [100%]

=================================== FAILURES ===================================
______________ TestPDB.test_pdb_continue_with_recursive_debug[-s] ______________

self = <test_debugging.TestPDB object at 0x7fffab7415e0>, capture_arg = '-s'
pytester = <Pytester PosixPath('/tmp/pytest-of-marcel/pytest-98/test_pdb_continue_with_recursive_debug1')>

    @pytest.mark.parametrize("capture_arg", ("", "-s", "-p no:capture"))
    def test_pdb_continue_with_recursive_debug(
        self, capture_arg, pytester: Pytester
    ) -> None:
        """Full coverage for do_debug without capturing.

        This is very similar to test_pdb_interaction_continue_recursive in general,
        but mocks out ``pdb.set_trace`` for providing more coverage.
        """
        p1 = pytester.makepyfile(
            """
            try:
                input = raw_input
            except NameError:
                pass

            def set_trace():
                __import__('pdb').set_trace()

            def test_1(monkeypatch):
                import _pytest.debugging

                class pytestPDBTest(_pytest.debugging.pytestPDB):
                    @classmethod
                    def set_trace(cls, *args, **kwargs):
                        # Init PytestPdbWrapper to handle capturing.
                        _pdb = cls._init_pdb("set_trace", *args, **kwargs)

                        # Mock out pdb.Pdb.do_continue.
                        import pdb
                        pdb.Pdb.do_continue = lambda self, arg: None

                        print("===" + " SET_TRACE ===")
                        assert input() == "debug set_trace()"

                        # Simulate PytestPdbWrapper.do_debug
                        cls._recursive_debug += 1
                        print("ENTERING RECURSIVE DEBUGGER")
                        print("===" + " SET_TRACE_2 ===")

                        assert input() == "c"
                        _pdb.do_continue("")
                        print("===" + " SET_TRACE_3 ===")

                        # Simulate PytestPdbWrapper.do_debug
                        print("LEAVING RECURSIVE DEBUGGER")
                        cls._recursive_debug -= 1

                        print("===" + " SET_TRACE_4 ===")
                        assert input() == "c"
                        _pdb.do_continue("")

                    def do_continue(self, arg):
                        print("=== do_continue")

                monkeypatch.setattr(_pytest.debugging, "pytestPDB", pytestPDBTest)

                import pdb
                monkeypatch.setattr(pdb, "set_trace", pytestPDBTest.set_trace)

                set_trace()
        """
        )
        child = pytester.spawn_pytest(f"--tb=short {p1} {capture_arg}")
        child.expect("=== SET_TRACE ===")
        before = child.before.decode("utf8")
        if not capture_arg:
            assert ">>> PDB set_trace (IO-capturing turned off) >>>" in before
        else:
            assert ">>> PDB set_trace >>>" in before
        child.sendline("debug set_trace()")
        child.expect("=== SET_TRACE_2 ===")
        before = child.before.decode("utf8")
        assert "\r\nENTERING RECURSIVE DEBUGGER\r\n" in before
        child.sendline("c")
        child.expect("=== SET_TRACE_3 ===")

        # No continue message with recursive debugging.
        before = child.before.decode("utf8")
        assert ">>> PDB continue " not in before

        child.sendline("c")
        child.expect("=== SET_TRACE_4 ===")
        before = child.before.decode("utf8")
        assert "\r\nLEAVING RECURSIVE DEBUGGER\r\n" in before
>       child.sendline("c")

$(BUILD_DIR)/testing/test_debugging.py:754:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/usr/lib/python3.9/vendor-packages/pexpect/pty_spawn.py:578: in sendline
    return self.send(s + self.linesep)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <pexpect.pty_spawn.spawn object at 0x7fffa9b09580>, s = b'c\n'

    def send(self, s):
        '''Sends string ``s`` to the child process, returning the number of
        bytes written. If a logfile is specified, a copy is written to that
        log.

        The default terminal input mode is canonical processing unless set
        otherwise by the child process. This allows backspace and other line
        processing to be performed prior to transmitting to the receiving
        program. As this is buffered, there is a limited size of such buffer.

        On Linux systems, this is 4096 (defined by N_TTY_BUF_SIZE). All
        other systems honor the POSIX.1 definition PC_MAX_CANON -- 1024
        on OSX, 256 on OpenSolaris, and 1920 on FreeBSD.

        This value may be discovered using fpathconf(3)::

            >>> from os import fpathconf
            >>> print(fpathconf(0, 'PC_MAX_CANON'))
            256

        On such a system, only 256 bytes may be received per line. Any
        subsequent bytes received will be discarded. BEL (``'\a'``) is then
        sent to output if IMAXBEL (termios.h) is set by the tty driver.
        This is usually enabled by default.  Linux does not honor this as
        an option -- it behaves as though it is always set on.

        Canonical input processing may be disabled altogether by executing
        a shell, then stty(1), before executing the final program::

            >>> bash = pexpect.spawn('/bin/bash', echo=False)
            >>> bash.sendline('stty -icanon')
            >>> bash.sendline('base64')
            >>> bash.sendline('x' * 5000)
        '''

        if self.delaybeforesend is not None:
            time.sleep(self.delaybeforesend)

        s = self._coerce_send_string(s)
        self._log(s, 'send')

        b = self._encoder.encode(s, final=False)
>       return os.write(self.child_fd, b)
E       OSError: [Errno 22] Invalid argument

/usr/lib/python3.9/vendor-packages/pexpect/pty_spawn.py:569: OSError
=========================== short test summary info ============================
FAILED testing/test_debugging.py::TestPDB::test_pdb_continue_with_recursive_debug[-s]
========================= 1 failed, 2 passed in 3.28s ==========================
py39: exit 1 (6.03 seconds) $(BUILD_DIR)> pytest testing/test_debugging.py::TestPDB::test_pdb_continue_with_recursive_debug pid=5673
  py39: FAIL code 1 (6.09=setup[0.06]+cmd[6.03] seconds)
  evaluation failed :( (7.31 seconds)
@Zac-HD Zac-HD added type: bug problem that needs to be addressed type: selftests a problem in the tests of pytest labels Sep 13, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: bug problem that needs to be addressed type: selftests a problem in the tests of pytest
Projects
None yet
Development

No branches or pull requests

2 participants