klein icon indicating copy to clipboard operation
klein copied to clipboard

KleinResourceTests.test_addSlash fails on Musl or glibc based system

Open dol-sen opened this issue 3 years ago • 9 comments

Gentoo bug: https://bugs.gentoo.org/865677

Full build log: https://865677.bugs.gentoo.org/attachment.cgi?id=800049

================================== FAILURES ===================================
_______________________ KleinResourceTests.test_addSlash _______________________

self = <klein.test.test_resource.KleinResourceTests testMethod=test_addSlash>

    def test_addSlash(self) -> None:
        app = self.app
        request = MockRequest(b"/foo")
    
        @app.route("/foo/")
        def foo(request: IRequest) -> KleinRenderable:
            return "foo"
    
        d = _render(self.kr, request)
    
        self.assertFired(d)
        self.assertEqual(
            request.setHeader.call_count,
            3,
        )
>       request.setHeader.assert_has_calls(
            [
                call(b"Content-Type", b"text/html; charset=utf-8"),
                call(b"Content-Length", b"258"),
                call(b"Location", b"http://localhost:8080/foo/"),
            ]
        )

app        = <klein._app.Klein object at 0x7f463a37d610>
d          = <Deferred at 0x7f4637efc730 current result: None>
foo        = <function KleinResourceTests.test_addSlash.<locals>.foo at 0x7f4639dfa5e0>
request    = <MockRequest at 0x7f463983cf70 method=GET uri=/foo clientproto=HTTP/1.1>
self       = <klein.test.test_resource.KleinResourceTests testMethod=test_addSlash>

src/klein/test/test_resource.py:642: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <Mock id='139939562899008'>
calls = [call(b'Content-Type', b'text/html; charset=utf-8'), call(b'Content-Length', b'258'), call(b'Location', b'http://localhost:8080/foo/')]
any_order = False

    def assert_has_calls(self, calls, any_order=False):
        """assert the mock has been called with the specified calls.
        The `mock_calls` list is checked for the calls.
    
        If `any_order` is False (the default) then the calls must be
        sequential. There can be extra calls before or after the
        specified calls.
    
        If `any_order` is True then the calls can be in any order, but
        they must all appear in `mock_calls`."""
        expected = [self._call_matcher(c) for c in calls]
        cause = next((e for e in expected if isinstance(e, Exception)), None)
        all_calls = _CallList(self._call_matcher(c) for c in self.mock_calls)
        if not any_order:
            if expected not in all_calls:
                if cause is None:
                    problem = 'Calls not found.'
                else:
                    problem = ('Error processing expected calls.\n'
                               'Errors: {}').format(
                                   [e if isinstance(e, Exception) else None
                                    for e in expected])
>               raise AssertionError(
                    f'{problem}\n'
                    f'Expected: {_CallList(calls)}'
                    f'{self._calls_repr(prefix="Actual").rstrip(".")}'
                ) from cause
E               AssertionError: Calls not found.
E               Expected: [call(b'Content-Type', b'text/html; charset=utf-8'),
E                call(b'Content-Length', b'258'),
E                call(b'Location', b'http://localhost:8080/foo/')]
E               Actual: [call(b'Content-Type', b'text/html; charset=utf-8'),
E                call(b'Content-Length', b'239'),
E                call(b'Location', b'http://localhost:8080/foo/')]

all_calls  = [call(b'Content-Type', b'text/html; charset=utf-8'),
 call(b'Content-Length', b'239'),
 call(b'Location', b'http://localhost:8080/foo/')]
any_order  = False
calls      = [call(b'Content-Type', b'text/html; charset=utf-8'),
 call(b'Content-Length', b'258'),
 call(b'Location', b'http://localhost:8080/foo/')]
cause      = None
expected   = [call(b'Content-Type', b'text/html; charset=utf-8'),
 call(b'Content-Length', b'258'),
 call(b'Location', b'http://localhost:8080/foo/')]
problem    = 'Calls not found.'
self       = <Mock id='139939562899008'>

