17
17
"""Testing framework extensions"""
19
from __future__ import absolute_import
19
21
# NOTE: Some classes in here use camelCaseNaming() rather than
20
22
# underscore_naming(). That's for consistency with unittest; it's not the
21
23
# general style of bzrlib. Please continue that consistency when adding e.g.
96
99
from bzrlib.tests import (
101
105
from bzrlib.ui import NullProgressView
102
106
from bzrlib.ui.text import TextUIFactory
107
from bzrlib.tests.features import _CompatabilityThunkFeature
104
109
# Mark this python module as being part of the implementation
105
110
# of unittest: this gives us better tracebacks where the last
242
247
different types of display.
244
249
When a test finishes, in whatever way, it calls one of the addSuccess,
245
addFailure or addError classes. These in turn may redirect to a more
250
addFailure or addError methods. These in turn may redirect to a more
246
251
specific case for the special test results supported by our extended
995
1000
def setUp(self):
996
1001
super(TestCase, self).setUp()
1003
timeout = config.GlobalStack().get('selftest.timeout')
1005
timeout_fixture = fixtures.TimeoutFixture(timeout)
1006
timeout_fixture.setUp()
1007
self.addCleanup(timeout_fixture.cleanUp)
997
1009
for feature in getattr(self, '_test_needs_features', []):
998
1010
self.requireFeature(feature)
999
1011
self._cleanEnvironment()
1000
1013
if bzrlib.global_state is not None:
1001
1014
self.overrideAttr(bzrlib.global_state, 'cmdline_overrides',
1002
config.CommandLineSection())
1015
config.CommandLineStore())
1003
1017
self._silenceUI()
1004
1018
self._startLogFile()
1005
1019
self._benchcalls = []
1720
1734
def _startLogFile(self):
1721
"""Send bzr and test log messages to a temporary file.
1723
The file is removed as the test is torn down.
1735
"""Setup a in-memory target for bzr and testcase log messages"""
1725
1736
pseudo_log_file = StringIO()
1726
1737
def _get_log_contents_for_weird_testtools_api():
1727
1738
return [pseudo_log_file.getvalue().decode(
1734
1745
self.addCleanup(self._finishLogFile)
1736
1747
def _finishLogFile(self):
1737
"""Finished with the log file.
1739
Close the file and delete it.
1748
"""Flush and dereference the in-memory log for this testcase"""
1741
1749
if trace._trace_file:
1742
1750
# flush the log file, to get all content
1743
1751
trace._trace_file.flush()
1744
1752
trace.pop_log_file(self._log_memento)
1753
# The logging module now tracks references for cleanup so discard ours
1754
del self._log_memento
1746
1756
def thisFailsStrictLockCheck(self):
1747
1757
"""It is known that this test would fail with -Dstrict_locks.
1983
1993
self.log('run bzr: %r', args)
1984
1994
# FIXME: don't call into logging here
1985
handler = logging.StreamHandler(stderr)
1986
handler.setLevel(logging.INFO)
1995
handler = trace.EncodedStreamHandler(stderr, errors="replace",
1987
1997
logger = logging.getLogger('')
1988
1998
logger.addHandler(handler)
1989
1999
old_ui_factory = ui.ui_factory
2178
2188
if env_changes is None:
2179
2189
env_changes = {}
2190
# Because $HOME is set to a tempdir for the context of a test, modules
2191
# installed in the user dir will not be found unless $PYTHONUSERBASE
2192
# gets set to the computed directory of this parent process.
2193
if site.USER_BASE is not None:
2194
env_changes["PYTHONUSERBASE"] = site.USER_BASE
2182
2197
def cleanup_environment():
2373
2388
from bzrlib.smart import request
2374
2389
request_handlers = request.request_handlers
2375
2390
orig_method = request_handlers.get(verb)
2391
orig_info = request_handlers.get_info(verb)
2376
2392
request_handlers.remove(verb)
2377
self.addCleanup(request_handlers.register, verb, orig_method)
2393
self.addCleanup(request_handlers.register, verb, orig_method,
2380
2397
class CapturedCall(object):
2641
2658
self.test_home_dir = self.test_dir + "/MemoryTransportMissingHomeDir"
2642
2659
self.permit_dir(self.test_dir)
2644
def make_branch(self, relpath, format=None):
2661
def make_branch(self, relpath, format=None, name=None):
2645
2662
"""Create a branch on the transport at relpath."""
2646
2663
repo = self.make_repository(relpath, format=format)
2647
return repo.bzrdir.create_branch(append_revisions_only=False)
2664
return repo.bzrdir.create_branch(append_revisions_only=False,
2649
2667
def get_default_format(self):
2650
2668
return 'default'
2718
2736
def setUp(self):
2719
2737
super(TestCaseWithMemoryTransport, self).setUp()
2720
# Ensure that ConnectedTransport doesn't leak sockets
2721
def get_transport_from_url_with_cleanup(*args, **kwargs):
2722
t = orig_get_transport_from_url(*args, **kwargs)
2723
if isinstance(t, _mod_transport.ConnectedTransport):
2724
self.addCleanup(t.disconnect)
2727
orig_get_transport_from_url = self.overrideAttr(
2728
_mod_transport, 'get_transport_from_url',
2729
get_transport_from_url_with_cleanup)
2739
def _add_disconnect_cleanup(transport):
2740
"""Schedule disconnection of given transport at test cleanup
2742
This needs to happen for all connected transports or leaks occur.
2744
Note reconnections may mean we call disconnect multiple times per
2745
transport which is suboptimal but seems harmless.
2747
self.addCleanup(transport.disconnect)
2749
_mod_transport.Transport.hooks.install_named_hook('post_connect',
2750
_add_disconnect_cleanup, None)
2730
2752
self._make_test_root()
2731
2753
self.addCleanup(os.chdir, os.getcwdu())
2732
2754
self.makeAndChdirToTestDir()
2738
2760
def setup_smart_server_with_call_log(self):
2739
2761
"""Sets up a smart server as the transport server with a call log."""
2740
2762
self.transport_server = test_server.SmartTCPServer_for_testing
2763
self.hpss_connections = []
2741
2764
self.hpss_calls = []
2742
2765
import traceback
2743
2766
# Skip the current stack down to the caller of
2746
2769
def capture_hpss_call(params):
2747
2770
self.hpss_calls.append(
2748
2771
CapturedCall(params, prefix_length))
2772
def capture_connect(transport):
2773
self.hpss_connections.append(transport)
2749
2774
client._SmartClient.hooks.install_named_hook(
2750
2775
'call', capture_hpss_call, None)
2776
_mod_transport.Transport.hooks.install_named_hook(
2777
'post_connect', capture_connect, None)
2752
2779
def reset_smart_call_log(self):
2753
2780
self.hpss_calls = []
2781
self.hpss_connections = []
2756
2784
class TestCaseInTempDir(TestCaseWithMemoryTransport):
3493
3521
ProtocolTestCase.run(self, result)
3495
os.waitpid(self.pid, 0)
3523
pid, status = os.waitpid(self.pid, 0)
3524
# GZ 2011-10-18: If status is nonzero, should report to the result
3525
# that something went wrong.
3497
3527
test_blocks = partition_tests(suite, concurrency)
3498
3528
# Clear the tests from the original suite so it doesn't keep them alive
3504
3534
c2pread, c2pwrite = os.pipe()
3505
3535
pid = os.fork()
3507
workaround_zealous_crypto_random()
3538
stream = os.fdopen(c2pwrite, 'wb', 1)
3539
workaround_zealous_crypto_random()
3509
3540
os.close(c2pread)
3510
3541
# Leave stderr and stdout open so we can see test noise
3511
3542
# Close stdin so that the child goes away if it decides to
3512
3543
# read from stdin (otherwise its a roulette to see what
3513
3544
# child actually gets keystrokes for pdb etc).
3514
3545
sys.stdin.close()
3515
# GZ 2011-06-16: Why set stdin to None? Breaks multi fork.
3517
stream = os.fdopen(c2pwrite, 'wb', 1)
3518
3546
subunit_result = AutoTimingTestResultDecorator(
3519
3547
SubUnitBzrProtocolClient(stream))
3520
3548
process_suite.run(subunit_result)
3522
# GZ 2011-06-16: Is always exiting with silent success
3523
# really the right thing? Hurts debugging.
3550
# Try and report traceback on stream, but exit with error even
3551
# if stream couldn't be created or something else goes wrong.
3552
# The traceback is formatted to a string and written in one go
3553
# to avoid interleaving lines from multiple failing children.
3555
stream.write(traceback.format_exc())
3526
3560
os.close(c2pwrite)
3527
3561
stream = os.fdopen(c2pread, 'rb', 1)
3969
4003
'bzrlib.tests.test_http',
3970
4004
'bzrlib.tests.test_http_response',
3971
4005
'bzrlib.tests.test_https_ca_bundle',
4006
'bzrlib.tests.test_https_urllib',
3972
4007
'bzrlib.tests.test_i18n',
3973
4008
'bzrlib.tests.test_identitymap',
3974
4009
'bzrlib.tests.test_ignores',
4023
4058
'bzrlib.tests.test_revisiontree',
4024
4059
'bzrlib.tests.test_rio',
4025
4060
'bzrlib.tests.test_rules',
4061
'bzrlib.tests.test_url_policy_open',
4026
4062
'bzrlib.tests.test_sampler',
4027
4063
'bzrlib.tests.test_scenarios',
4028
4064
'bzrlib.tests.test_script',
4072
4108
'bzrlib.tests.test_version',
4073
4109
'bzrlib.tests.test_version_info',
4074
4110
'bzrlib.tests.test_versionedfile',
4111
'bzrlib.tests.test_vf_search',
4075
4112
'bzrlib.tests.test_weave',
4076
4113
'bzrlib.tests.test_whitebox',
4077
4114
'bzrlib.tests.test_win32utils',
4463
@deprecated_function(deprecated_in((2, 5, 0)))
4464
def ModuleAvailableFeature(name):
4465
from bzrlib.tests import features
4466
return features.ModuleAvailableFeature(name)
4500
# API compatibility for old plugins; see bug 892622.
4503
'HTTPServerFeature',
4504
'ModuleAvailableFeature',
4505
'HTTPSServerFeature', 'SymlinkFeature', 'HardlinkFeature',
4506
'OsFifoFeature', 'UnicodeFilenameFeature',
4507
'ByteStringNamedFilesystem', 'UTF8Filesystem',
4508
'BreakinFeature', 'CaseInsCasePresFilenameFeature',
4509
'CaseInsensitiveFilesystemFeature', 'case_sensitive_filesystem_feature',
4510
'posix_permissions_feature',
4512
globals()[name] = _CompatabilityThunkFeature(
4513
symbol_versioning.deprecated_in((2, 5, 0)),
4514
'bzrlib.tests', name,
4515
name, 'bzrlib.tests.features')
4518
for (old_name, new_name) in [
4519
('UnicodeFilename', 'UnicodeFilenameFeature'),
4521
globals()[name] = _CompatabilityThunkFeature(
4522
symbol_versioning.deprecated_in((2, 5, 0)),
4523
'bzrlib.tests', old_name,
4524
new_name, 'bzrlib.tests.features')