Closed lukasgraf closed 4 years ago
@lukasgraf why are you setting it up with buildout-py3.cfg
? In Python 3 this should not work at all because Products.ATContentTypes
is not ported to Python 3. Instead you should use buildout-py2.cfg
which pulls in all AT packages for the tests.
Another question: I do not understand why the issue only happens in TestBatchingArchetypes
and not in TestBatchingSearch
or any of the other DX testcases that use exactly the same event handler and test the same thing using a very similar testlayer (including plone.testing.zope.WSGIServer
).
@pbauer good point, I got that wrong. Should be buildout-py2.cfg
as you say. I'll retest it and update the steps to reproduce accordingly.
As for the second question: I think it might be because of a different order the individual tests are run in. If my suspicion about the thread local SiteInfo
being at the heart of the issue is correct, then it's basically a scenario where the first test's setup controls what instance of the stacked site manager is getting used for the rest of the layer.
I think this is n longer an issue, reopen if I am wrong.
(Follow-up issue from plone/Products.CMFPlone#2592)
Steps to reproduce
buildout-py2.cfg
ROBOT_BROWSER=chrome bin/test --all -s plone.app.widgets -s plone.restapi -t test_datetime_widget.robot -t TestBatchingArchetypes
(You may want to use
ROBOT_BROWSER=chrome bin/test ...
to run the robot tests with Chrome instead of FF)=>
Tests fail with
because a
plone.restapi
got HTML instead of JSON in a response.I've looked into this failure as part of https://github.com/plone/Products.CMFPlone/issues/2592#issuecomment-429538716.
The failure in
plone.restapi
happens because the subscriber registration of themark_as_api_request
forIPubStart
seems to vanish when a robotframework test like the one fromp.a.widgets
runs before it.This is the difference I'm seeing (all from inside a waitress request handler thread):
Passing test (just running the
plone.restapi
test alone):=> Site manager contains the event subscriber registration. Good.
Failing test (first the robot test from
p.a.widgets
, then theplone.restapi
test):=> Registration is missing.
When I further inspect which exact stacked component registry instance we're working with, I see something strange:
Passing test:
=> The current site manager is the last one from
plone.testing.zca
's component registry stack. Good.Failing test:
=> The current site manager is a different one than the last one from
plone.testing.zca
's stack, yet has the same name (test-stack-3
) / stack depth number.If we actually poke the last component registry from zca's stack (during the failing test), that's where our subscriber registration would be:
Failing test:
This leads be to believe that there's an isolation issue around the component registry with the
WSGIServer
layer.My hypothesis is this:
The reference to the current site manager is stored on the
SiteInfo
object inzope.component.hooks
.SiteInfo
is thread local. Since theWSGIServer
layer starts its threads on layer setUp, and only tears them down at layer teardown, its threads start off with aSiteInfo
instance after initial layer setup that is then detached from the main thread'sSiteInfo
(becomes thread-local) for the lifecycle of the layer.That would then render
plone.testing.zca
's attempts to provide component registry isolation via its stacked configuration contexts ineffective, because itspushGlobalRegistry()
/popGlobalRegistry()
functions operate on the main thread's site manager, not on the waitress thread one's.In an attempt to confirm this hypothesis, I changed
SiteInfo
to inherit fromobject
instead ofthreading.local
- and indeed, this did "fix" the test failure. I was also able to reproduce the test failure with other robot tests, not justp.a.widgets
- the robot tests fromp.a.multilingual
orp.a.contenttypes
cause exactly the same issue (if they happen to be run before theplone.restapi
test)./cc @davisagli (because you indicated you could maybe look into this eventually, and I'm out of my depth with threading issues around webtest/waitress/WSGI to be honest)