Fixed #27079 -- Avoided multiple setUpClass()/tearDownClass() calls in LiveServerTestCase tests.
This commit is contained in:
parent
cbd9f8531d
commit
def09bf412
|
@ -1533,7 +1533,11 @@ class LiveServerTestCase(TransactionTestCase):
|
||||||
ALLOWED_HOSTS={'append': cls.allowed_host},
|
ALLOWED_HOSTS={'append': cls.allowed_host},
|
||||||
)
|
)
|
||||||
cls._live_server_modified_settings.enable()
|
cls._live_server_modified_settings.enable()
|
||||||
|
cls.addClassCleanup(cls._live_server_modified_settings.disable)
|
||||||
|
cls._start_server_thread()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _start_server_thread(cls):
|
||||||
connections_override = cls._make_connections_override()
|
connections_override = cls._make_connections_override()
|
||||||
for conn in connections_override.values():
|
for conn in connections_override.values():
|
||||||
# Explicitly enable thread-shareability for this connection.
|
# Explicitly enable thread-shareability for this connection.
|
||||||
|
@ -1542,13 +1546,11 @@ class LiveServerTestCase(TransactionTestCase):
|
||||||
cls.server_thread = cls._create_server_thread(connections_override)
|
cls.server_thread = cls._create_server_thread(connections_override)
|
||||||
cls.server_thread.daemon = True
|
cls.server_thread.daemon = True
|
||||||
cls.server_thread.start()
|
cls.server_thread.start()
|
||||||
|
cls.addClassCleanup(cls._terminate_thread)
|
||||||
|
|
||||||
# Wait for the live server to be ready
|
# Wait for the live server to be ready
|
||||||
cls.server_thread.is_ready.wait()
|
cls.server_thread.is_ready.wait()
|
||||||
if cls.server_thread.error:
|
if cls.server_thread.error:
|
||||||
# Clean up behind ourselves, since tearDownClass won't get called in
|
|
||||||
# case of errors.
|
|
||||||
cls._tearDownClassInternal()
|
|
||||||
raise cls.server_thread.error
|
raise cls.server_thread.error
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -1561,20 +1563,13 @@ class LiveServerTestCase(TransactionTestCase):
|
||||||
)
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _tearDownClassInternal(cls):
|
def _terminate_thread(cls):
|
||||||
# Terminate the live server's thread.
|
# Terminate the live server's thread.
|
||||||
cls.server_thread.terminate()
|
cls.server_thread.terminate()
|
||||||
# Restore shared connections' non-shareability.
|
# Restore shared connections' non-shareability.
|
||||||
for conn in cls.server_thread.connections_override.values():
|
for conn in cls.server_thread.connections_override.values():
|
||||||
conn.dec_thread_sharing()
|
conn.dec_thread_sharing()
|
||||||
|
|
||||||
cls._live_server_modified_settings.disable()
|
|
||||||
super().tearDownClass()
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def tearDownClass(cls):
|
|
||||||
cls._tearDownClassInternal()
|
|
||||||
|
|
||||||
|
|
||||||
class SerializeMixin:
|
class SerializeMixin:
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -127,18 +127,12 @@ class LiveServerTestCaseSetupTest(LiveServerBase):
|
||||||
super().setUpClass()
|
super().setUpClass()
|
||||||
except RuntimeError:
|
except RuntimeError:
|
||||||
# LiveServerTestCase's change to ALLOWED_HOSTS should be reverted.
|
# LiveServerTestCase's change to ALLOWED_HOSTS should be reverted.
|
||||||
|
cls.doClassCleanups()
|
||||||
cls.check_allowed_hosts(['testserver'])
|
cls.check_allowed_hosts(['testserver'])
|
||||||
else:
|
else:
|
||||||
raise RuntimeError('Server did not fail.')
|
raise RuntimeError('Server did not fail.')
|
||||||
cls.set_up_called = True
|
cls.set_up_called = True
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def tearDownClass(cls):
|
|
||||||
# Make tearDownClass() a no-op because setUpClass() was already cleaned
|
|
||||||
# up, and because the error inside setUpClass() was handled, which will
|
|
||||||
# cause tearDownClass() to be called when it normally wouldn't.
|
|
||||||
pass
|
|
||||||
|
|
||||||
def test_set_up_class(self):
|
def test_set_up_class(self):
|
||||||
self.assertIs(self.set_up_called, True)
|
self.assertIs(self.set_up_called, True)
|
||||||
|
|
||||||
|
@ -334,7 +328,7 @@ class LiveServerPort(LiveServerBase):
|
||||||
"""
|
"""
|
||||||
TestCase = type("TestCase", (LiveServerBase,), {})
|
TestCase = type("TestCase", (LiveServerBase,), {})
|
||||||
try:
|
try:
|
||||||
TestCase.setUpClass()
|
TestCase._start_server_thread()
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
if e.errno == errno.EADDRINUSE:
|
if e.errno == errno.EADDRINUSE:
|
||||||
# We're out of ports, LiveServerTestCase correctly fails with
|
# We're out of ports, LiveServerTestCase correctly fails with
|
||||||
|
@ -342,15 +336,12 @@ class LiveServerPort(LiveServerBase):
|
||||||
return
|
return
|
||||||
# Unexpected error.
|
# Unexpected error.
|
||||||
raise
|
raise
|
||||||
try:
|
self.assertNotEqual(
|
||||||
# We've acquired a port, ensure our server threads acquired
|
self.live_server_url,
|
||||||
# different addresses.
|
TestCase.live_server_url,
|
||||||
self.assertNotEqual(
|
f'Acquired duplicate server addresses for server threads: '
|
||||||
self.live_server_url, TestCase.live_server_url,
|
f'{self.live_server_url}',
|
||||||
"Acquired duplicate server addresses for server threads: %s" % self.live_server_url
|
)
|
||||||
)
|
|
||||||
finally:
|
|
||||||
TestCase.tearDownClass()
|
|
||||||
|
|
||||||
def test_specified_port_bind(self):
|
def test_specified_port_bind(self):
|
||||||
"""LiveServerTestCase.port customizes the server's port."""
|
"""LiveServerTestCase.port customizes the server's port."""
|
||||||
|
@ -360,14 +351,13 @@ class LiveServerPort(LiveServerBase):
|
||||||
s.bind(('', 0))
|
s.bind(('', 0))
|
||||||
TestCase.port = s.getsockname()[1]
|
TestCase.port = s.getsockname()[1]
|
||||||
s.close()
|
s.close()
|
||||||
TestCase.setUpClass()
|
TestCase._start_server_thread()
|
||||||
try:
|
self.assertEqual(
|
||||||
self.assertEqual(
|
TestCase.port,
|
||||||
TestCase.port, TestCase.server_thread.port,
|
TestCase.server_thread.port,
|
||||||
'Did not use specified port for LiveServerTestCase thread: %s' % TestCase.port
|
f'Did not use specified port for LiveServerTestCase thread: '
|
||||||
)
|
f'{TestCase.port}',
|
||||||
finally:
|
)
|
||||||
TestCase.tearDownClass()
|
|
||||||
|
|
||||||
|
|
||||||
class LiveServerThreadedTests(LiveServerBase):
|
class LiveServerThreadedTests(LiveServerBase):
|
||||||
|
|
|
@ -29,22 +29,8 @@ class LiveServerBase(StaticLiveServerTestCase):
|
||||||
# Override settings
|
# Override settings
|
||||||
cls.settings_override = override_settings(**TEST_SETTINGS)
|
cls.settings_override = override_settings(**TEST_SETTINGS)
|
||||||
cls.settings_override.enable()
|
cls.settings_override.enable()
|
||||||
try:
|
cls.addClassCleanup(cls.settings_override.disable)
|
||||||
super().setUpClass()
|
super().setUpClass()
|
||||||
except Exception:
|
|
||||||
# Clean up since tearDownClass() isn't called on errors.
|
|
||||||
cls._tearDownLiveServerBase()
|
|
||||||
raise
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def _tearDownLiveServerBase(cls):
|
|
||||||
# Restore original settings
|
|
||||||
cls.settings_override.disable()
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def tearDownClass(cls):
|
|
||||||
super().tearDownClass()
|
|
||||||
cls._tearDownLiveServerBase()
|
|
||||||
|
|
||||||
|
|
||||||
class StaticLiveServerChecks(LiveServerBase):
|
class StaticLiveServerChecks(LiveServerBase):
|
||||||
|
@ -74,8 +60,6 @@ class StaticLiveServerChecks(LiveServerBase):
|
||||||
# app without having set the required STATIC_URL setting.")
|
# app without having set the required STATIC_URL setting.")
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
# super().setUpClass() cleans up after itself on a failure.
|
|
||||||
super().tearDownClass()
|
|
||||||
raise Exception('setUpClass() should have raised an exception.')
|
raise Exception('setUpClass() should have raised an exception.')
|
||||||
|
|
||||||
def test_test_test(self):
|
def test_test_test(self):
|
||||||
|
|
Loading…
Reference in New Issue