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
100
from bzrlib.tests import (
101
106
from bzrlib.ui import NullProgressView
102
107
from bzrlib.ui.text import TextUIFactory
108
from bzrlib.tests.features import _CompatabilityThunkFeature
104
110
# Mark this python module as being part of the implementation
105
111
# of unittest: this gives us better tracebacks where the last
242
249
different types of display.
244
251
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
252
addFailure or addError methods. These in turn may redirect to a more
246
253
specific case for the special test results supported by our extended
353
360
return float(''.join(details['benchtime'].iter_bytes()))
354
361
return getattr(testCase, "_benchtime", None)
363
def _delta_to_float(self, a_timedelta, precision):
364
# This calls ceiling to ensure that the most pessimistic view of time
365
# taken is shown (rather than leaving it to the Python %f operator
366
# to decide whether to round/floor/ceiling. This was added when we
367
# had pyp3 test failures that suggest a floor was happening.
368
shift = 10 ** precision
369
return math.ceil((a_timedelta.days * 86400.0 + a_timedelta.seconds +
370
a_timedelta.microseconds / 1000000.0) * shift) / shift
356
372
def _elapsedTestTimeString(self):
357
373
"""Return a time string for the overall time the current test has taken."""
358
374
return self._formatTime(self._delta_to_float(
359
self._now() - self._start_datetime))
375
self._now() - self._start_datetime, 3))
361
377
def _testTimeString(self, testCase):
362
378
benchmark_time = self._extractBenchmarkTime(testCase)
995
1011
def setUp(self):
996
1012
super(TestCase, self).setUp()
1014
# At this point we're still accessing the config files in $BZR_HOME (as
1015
# set by the user running selftest).
1016
timeout = config.GlobalStack().get('selftest.timeout')
1018
timeout_fixture = fixtures.TimeoutFixture(timeout)
1019
timeout_fixture.setUp()
1020
self.addCleanup(timeout_fixture.cleanUp)
997
1022
for feature in getattr(self, '_test_needs_features', []):
998
1023
self.requireFeature(feature)
999
1024
self._cleanEnvironment()
1000
1026
if bzrlib.global_state is not None:
1001
1027
self.overrideAttr(bzrlib.global_state, 'cmdline_overrides',
1002
config.CommandLineSection())
1028
config.CommandLineStore())
1003
1030
self._silenceUI()
1004
1031
self._startLogFile()
1005
1032
self._benchcalls = []
1012
1039
# between tests. We should get rid of this altogether: bug 656694. --
1014
1041
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
1042
self._log_files = set()
1020
1043
# Each key in the ``_counters`` dict holds a value for a different
1021
1044
# counter. When the test ends, addDetail() should be used to output the
1314
1337
# hook into bzr dir opening. This leaves a small window of error for
1315
1338
# transport tests, but they are well known, and we can improve on this
1317
bzrdir.BzrDir.hooks.install_named_hook("pre_open",
1340
controldir.ControlDir.hooks.install_named_hook("pre_open",
1318
1341
self._preopen_isolate_transport, "Check bzr directories are safe.")
1320
1343
def _ndiff_strings(self, a, b):
1768
1791
:returns: The actual attr value.
1770
value = getattr(obj, attr_name)
1771
1793
# The actual value is captured by the call below
1772
self.addCleanup(setattr, obj, attr_name, value)
1794
value = getattr(obj, attr_name, _unitialized_attr)
1795
if value is _unitialized_attr:
1796
# When the test completes, the attribute should not exist, but if
1797
# we aren't setting a value, we don't need to do anything.
1798
if new is not _unitialized_attr:
1799
self.addCleanup(delattr, obj, attr_name)
1801
self.addCleanup(setattr, obj, attr_name, value)
1773
1802
if new is not _unitialized_attr:
1774
1803
setattr(obj, attr_name, new)
1979
2008
self.log('run bzr: %r', args)
1980
2009
# FIXME: don't call into logging here
1981
handler = logging.StreamHandler(stderr)
1982
handler.setLevel(logging.INFO)
2010
handler = trace.EncodedStreamHandler(stderr, errors="replace",
1983
2012
logger = logging.getLogger('')
1984
2013
logger.addHandler(handler)
1985
2014
old_ui_factory = ui.ui_factory
2174
2203
if env_changes is None:
2175
2204
env_changes = {}
2205
# Because $HOME is set to a tempdir for the context of a test, modules
2206
# installed in the user dir will not be found unless $PYTHONUSERBASE
2207
# gets set to the computed directory of this parent process.
2208
if site.USER_BASE is not None:
2209
env_changes["PYTHONUSERBASE"] = site.USER_BASE
2178
2212
def cleanup_environment():
2369
2403
from bzrlib.smart import request
2370
2404
request_handlers = request.request_handlers
2371
2405
orig_method = request_handlers.get(verb)
2406
orig_info = request_handlers.get_info(verb)
2372
2407
request_handlers.remove(verb)
2373
self.addCleanup(request_handlers.register, verb, orig_method)
2408
self.addCleanup(request_handlers.register, verb, orig_method,
2376
2412
class CapturedCall(object):
2429
2465
self.transport_readonly_server = None
2430
2466
self.__vfs_server = None
2469
super(TestCaseWithMemoryTransport, self).setUp()
2471
def _add_disconnect_cleanup(transport):
2472
"""Schedule disconnection of given transport at test cleanup
2474
This needs to happen for all connected transports or leaks occur.
2476
Note reconnections may mean we call disconnect multiple times per
2477
transport which is suboptimal but seems harmless.
2479
self.addCleanup(transport.disconnect)
2481
_mod_transport.Transport.hooks.install_named_hook('post_connect',
2482
_add_disconnect_cleanup, None)
2484
self._make_test_root()
2485
self.addCleanup(os.chdir, os.getcwdu())
2486
self.makeAndChdirToTestDir()
2487
self.overrideEnvironmentForTesting()
2488
self.__readonly_server = None
2489
self.__server = None
2490
self.reduceLockdirTimeout()
2491
# Each test may use its own config files even if the local config files
2492
# don't actually exist. They'll rightly fail if they try to create them
2494
self.overrideAttr(config, '_shared_stores', {})
2432
2496
def get_transport(self, relpath=None):
2433
2497
"""Return a writeable transport.
2579
2643
root = TestCaseWithMemoryTransport.TEST_ROOT
2580
# Make sure we get a readable and accessible home for .bzr.log
2581
# and/or config files, and not fallback to weird defaults (see
2582
# http://pad.lv/825027).
2583
self.assertIs(None, os.environ.get('BZR_HOME', None))
2584
os.environ['BZR_HOME'] = root
2585
wt = bzrdir.BzrDir.create_standalone_workingtree(root)
2586
del os.environ['BZR_HOME']
2645
# Make sure we get a readable and accessible home for .bzr.log
2646
# and/or config files, and not fallback to weird defaults (see
2647
# http://pad.lv/825027).
2648
self.assertIs(None, os.environ.get('BZR_HOME', None))
2649
os.environ['BZR_HOME'] = root
2650
wt = controldir.ControlDir.create_standalone_workingtree(root)
2651
del os.environ['BZR_HOME']
2652
except Exception, e:
2653
self.fail("Fail to initialize the safety net: %r\n" % (e,))
2587
2654
# Hack for speed: remember the raw bytes of the dirstate file so that
2588
2655
# we don't need to re-open the wt to check it hasn't changed.
2589
2656
TestCaseWithMemoryTransport._SAFETY_NET_PRISTINE_DIRSTATE = (
2637
2704
self.test_home_dir = self.test_dir + "/MemoryTransportMissingHomeDir"
2638
2705
self.permit_dir(self.test_dir)
2640
def make_branch(self, relpath, format=None):
2707
def make_branch(self, relpath, format=None, name=None):
2641
2708
"""Create a branch on the transport at relpath."""
2642
2709
repo = self.make_repository(relpath, format=format)
2643
return repo.bzrdir.create_branch(append_revisions_only=False)
2710
return repo.bzrdir.create_branch(append_revisions_only=False,
2645
2713
def get_default_format(self):
2646
2714
return 'default'
2658
2726
if format is None:
2659
2727
format = self.get_default_format()
2660
2728
if isinstance(format, basestring):
2661
format = bzrdir.format_registry.make_bzrdir(format)
2729
format = controldir.format_registry.make_bzrdir(format)
2664
2732
def make_bzrdir(self, relpath, format=None):
2711
2779
self.overrideEnv('HOME', test_home_dir)
2712
2780
self.overrideEnv('BZR_HOME', test_home_dir)
2715
super(TestCaseWithMemoryTransport, self).setUp()
2716
# Ensure that ConnectedTransport doesn't leak sockets
2717
def get_transport_from_url_with_cleanup(*args, **kwargs):
2718
t = orig_get_transport_from_url(*args, **kwargs)
2719
if isinstance(t, _mod_transport.ConnectedTransport):
2720
self.addCleanup(t.disconnect)
2723
orig_get_transport_from_url = self.overrideAttr(
2724
_mod_transport, 'get_transport_from_url',
2725
get_transport_from_url_with_cleanup)
2726
self._make_test_root()
2727
self.addCleanup(os.chdir, os.getcwdu())
2728
self.makeAndChdirToTestDir()
2729
self.overrideEnvironmentForTesting()
2730
self.__readonly_server = None
2731
self.__server = None
2732
self.reduceLockdirTimeout()
2734
2782
def setup_smart_server_with_call_log(self):
2735
2783
"""Sets up a smart server as the transport server with a call log."""
2736
2784
self.transport_server = test_server.SmartTCPServer_for_testing
2785
self.hpss_connections = []
2737
2786
self.hpss_calls = []
2738
2787
import traceback
2739
2788
# Skip the current stack down to the caller of
2742
2791
def capture_hpss_call(params):
2743
2792
self.hpss_calls.append(
2744
2793
CapturedCall(params, prefix_length))
2794
def capture_connect(transport):
2795
self.hpss_connections.append(transport)
2745
2796
client._SmartClient.hooks.install_named_hook(
2746
2797
'call', capture_hpss_call, None)
2798
_mod_transport.Transport.hooks.install_named_hook(
2799
'post_connect', capture_connect, None)
2748
2801
def reset_smart_call_log(self):
2749
2802
self.hpss_calls = []
2803
self.hpss_connections = []
2752
2806
class TestCaseInTempDir(TestCaseWithMemoryTransport):
2822
2876
# stacking policy to honour; create a bzr dir with an unshared
2823
2877
# repository (but not a branch - our code would be trying to escape
2824
2878
# then!) to stop them, and permit it to be read.
2825
# control = bzrdir.BzrDir.create(self.test_base_dir)
2879
# control = controldir.ControlDir.create(self.test_base_dir)
2826
2880
# control.create_repository()
2827
2881
self.test_home_dir = self.test_base_dir + '/home'
2828
2882
os.mkdir(self.test_home_dir)
2917
2971
readwrite one must both define get_url() as resolving to os.getcwd().
2975
super(TestCaseWithTransport, self).setUp()
2976
self.__vfs_server = None
2920
2978
def get_vfs_only_server(self):
2921
2979
"""See TestCaseWithMemoryTransport.
2968
3026
if self.vfs_transport_factory is test_server.LocalURLServer:
2969
3027
# the branch is colocated on disk, we cannot create a checkout.
2970
3028
# hopefully callers will expect this.
2971
local_controldir= bzrdir.BzrDir.open(self.get_vfs_only_url(relpath))
3029
local_controldir = controldir.ControlDir.open(
3030
self.get_vfs_only_url(relpath))
2972
3031
wt = local_controldir.create_workingtree()
2973
3032
if wt.branch._format != b._format:
3004
3063
self.assertFalse(differences.has_changed(),
3005
3064
"Trees %r and %r are different: %r" % (left, right, differences))
3008
super(TestCaseWithTransport, self).setUp()
3009
self.__vfs_server = None
3011
3066
def disable_missing_extensions_warning(self):
3012
3067
"""Some tests expect a precise stderr content.
3014
3069
There is no point in forcing them to duplicate the extension related
3017
config.GlobalConfig().set_user_option('ignore_missing_extensions', True)
3072
config.GlobalStack().set('ignore_missing_extensions', True)
3020
3075
class ChrootedTestCase(TestCaseWithTransport):
3748
3803
:return: (absents, duplicates) absents is a list containing the test found
3749
3804
in id_list but not in test_suite, duplicates is a list containing the
3750
test found multiple times in test_suite.
3805
tests found multiple times in test_suite.
3752
3807
When using a prefined test id list, it may occurs that some tests do not
3753
3808
exist anymore or that some tests use the same id. This function warns the
3878
3933
'bzrlib.tests.blackbox',
3879
3934
'bzrlib.tests.commands',
3880
'bzrlib.tests.doc_generate',
3881
3935
'bzrlib.tests.per_branch',
3882
3936
'bzrlib.tests.per_bzrdir',
3883
3937
'bzrlib.tests.per_controldir',
3971
4025
'bzrlib.tests.test_http',
3972
4026
'bzrlib.tests.test_http_response',
3973
4027
'bzrlib.tests.test_https_ca_bundle',
4028
'bzrlib.tests.test_https_urllib',
3974
4029
'bzrlib.tests.test_i18n',
3975
4030
'bzrlib.tests.test_identitymap',
3976
4031
'bzrlib.tests.test_ignores',
4025
4080
'bzrlib.tests.test_revisiontree',
4026
4081
'bzrlib.tests.test_rio',
4027
4082
'bzrlib.tests.test_rules',
4083
'bzrlib.tests.test_url_policy_open',
4028
4084
'bzrlib.tests.test_sampler',
4029
4085
'bzrlib.tests.test_scenarios',
4030
4086
'bzrlib.tests.test_script',
4074
4130
'bzrlib.tests.test_version',
4075
4131
'bzrlib.tests.test_version_info',
4076
4132
'bzrlib.tests.test_versionedfile',
4133
'bzrlib.tests.test_vf_search',
4077
4134
'bzrlib.tests.test_weave',
4078
4135
'bzrlib.tests.test_whitebox',
4079
4136
'bzrlib.tests.test_win32utils',
4294
4351
"""Copy test and apply scenario to it.
4296
4353
:param test: A test to adapt.
4297
:param scenario: A tuple describing the scenarion.
4354
:param scenario: A tuple describing the scenario.
4298
4355
The first element of the tuple is the new test id.
4299
4356
The second element is a dict containing attributes to set on the
4465
@deprecated_function(deprecated_in((2, 5, 0)))
4466
def ModuleAvailableFeature(name):
4467
from bzrlib.tests import features
4468
return features.ModuleAvailableFeature(name)
4522
# API compatibility for old plugins; see bug 892622.
4525
'HTTPServerFeature',
4526
'ModuleAvailableFeature',
4527
'HTTPSServerFeature', 'SymlinkFeature', 'HardlinkFeature',
4528
'OsFifoFeature', 'UnicodeFilenameFeature',
4529
'ByteStringNamedFilesystem', 'UTF8Filesystem',
4530
'BreakinFeature', 'CaseInsCasePresFilenameFeature',
4531
'CaseInsensitiveFilesystemFeature', 'case_sensitive_filesystem_feature',
4532
'posix_permissions_feature',
4534
globals()[name] = _CompatabilityThunkFeature(
4535
symbol_versioning.deprecated_in((2, 5, 0)),
4536
'bzrlib.tests', name,
4537
name, 'bzrlib.tests.features')
4540
for (old_name, new_name) in [
4541
('UnicodeFilename', 'UnicodeFilenameFeature'),
4543
globals()[name] = _CompatabilityThunkFeature(
4544
symbol_versioning.deprecated_in((2, 5, 0)),
4545
'bzrlib.tests', old_name,
4546
new_name, 'bzrlib.tests.features')