/usr/lib/python3.8/unittest/mock.py:950: AssertionError
=============================== warnings summary ===============================
../../../../../../../usr/lib/python3.8/site-packages/twisted/web/test/test_web.py:21
  /usr/lib/python3.8/site-packages/twisted/web/test/test_web.py:21: DeprecationWarning: twisted.test.proto_helpers.EventLoggingObserver was deprecated in Twisted 19.7.0: Please use twisted.internet.testing.EventLoggingObserver instead.
    from twisted.test.proto_helpers import EventLoggingObserver

src/klein/_form.py:132: 1 warning
src/klein/test/test_form.py: 14 warnings
  /var/tmp/portage/dev-python/klein-21.8.0/work/klein-21.8.0/src/klein/_form.py:132: DeprecationWarning: assoc is deprecated and will be removed after 2018/01.
    return attr.assoc(

src/klein/test/test_form.py:38
  /var/tmp/portage/dev-python/klein-21.8.0/work/klein-21.8.0/src/klein/test/test_form.py:38: PytestCollectionWarning: cannot collect test class 'TestObject' because it has a __init__ constructor (from: src/klein/test/test_form.py)
    class TestObject:

src/klein/test/test_form.py: 17 warnings
  /var/tmp/portage/dev-python/klein-21.8.0/work/klein-21.8.0/src/klein/_form.py:340: DeprecationWarning: assoc is deprecated and will be removed after 2018/01.
    yield attr.assoc(

src/klein/test/test_resource.py::KleinResourceTests::test_explicitStaticBranch
  /var/tmp/portage/dev-python/klein-21.8.0/work/klein-21.8.0/src/klein/test/test_resource.py:596: ResourceWarning: unclosed file <_io.BufferedReader name='/var/tmp/portage/dev-python/klein-21.8.0/work/klein-21.8.0/src/klein/test/__init__.py'>
    expected = open(

src/klein/test/test_resource.py::KleinResourceTests::test_staticRoot
  /var/tmp/portage/dev-python/klein-21.8.0/work/klein-21.8.0/src/klein/test/test_resource.py:578: ResourceWarning: unclosed file <_io.BufferedReader name='/var/tmp/portage/dev-python/klein-21.8.0/work/klein-21.8.0/src/klein/test/__init__.py'>
    expected = open(

-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
=========================== short test summary info ============================
FAILED src/klein/test/test_resource.py::KleinResourceTests::test_addSlash - A...
============ 1 failed, 241 passed, 36 warnings in 108.70s (0:01:48) ============
 * ERROR: dev-python/klein-21.8.0::gentoo failed (test phase):
 *   pytest failed with python3.8

dol-sen avatar Aug 18 '22 15:08 dol-sen

It appears you are running the test suite with pytest. Instead, run it like this: python -m twisted.trial klein or tox -e py38. Feel free to re-open if the issue persists when the tests are run that way.

exarkun avatar Aug 27 '22 12:08 exarkun

Well, something has changed since I added the 21.8.0 release to our Gentoo tree. I am now getting this same test fail error on my system (gcc/glibc based) using both pytest and twisted.trial.

Could this be a change in one of the dependencies causing this?

=============================================================================== [ERROR] Traceback (most recent call last): File "/usr/lib/python3.8/site-packages/klein/test/test_resource.py", line 642, in test_addSlash request.setHeader.assert_has_calls( File "/usr/lib/python3.8/unittest/mock.py", line 950, in assert_has_calls raise AssertionError( builtins.AssertionError: Calls not found. Expected: [call(b'Content-Type', b'text/html; charset=utf-8'), call(b'Content-Length', b'258'), call(b'Location', b'http://localhost:8080/foo/')] Actual: [call(b'Content-Type', b'text/html; charset=utf-8'), call(b'Content-Length', b'239'), call(b'Location', b'http://localhost:8080/foo/')]

klein.test.test_resource.KleinResourceTests.test_addSlash

Ran 242 tests in 126.510s

FAILED (errors=1, successes=241)

  • ERROR: dev-python/klein-21.8.0-r1::gentoo failed (test phase):

Installed Dependencies: storm /etc/portage # emerge -va1 --jobs=1 klein attrs hyperlink incremental tubes twisted werkzeug zope-interface hypothesis treq

These are the packages that would be merged, in order:

Calculating dependencies... done! [ebuild R ] dev-python/zope-interface-5.4.0-r2::gentoo USE="-test" PYTHON_TARGETS="python3_8 python3_9 python3_10 -pypy3 -python3_11" 0 KiB [ebuild R ] dev-python/attrs-22.1.0::gentoo USE="-test" PYTHON_TARGETS="python3_8 python3_9 python3_10 -pypy3 -python3_11" 0 KiB [ebuild R ] dev-python/hyperlink-21.0.0-r1::gentoo USE="-test" PYTHON_TARGETS="python3_8 python3_9 python3_10 -pypy3 -python3_11" 0 KiB [ebuild R ] dev-python/incremental-21.3.0-r1::gentoo USE="-test" PYTHON_TARGETS="python3_8 python3_9 python3_10 -pypy3 -python3_11" 0 KiB [ebuild R ] dev-python/werkzeug-2.2.2::gentoo USE="-test" PYTHON_TARGETS="python3_8 python3_9 python3_10 -pypy3 -python3_11" 0 KiB [ebuild R ] dev-python/hypothesis-6.54.4::gentoo USE="cli -test" PYTHON_TARGETS="python3_8 python3_9 python3_10 -pypy3 -python3_11" 0 KiB [ebuild R ] dev-python/twisted-22.4.0-r2::gentoo USE="http2 ssl -conch -serial -test" PYTHON_TARGETS="python3_8 python3_9 python3_10 -pypy3 -python3_11" 0 KiB [ebuild R ] dev-python/tubes-0.2.1::gentoo USE="-test" PYTHON_TARGETS="python3_8 python3_9 python3_10 -python3_11" 0 KiB [ebuild R ] dev-python/treq-22.2.0-r1::gentoo USE="-doc -test" PYTHON_TARGETS="python3_8 python3_9 python3_10" 0 KiB [ebuild R ] dev-python/klein-21.8.0-r1::gentoo USE="-test" PYTHON_TARGETS="python3_8 python3_9 python3_10" 0 KiB

Total: 10 packages (10 reinstalls), Size of downloads: 0 KiB

Would you like to merge these packages? [Yes/No] n

dol-sen avatar Aug 27 '22 16:08 dol-sen

Also, github is not letting me re-open this bug!

dol-sen avatar Aug 27 '22 16:08 dol-sen

Can one of the repo admins please re-open this issue for me?

dol-sen avatar Aug 27 '22 16:08 dol-sen

I just ran the test suite on the installed klein pkg and am getting the same failure. So it is not a network-sandbox issue with our emerge process.

dol-sen avatar Aug 27 '22 17:08 dol-sen

I just re-ran tests for all those pkgs that had tests enabled in their ebuilds, plus a few of their deps, and all passed except for klein again.

dol-sen avatar Aug 27 '22 19:08 dol-sen

On NixOS with Python 3.8.13 and 3.10.5 I tried to reproduce with:

pip install zope-interface==5.4.0 attrs==22.1.0 hyperlink==21.0.0 incremental==21.3.0 werkzeug==2.2.2 hypothesis==6.54.4 twisted==22.4.0 tubes==0.2.1 treq==22.2.0 klein==21.8.0
pip install -e klein-checkout
python -m twisted.trial klein

but I wasn't able to. :/

exarkun avatar Sep 01 '22 12:09 exarkun

However, with Klein 21.8.0 I did reproduce the failure.

exarkun avatar Sep 01 '22 12:09 exarkun

It looks like this was fixed in bce8b85036a6d185b9e8aab037c805f81354544c (merged in 404116929b9e7e798af2c7f1aa8a530639e5931a for #552).

So all that's needed now is a release.

The fix was a test-only fix, for what it's worth (the assertion about the exact content length is no longer made).

exarkun avatar Sep 01 '22 12:09 exarkun

This was included in 23.5.0

exarkun avatar Aug 07 '23 16:08 exarkun