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
248
different types of display.
244
250
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
251
addFailure or addError methods. These in turn may redirect to a more
246
252
specific case for the special test results supported by our extended
995
1001
def setUp(self):
996
1002
super(TestCase, self).setUp()
1004
# At this point we're still accessing the config files in $BZR_HOME (as
1005
# set by the user running selftest).
1006
timeout = config.GlobalStack().get('selftest.timeout')
1008
timeout_fixture = fixtures.TimeoutFixture(timeout)
1009
timeout_fixture.setUp()
1010
self.addCleanup(timeout_fixture.cleanUp)
997
1012
for feature in getattr(self, '_test_needs_features', []):
998
1013
self.requireFeature(feature)
999
1014
self._cleanEnvironment()
1000
1016
if bzrlib.global_state is not None:
1001
1017
self.overrideAttr(bzrlib.global_state, 'cmdline_overrides',
1002
config.CommandLineSection())
1018
config.CommandLineStore())
1003
1020
self._silenceUI()
1004
1021
self._startLogFile()
1005
1022
self._benchcalls = []
1012
1029
# between tests. We should get rid of this altogether: bug 656694. --
1014
1031
self.overrideAttr(bzrlib.trace, '_verbosity_level', 0)
1015
# Isolate config option expansion until its default value for bzrlib is
1016
# settled on or a the FIXME associated with _get_expand_default_value
1017
# is addressed -- vila 20110219
1018
self.overrideAttr(config, '_expand_default_value', None)
1019
1032
self._log_files = set()
1020
1033
# Each key in the ``_counters`` dict holds a value for a different
1021
1034
# counter. When the test ends, addDetail() should be used to output the
1314
1327
# hook into bzr dir opening. This leaves a small window of error for
1315
1328
# transport tests, but they are well known, and we can improve on this
1317
bzrdir.BzrDir.hooks.install_named_hook("pre_open",
1330
controldir.ControlDir.hooks.install_named_hook("pre_open",
1318
1331
self._preopen_isolate_transport, "Check bzr directories are safe.")
1320
1333
def _ndiff_strings(self, a, b):
1720
1733
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.
1734
"""Setup a in-memory target for bzr and testcase log messages"""
1725
1735
pseudo_log_file = StringIO()
1726
1736
def _get_log_contents_for_weird_testtools_api():
1727
1737
return [pseudo_log_file.getvalue().decode(
1734
1744
self.addCleanup(self._finishLogFile)
1736
1746
def _finishLogFile(self):
1737
"""Finished with the log file.
1739
Close the file and delete it.
1747
"""Flush and dereference the in-memory log for this testcase"""
1741
1748
if trace._trace_file:
1742
1749
# flush the log file, to get all content
1743
1750
trace._trace_file.flush()
1744
1751
trace.pop_log_file(self._log_memento)
1752
# The logging module now tracks references for cleanup so discard ours
1753
del self._log_memento
1746
1755
def thisFailsStrictLockCheck(self):
1747
1756
"""It is known that this test would fail with -Dstrict_locks.
1772
1781
:returns: The actual attr value.
1774
value = getattr(obj, attr_name)
1775
1783
# The actual value is captured by the call below
1776
self.addCleanup(setattr, obj, attr_name, value)
1784
value = getattr(obj, attr_name, _unitialized_attr)
1785
if value is _unitialized_attr:
1786
# When the test completes, the attribute should not exist, but if
1787
# we aren't setting a value, we don't need to do anything.
1788
if new is not _unitialized_attr:
1789
self.addCleanup(delattr, obj, attr_name)
1791
self.addCleanup(setattr, obj, attr_name, value)
1777
1792
if new is not _unitialized_attr:
1778
1793
setattr(obj, attr_name, new)
1983
1998
self.log('run bzr: %r', args)
1984
1999
# FIXME: don't call into logging here
1985
handler = logging.StreamHandler(stderr)
1986
handler.setLevel(logging.INFO)
2000
handler = trace.EncodedStreamHandler(stderr, errors="replace",
1987
2002
logger = logging.getLogger('')
1988
2003
logger.addHandler(handler)
1989
2004
old_ui_factory = ui.ui_factory
2178
2193
if env_changes is None:
2179
2194
env_changes = {}
2195
# Because $HOME is set to a tempdir for the context of a test, modules
2196
# installed in the user dir will not be found unless $PYTHONUSERBASE
2197
# gets set to the computed directory of this parent process.
2198
if site.USER_BASE is not None:
2199
env_changes["PYTHONUSERBASE"] = site.USER_BASE
2182
2202
def cleanup_environment():
2373
2393
from bzrlib.smart import request
2374
2394
request_handlers = request.request_handlers
2375
2395
orig_method = request_handlers.get(verb)
2396
orig_info = request_handlers.get_info(verb)
2376
2397
request_handlers.remove(verb)
2377
self.addCleanup(request_handlers.register, verb, orig_method)
2398
self.addCleanup(request_handlers.register, verb, orig_method,
2380
2402
class CapturedCall(object):
2433
2455
self.transport_readonly_server = None
2434
2456
self.__vfs_server = None
2459
super(TestCaseWithMemoryTransport, self).setUp()
2461
def _add_disconnect_cleanup(transport):
2462
"""Schedule disconnection of given transport at test cleanup
2464
This needs to happen for all connected transports or leaks occur.
2466
Note reconnections may mean we call disconnect multiple times per
2467
transport which is suboptimal but seems harmless.
2469
self.addCleanup(transport.disconnect)
2471
_mod_transport.Transport.hooks.install_named_hook('post_connect',
2472
_add_disconnect_cleanup, None)
2474
self._make_test_root()
2475
self.addCleanup(os.chdir, os.getcwdu())
2476
self.makeAndChdirToTestDir()
2477
self.overrideEnvironmentForTesting()
2478
self.__readonly_server = None
2479
self.__server = None
2480
self.reduceLockdirTimeout()
2481
# Each test may use its own config files even if the local config files
2482
# don't actually exist. They'll rightly fail if they try to create them
2484
self.overrideAttr(config, '_shared_stores', {})
2436
2486
def get_transport(self, relpath=None):
2437
2487
"""Return a writeable transport.
2583
2633
root = TestCaseWithMemoryTransport.TEST_ROOT
2584
# Make sure we get a readable and accessible home for .bzr.log
2585
# and/or config files, and not fallback to weird defaults (see
2586
# http://pad.lv/825027).
2587
self.assertIs(None, os.environ.get('BZR_HOME', None))
2588
os.environ['BZR_HOME'] = root
2589
wt = bzrdir.BzrDir.create_standalone_workingtree(root)
2590
del os.environ['BZR_HOME']
2635
# Make sure we get a readable and accessible home for .bzr.log
2636
# and/or config files, and not fallback to weird defaults (see
2637
# http://pad.lv/825027).
2638
self.assertIs(None, os.environ.get('BZR_HOME', None))
2639
os.environ['BZR_HOME'] = root
2640
wt = controldir.ControlDir.create_standalone_workingtree(root)
2641
del os.environ['BZR_HOME']
2642
except Exception, e:
2643
self.fail("Fail to initialize the safety net: %r\n" % (e,))
2591
2644
# Hack for speed: remember the raw bytes of the dirstate file so that
2592
2645
# we don't need to re-open the wt to check it hasn't changed.
2593
2646
TestCaseWithMemoryTransport._SAFETY_NET_PRISTINE_DIRSTATE = (
2641
2694
self.test_home_dir = self.test_dir + "/MemoryTransportMissingHomeDir"
2642
2695
self.permit_dir(self.test_dir)
2644
def make_branch(self, relpath, format=None):
2697
def make_branch(self, relpath, format=None, name=None):
2645
2698
"""Create a branch on the transport at relpath."""
2646
2699
repo = self.make_repository(relpath, format=format)
2647
return repo.bzrdir.create_branch(append_revisions_only=False)
2700
return repo.bzrdir.create_branch(append_revisions_only=False,
2649
2703
def get_default_format(self):
2650
2704
return 'default'
2662
2716
if format is None:
2663
2717
format = self.get_default_format()
2664
2718
if isinstance(format, basestring):
2665
format = bzrdir.format_registry.make_bzrdir(format)
2719
format = controldir.format_registry.make_bzrdir(format)
2668
2722
def make_bzrdir(self, relpath, format=None):
2715
2769
self.overrideEnv('HOME', test_home_dir)
2716
2770
self.overrideEnv('BZR_HOME', test_home_dir)
2719
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)
2730
self._make_test_root()
2731
self.addCleanup(os.chdir, os.getcwdu())
2732
self.makeAndChdirToTestDir()
2733
self.overrideEnvironmentForTesting()
2734
self.__readonly_server = None
2735
self.__server = None
2736
self.reduceLockdirTimeout()
2738
2772
def setup_smart_server_with_call_log(self):
2739
2773
"""Sets up a smart server as the transport server with a call log."""
2740
2774
self.transport_server = test_server.SmartTCPServer_for_testing
2775
self.hpss_connections = []
2741
2776
self.hpss_calls = []
2742
2777
import traceback
2743
2778
# Skip the current stack down to the caller of
2746
2781
def capture_hpss_call(params):
2747
2782
self.hpss_calls.append(
2748
2783
CapturedCall(params, prefix_length))
2784
def capture_connect(transport):
2785
self.hpss_connections.append(transport)
2749
2786
client._SmartClient.hooks.install_named_hook(
2750
2787
'call', capture_hpss_call, None)
2788
_mod_transport.Transport.hooks.install_named_hook(
2789
'post_connect', capture_connect, None)
2752
2791
def reset_smart_call_log(self):
2753
2792
self.hpss_calls = []
2793
self.hpss_connections = []
2756
2796
class TestCaseInTempDir(TestCaseWithMemoryTransport):
2826
2866
# stacking policy to honour; create a bzr dir with an unshared
2827
2867
# repository (but not a branch - our code would be trying to escape
2828
2868
# then!) to stop them, and permit it to be read.
2829
# control = bzrdir.BzrDir.create(self.test_base_dir)
2869
# control = controldir.ControlDir.create(self.test_base_dir)
2830
2870
# control.create_repository()
2831
2871
self.test_home_dir = self.test_base_dir + '/home'
2832
2872
os.mkdir(self.test_home_dir)
2921
2961
readwrite one must both define get_url() as resolving to os.getcwd().
2965
super(TestCaseWithTransport, self).setUp()
2966
self.__vfs_server = None
2924
2968
def get_vfs_only_server(self):
2925
2969
"""See TestCaseWithMemoryTransport.
2972
3016
if self.vfs_transport_factory is test_server.LocalURLServer:
2973
3017
# the branch is colocated on disk, we cannot create a checkout.
2974
3018
# hopefully callers will expect this.
2975
local_controldir= bzrdir.BzrDir.open(self.get_vfs_only_url(relpath))
3019
local_controldir = controldir.ControlDir.open(
3020
self.get_vfs_only_url(relpath))
2976
3021
wt = local_controldir.create_workingtree()
2977
3022
if wt.branch._format != b._format:
3008
3053
self.assertFalse(differences.has_changed(),
3009
3054
"Trees %r and %r are different: %r" % (left, right, differences))
3012
super(TestCaseWithTransport, self).setUp()
3013
self.__vfs_server = None
3015
3056
def disable_missing_extensions_warning(self):
3016
3057
"""Some tests expect a precise stderr content.
3018
3059
There is no point in forcing them to duplicate the extension related
3021
config.GlobalConfig().set_user_option('ignore_missing_extensions', True)
3062
config.GlobalStack().set('ignore_missing_extensions', True)
3024
3065
class ChrootedTestCase(TestCaseWithTransport):
3493
3534
ProtocolTestCase.run(self, result)
3495
os.waitpid(self.pid, 0)
3536
pid, status = os.waitpid(self.pid, 0)
3537
# GZ 2011-10-18: If status is nonzero, should report to the result
3538
# that something went wrong.
3497
3540
test_blocks = partition_tests(suite, concurrency)
3498
3541
# Clear the tests from the original suite so it doesn't keep them alive
3504
3547
c2pread, c2pwrite = os.pipe()
3505
3548
pid = os.fork()
3507
workaround_zealous_crypto_random()
3551
stream = os.fdopen(c2pwrite, 'wb', 1)
3552
workaround_zealous_crypto_random()
3509
3553
os.close(c2pread)
3510
3554
# Leave stderr and stdout open so we can see test noise
3511
3555
# Close stdin so that the child goes away if it decides to
3512
3556
# read from stdin (otherwise its a roulette to see what
3513
3557
# child actually gets keystrokes for pdb etc).
3514
3558
sys.stdin.close()
3515
# GZ 2011-06-16: Why set stdin to None? Breaks multi fork.
3517
stream = os.fdopen(c2pwrite, 'wb', 1)
3518
3559
subunit_result = AutoTimingTestResultDecorator(
3519
3560
SubUnitBzrProtocolClient(stream))
3520
3561
process_suite.run(subunit_result)
3522
# GZ 2011-06-16: Is always exiting with silent success
3523
# really the right thing? Hurts debugging.
3563
# Try and report traceback on stream, but exit with error even
3564
# if stream couldn't be created or something else goes wrong.
3565
# The traceback is formatted to a string and written in one go
3566
# to avoid interleaving lines from multiple failing children.
3568
stream.write(traceback.format_exc())
3526
3573
os.close(c2pwrite)
3527
3574
stream = os.fdopen(c2pread, 'rb', 1)
3746
3793
:return: (absents, duplicates) absents is a list containing the test found
3747
3794
in id_list but not in test_suite, duplicates is a list containing the
3748
test found multiple times in test_suite.
3795
tests found multiple times in test_suite.
3750
3797
When using a prefined test id list, it may occurs that some tests do not
3751
3798
exist anymore or that some tests use the same id. This function warns the
3876
3923
'bzrlib.tests.blackbox',
3877
3924
'bzrlib.tests.commands',
3878
'bzrlib.tests.doc_generate',
3879
3925
'bzrlib.tests.per_branch',
3880
3926
'bzrlib.tests.per_bzrdir',
3881
3927
'bzrlib.tests.per_controldir',
3969
4015
'bzrlib.tests.test_http',
3970
4016
'bzrlib.tests.test_http_response',
3971
4017
'bzrlib.tests.test_https_ca_bundle',
4018
'bzrlib.tests.test_https_urllib',
3972
4019
'bzrlib.tests.test_i18n',
3973
4020
'bzrlib.tests.test_identitymap',
3974
4021
'bzrlib.tests.test_ignores',
4023
4070
'bzrlib.tests.test_revisiontree',
4024
4071
'bzrlib.tests.test_rio',
4025
4072
'bzrlib.tests.test_rules',
4073
'bzrlib.tests.test_url_policy_open',
4026
4074
'bzrlib.tests.test_sampler',
4027
4075
'bzrlib.tests.test_scenarios',
4028
4076
'bzrlib.tests.test_script',
4072
4120
'bzrlib.tests.test_version',
4073
4121
'bzrlib.tests.test_version_info',
4074
4122
'bzrlib.tests.test_versionedfile',
4123
'bzrlib.tests.test_vf_search',
4075
4124
'bzrlib.tests.test_weave',
4076
4125
'bzrlib.tests.test_whitebox',
4077
4126
'bzrlib.tests.test_win32utils',
4292
4341
"""Copy test and apply scenario to it.
4294
4343
:param test: A test to adapt.
4295
:param scenario: A tuple describing the scenarion.
4344
:param scenario: A tuple describing the scenario.
4296
4345
The first element of the tuple is the new test id.
4297
4346
The second element is a dict containing attributes to set on the
4463
@deprecated_function(deprecated_in((2, 5, 0)))
4464
def ModuleAvailableFeature(name):
4465
from bzrlib.tests import features
4466
return features.ModuleAvailableFeature(name)
4512
# API compatibility for old plugins; see bug 892622.
4515
'HTTPServerFeature',
4516
'ModuleAvailableFeature',
4517
'HTTPSServerFeature', 'SymlinkFeature', 'HardlinkFeature',
4518
'OsFifoFeature', 'UnicodeFilenameFeature',
4519
'ByteStringNamedFilesystem', 'UTF8Filesystem',
4520
'BreakinFeature', 'CaseInsCasePresFilenameFeature',
4521
'CaseInsensitiveFilesystemFeature', 'case_sensitive_filesystem_feature',
4522
'posix_permissions_feature',
4524
globals()[name] = _CompatabilityThunkFeature(
4525
symbol_versioning.deprecated_in((2, 5, 0)),
4526
'bzrlib.tests', name,
4527
name, 'bzrlib.tests.features')
4530
for (old_name, new_name) in [
4531
('UnicodeFilename', 'UnicodeFilenameFeature'),
4533
globals()[name] = _CompatabilityThunkFeature(
4534
symbol_versioning.deprecated_in((2, 5, 0)),
4535
'bzrlib.tests', old_name,
4536
new_name, 'bzrlib.tests.features')