212
219
osutils.set_or_unset_env(var, value)
222
def _clear__type_equality_funcs(test):
223
"""Cleanup bound methods stored on TestCase instances
225
Clear the dict breaking a few (mostly) harmless cycles in the affected
226
unittests released with Python 2.6 and initial Python 2.7 versions.
228
For a few revisions between Python 2.7.1 and Python 2.7.2 that annoyingly
229
shipped in Oneiric, an object with no clear method was used, hence the
230
extra complications, see bug 809048 for details.
232
type_equality_funcs = getattr(test, "_type_equality_funcs", None)
233
if type_equality_funcs is not None:
234
tef_clear = getattr(type_equality_funcs, "clear", None)
235
if tef_clear is None:
236
tef_instance_dict = getattr(type_equality_funcs, "__dict__", None)
237
if tef_instance_dict is not None:
238
tef_clear = tef_instance_dict.clear
239
if tef_clear is not None:
215
243
class ExtendedTestResult(testtools.TextTestResult):
216
244
"""Accepts, reports and accumulates the results of running tests.
332
360
return float(''.join(details['benchtime'].iter_bytes()))
333
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
335
372
def _elapsedTestTimeString(self):
336
373
"""Return a time string for the overall time the current test has taken."""
337
374
return self._formatTime(self._delta_to_float(
338
self._now() - self._start_datetime))
375
self._now() - self._start_datetime, 3))
340
377
def _testTimeString(self, testCase):
341
378
benchmark_time = self._extractBenchmarkTime(testCase)
385
422
getDetails = getattr(test, "getDetails", None)
386
423
if getDetails is not None:
387
424
getDetails().clear()
388
# Clear _type_equality_funcs to try to stop TestCase instances
389
# from wasting memory. 'clear' is not available in all Python
390
# versions (bug 809048)
391
type_equality_funcs = getattr(test, "_type_equality_funcs", None)
392
if type_equality_funcs is not None:
393
tef_clear = getattr(type_equality_funcs, "clear", None)
394
if tef_clear is None:
395
tef_instance_dict = getattr(type_equality_funcs, "__dict__", None)
396
if tef_instance_dict is not None:
397
tef_clear = tef_instance_dict.clear
398
if tef_clear is not None:
425
_clear__type_equality_funcs(test)
400
426
self._traceback_from_test = None
402
428
def startTests(self):
503
529
self.not_applicable_count += 1
504
530
self.report_not_applicable(test, reason)
532
def _count_stored_tests(self):
533
"""Count of tests instances kept alive due to not succeeding"""
534
return self.error_count + self.failure_count + self.known_failure_count
506
536
def _post_mortem(self, tb=None):
507
537
"""Start a PDB post mortem session."""
508
538
if os.environ.get('BZR_TEST_PDB', None):
981
1011
def setUp(self):
982
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)
983
1022
for feature in getattr(self, '_test_needs_features', []):
984
1023
self.requireFeature(feature)
985
1024
self._cleanEnvironment()
1026
if bzrlib.global_state is not None:
1027
self.overrideAttr(bzrlib.global_state, 'cmdline_overrides',
1028
config.CommandLineStore())
986
1030
self._silenceUI()
987
1031
self._startLogFile()
988
1032
self._benchcalls = []
995
1039
# between tests. We should get rid of this altogether: bug 656694. --
997
1041
self.overrideAttr(bzrlib.trace, '_verbosity_level', 0)
998
# Isolate config option expansion until its default value for bzrlib is
999
# settled on or a the FIXME associated with _get_expand_default_value
1000
# is addressed -- vila 20110219
1001
self.overrideAttr(config, '_expand_default_value', None)
1002
1042
self._log_files = set()
1003
1043
# Each key in the ``_counters`` dict holds a value for a different
1004
1044
# counter. When the test ends, addDetail() should be used to output the
1297
1337
# hook into bzr dir opening. This leaves a small window of error for
1298
1338
# transport tests, but they are well known, and we can improve on this
1300
bzrdir.BzrDir.hooks.install_named_hook("pre_open",
1340
controldir.ControlDir.hooks.install_named_hook("pre_open",
1301
1341
self._preopen_isolate_transport, "Check bzr directories are safe.")
1303
1343
def _ndiff_strings(self, a, b):
1717
1754
self.addCleanup(self._finishLogFile)
1719
1756
def _finishLogFile(self):
1720
"""Finished with the log file.
1722
Close the file and delete it.
1757
"""Flush and dereference the in-memory log for this testcase"""
1724
1758
if trace._trace_file:
1725
1759
# flush the log file, to get all content
1726
1760
trace._trace_file.flush()
1727
1761
trace.pop_log_file(self._log_memento)
1762
# The logging module now tracks references for cleanup so discard ours
1763
del self._log_memento
1729
1765
def thisFailsStrictLockCheck(self):
1730
1766
"""It is known that this test would fail with -Dstrict_locks.
1755
1791
:returns: The actual attr value.
1757
value = getattr(obj, attr_name)
1758
1793
# The actual value is captured by the call below
1759
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)
1760
1802
if new is not _unitialized_attr:
1761
1803
setattr(obj, attr_name, new)
1966
2008
self.log('run bzr: %r', args)
1967
2009
# FIXME: don't call into logging here
1968
handler = logging.StreamHandler(stderr)
1969
handler.setLevel(logging.INFO)
2010
handler = trace.EncodedStreamHandler(stderr, errors="replace",
1970
2012
logger = logging.getLogger('')
1971
2013
logger.addHandler(handler)
1972
2014
old_ui_factory = ui.ui_factory
2356
2403
from bzrlib.smart import request
2357
2404
request_handlers = request.request_handlers
2358
2405
orig_method = request_handlers.get(verb)
2406
orig_info = request_handlers.get_info(verb)
2359
2407
request_handlers.remove(verb)
2360
self.addCleanup(request_handlers.register, verb, orig_method)
2408
self.addCleanup(request_handlers.register, verb, orig_method,
2363
2412
class CapturedCall(object):
2416
2465
self.transport_readonly_server = None
2417
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', {})
2419
2496
def get_transport(self, relpath=None):
2420
2497
"""Return a writeable transport.
2570
2647
# http://pad.lv/825027).
2571
2648
self.assertIs(None, os.environ.get('BZR_HOME', None))
2572
2649
os.environ['BZR_HOME'] = root
2573
wt = bzrdir.BzrDir.create_standalone_workingtree(root)
2650
wt = controldir.ControlDir.create_standalone_workingtree(root)
2574
2651
del os.environ['BZR_HOME']
2575
2652
except Exception, e:
2576
self.fail("Fail to initialize the safety net: %r\nExiting\n" % (e,))
2653
self.fail("Fail to initialize the safety net: %r\n" % (e,))
2577
2654
# Hack for speed: remember the raw bytes of the dirstate file so that
2578
2655
# we don't need to re-open the wt to check it hasn't changed.
2579
2656
TestCaseWithMemoryTransport._SAFETY_NET_PRISTINE_DIRSTATE = (
2627
2704
self.test_home_dir = self.test_dir + "/MemoryTransportMissingHomeDir"
2628
2705
self.permit_dir(self.test_dir)
2630
def make_branch(self, relpath, format=None):
2707
def make_branch(self, relpath, format=None, name=None):
2631
2708
"""Create a branch on the transport at relpath."""
2632
2709
repo = self.make_repository(relpath, format=format)
2633
return repo.bzrdir.create_branch(append_revisions_only=False)
2635
def resolve_format(self, format):
2636
"""Resolve an object to a ControlDir format object.
2638
The initial format object can either already be
2639
a ControlDirFormat, None (for the default format),
2640
or a string with the name of the control dir format.
2642
:param format: Object to resolve
2643
:return A ControlDirFormat instance
2647
if isinstance(format, basestring):
2648
format = bzrdir.format_registry.make_bzrdir(format)
2651
def resolve_format(self, format):
2652
"""Resolve an object to a ControlDir format object.
2654
The initial format object can either already be
2655
a ControlDirFormat, None (for the default format),
2656
or a string with the name of the control dir format.
2658
:param format: Object to resolve
2659
:return A ControlDirFormat instance
2663
if isinstance(format, basestring):
2664
format = bzrdir.format_registry.make_bzrdir(format)
2710
return repo.bzrdir.create_branch(append_revisions_only=False,
2713
def get_default_format(self):
2716
def resolve_format(self, format):
2717
"""Resolve an object to a ControlDir format object.
2719
The initial format object can either already be
2720
a ControlDirFormat, None (for the default format),
2721
or a string with the name of the control dir format.
2723
:param format: Object to resolve
2724
:return A ControlDirFormat instance
2727
format = self.get_default_format()
2728
if isinstance(format, basestring):
2729
format = controldir.format_registry.make_bzrdir(format)
2667
2732
def make_bzrdir(self, relpath, format=None):
2714
2779
self.overrideEnv('HOME', test_home_dir)
2715
2780
self.overrideEnv('BZR_HOME', test_home_dir)
2718
super(TestCaseWithMemoryTransport, self).setUp()
2719
# Ensure that ConnectedTransport doesn't leak sockets
2720
def get_transport_from_url_with_cleanup(*args, **kwargs):
2721
t = orig_get_transport_from_url(*args, **kwargs)
2722
if isinstance(t, _mod_transport.ConnectedTransport):
2723
self.addCleanup(t.disconnect)
2726
orig_get_transport_from_url = self.overrideAttr(
2727
_mod_transport, 'get_transport_from_url',
2728
get_transport_from_url_with_cleanup)
2729
self._make_test_root()
2730
self.addCleanup(os.chdir, os.getcwdu())
2731
self.makeAndChdirToTestDir()
2732
self.overrideEnvironmentForTesting()
2733
self.__readonly_server = None
2734
self.__server = None
2735
self.reduceLockdirTimeout()
2737
2782
def setup_smart_server_with_call_log(self):
2738
2783
"""Sets up a smart server as the transport server with a call log."""
2739
2784
self.transport_server = test_server.SmartTCPServer_for_testing
2785
self.hpss_connections = []
2740
2786
self.hpss_calls = []
2741
2787
import traceback
2742
2788
# Skip the current stack down to the caller of
2745
2791
def capture_hpss_call(params):
2746
2792
self.hpss_calls.append(
2747
2793
CapturedCall(params, prefix_length))
2794
def capture_connect(transport):
2795
self.hpss_connections.append(transport)
2748
2796
client._SmartClient.hooks.install_named_hook(
2749
2797
'call', capture_hpss_call, None)
2798
_mod_transport.Transport.hooks.install_named_hook(
2799
'post_connect', capture_connect, None)
2751
2801
def reset_smart_call_log(self):
2752
2802
self.hpss_calls = []
2803
self.hpss_connections = []
2755
2806
class TestCaseInTempDir(TestCaseWithMemoryTransport):
2825
2876
# stacking policy to honour; create a bzr dir with an unshared
2826
2877
# repository (but not a branch - our code would be trying to escape
2827
2878
# then!) to stop them, and permit it to be read.
2828
# control = bzrdir.BzrDir.create(self.test_base_dir)
2879
# control = controldir.ControlDir.create(self.test_base_dir)
2829
2880
# control.create_repository()
2830
2881
self.test_home_dir = self.test_base_dir + '/home'
2831
2882
os.mkdir(self.test_home_dir)
2957
3012
# this obviously requires a format that supports branch references
2958
3013
# so check for that by checking bzrdir.BzrDirFormat.get_default_format()
3015
format = self.resolve_format(format=format)
3016
if not format.supports_workingtrees:
3017
b = self.make_branch(relpath+'.branch', format=format)
3018
return b.create_checkout(relpath, lightweight=True)
2960
3019
b = self.make_branch(relpath, format=format)
2962
3021
return b.bzrdir.create_workingtree()
2967
3026
if self.vfs_transport_factory is test_server.LocalURLServer:
2968
3027
# the branch is colocated on disk, we cannot create a checkout.
2969
3028
# hopefully callers will expect this.
2970
local_controldir= bzrdir.BzrDir.open(self.get_vfs_only_url(relpath))
3029
local_controldir = controldir.ControlDir.open(
3030
self.get_vfs_only_url(relpath))
2971
3031
wt = local_controldir.create_workingtree()
2972
3032
if wt.branch._format != b._format:
3003
3063
self.assertFalse(differences.has_changed(),
3004
3064
"Trees %r and %r are different: %r" % (left, right, differences))
3007
super(TestCaseWithTransport, self).setUp()
3008
self.__vfs_server = None
3010
3066
def disable_missing_extensions_warning(self):
3011
3067
"""Some tests expect a precise stderr content.
3013
3069
There is no point in forcing them to duplicate the extension related
3016
config.GlobalConfig().set_user_option('ignore_missing_extensions', True)
3072
config.GlobalStack().set('ignore_missing_extensions', True)
3019
3075
class ChrootedTestCase(TestCaseWithTransport):
3261
3317
result_decorators=result_decorators,
3263
3319
runner.stop_on_failure=stop_on_failure
3320
if isinstance(suite, unittest.TestSuite):
3321
# Empty out _tests list of passed suite and populate new TestSuite
3322
suite._tests[:], suite = [], TestSuite(suite)
3264
3323
# built in decorator factories:
3266
3325
random_order(random_seed, runner),
3365
3424
class TestDecorator(TestUtil.TestSuite):
3366
3425
"""A decorator for TestCase/TestSuite objects.
3368
Usually, subclasses should override __iter__(used when flattening test
3369
suites), which we do to filter, reorder, parallelise and so on, run() and
3427
Contains rather than flattening suite passed on construction
3373
def __init__(self, suite):
3374
TestUtil.TestSuite.__init__(self)
3377
def countTestCases(self):
3380
cases += test.countTestCases()
3387
def run(self, result):
3388
# Use iteration on self, not self._tests, to allow subclasses to hook
3391
if result.shouldStop:
3430
def __init__(self, suite=None):
3431
super(TestDecorator, self).__init__()
3432
if suite is not None:
3435
# Don't need subclass run method with suite emptying
3436
run = unittest.TestSuite.run
3397
3439
class CountingDecorator(TestDecorator):
3408
3450
"""A decorator which excludes test matching an exclude pattern."""
3410
3452
def __init__(self, suite, exclude_pattern):
3411
TestDecorator.__init__(self, suite)
3412
self.exclude_pattern = exclude_pattern
3413
self.excluded = False
3417
return iter(self._tests)
3418
self.excluded = True
3419
suite = exclude_tests_by_re(self, self.exclude_pattern)
3421
self.addTests(suite)
3422
return iter(self._tests)
3453
super(ExcludeDecorator, self).__init__(
3454
exclude_tests_by_re(suite, exclude_pattern))
3425
3457
class FilterTestsDecorator(TestDecorator):
3426
3458
"""A decorator which filters tests to those matching a pattern."""
3428
3460
def __init__(self, suite, pattern):
3429
TestDecorator.__init__(self, suite)
3430
self.pattern = pattern
3431
self.filtered = False
3435
return iter(self._tests)
3436
self.filtered = True
3437
suite = filter_suite_by_re(self, self.pattern)
3439
self.addTests(suite)
3440
return iter(self._tests)
3461
super(FilterTestsDecorator, self).__init__(
3462
filter_suite_by_re(suite, pattern))
3443
3465
class RandomDecorator(TestDecorator):
3444
3466
"""A decorator which randomises the order of its tests."""
3446
3468
def __init__(self, suite, random_seed, stream):
3447
TestDecorator.__init__(self, suite)
3448
self.random_seed = random_seed
3449
self.randomised = False
3450
self.stream = stream
3454
return iter(self._tests)
3455
self.randomised = True
3456
self.stream.write("Randomizing test order using seed %s\n\n" %
3457
(self.actual_seed()))
3469
random_seed = self.actual_seed(random_seed)
3470
stream.write("Randomizing test order using seed %s\n\n" %
3458
3472
# Initialise the random number generator.
3459
random.seed(self.actual_seed())
3460
suite = randomize_suite(self)
3462
self.addTests(suite)
3463
return iter(self._tests)
3473
random.seed(random_seed)
3474
super(RandomDecorator, self).__init__(randomize_suite(suite))
3465
def actual_seed(self):
3466
if self.random_seed == "now":
3477
def actual_seed(seed):
3467
3479
# We convert the seed to a long to make it reuseable across
3468
3480
# invocations (because the user can reenter it).
3469
self.random_seed = long(time.time())
3481
return long(time.time())
3471
3483
# Convert the seed to a long if we can
3473
self.random_seed = long(self.random_seed)
3486
except (TypeError, ValueError):
3476
return self.random_seed
3479
3491
class TestFirstDecorator(TestDecorator):
3480
3492
"""A decorator which moves named tests to the front."""
3482
3494
def __init__(self, suite, pattern):
3483
TestDecorator.__init__(self, suite)
3484
self.pattern = pattern
3485
self.filtered = False
3489
return iter(self._tests)
3490
self.filtered = True
3491
suites = split_suite_by_re(self, self.pattern)
3493
self.addTests(suites)
3494
return iter(self._tests)
3495
super(TestFirstDecorator, self).__init__()
3496
self.addTests(split_suite_by_re(suite, pattern))
3497
3499
def partition_tests(suite, count):
3542
3544
ProtocolTestCase.run(self, result)
3544
os.waitpid(self.pid, 0)
3546
pid, status = os.waitpid(self.pid, 0)
3547
# GZ 2011-10-18: If status is nonzero, should report to the result
3548
# that something went wrong.
3546
3550
test_blocks = partition_tests(suite, concurrency)
3551
# Clear the tests from the original suite so it doesn't keep them alive
3552
suite._tests[:] = []
3547
3553
for process_tests in test_blocks:
3548
process_suite = TestUtil.TestSuite()
3549
process_suite.addTests(process_tests)
3554
process_suite = TestUtil.TestSuite(process_tests)
3555
# Also clear each split list so new suite has only reference
3556
process_tests[:] = []
3550
3557
c2pread, c2pwrite = os.pipe()
3551
3558
pid = os.fork()
3553
workaround_zealous_crypto_random()
3561
stream = os.fdopen(c2pwrite, 'wb', 1)
3562
workaround_zealous_crypto_random()
3555
3563
os.close(c2pread)
3556
3564
# Leave stderr and stdout open so we can see test noise
3557
3565
# Close stdin so that the child goes away if it decides to
3558
3566
# read from stdin (otherwise its a roulette to see what
3559
3567
# child actually gets keystrokes for pdb etc).
3560
3568
sys.stdin.close()
3562
stream = os.fdopen(c2pwrite, 'wb', 1)
3563
3569
subunit_result = AutoTimingTestResultDecorator(
3564
TestProtocolClient(stream))
3570
SubUnitBzrProtocolClient(stream))
3565
3571
process_suite.run(subunit_result)
3573
# Try and report traceback on stream, but exit with error even
3574
# if stream couldn't be created or something else goes wrong.
3575
# The traceback is formatted to a string and written in one go
3576
# to avoid interleaving lines from multiple failing children.
3578
stream.write(traceback.format_exc())
3569
3583
os.close(c2pwrite)
3570
3584
stream = os.fdopen(c2pread, 'rb', 1)
3676
3690
# with proper exclusion rules.
3677
3691
# -Ethreads Will display thread ident at creation/join time to
3678
3692
# help track thread leaks
3693
# -Euncollected_cases Display the identity of any test cases that weren't
3694
# deallocated after being completed.
3680
3695
# -Econfig_stats Will collect statistics using addDetail
3681
3696
selftest_debug_flags = set()
3788
3803
:return: (absents, duplicates) absents is a list containing the test found
3789
3804
in id_list but not in test_suite, duplicates is a list containing the
3790
test found multiple times in test_suite.
3805
tests found multiple times in test_suite.
3792
3807
When using a prefined test id list, it may occurs that some tests do not
3793
3808
exist anymore or that some tests use the same id. This function warns the
4011
4025
'bzrlib.tests.test_http',
4012
4026
'bzrlib.tests.test_http_response',
4013
4027
'bzrlib.tests.test_https_ca_bundle',
4028
'bzrlib.tests.test_https_urllib',
4014
4029
'bzrlib.tests.test_i18n',
4015
4030
'bzrlib.tests.test_identitymap',
4016
4031
'bzrlib.tests.test_ignores',
4065
4080
'bzrlib.tests.test_revisiontree',
4066
4081
'bzrlib.tests.test_rio',
4067
4082
'bzrlib.tests.test_rules',
4083
'bzrlib.tests.test_url_policy_open',
4068
4084
'bzrlib.tests.test_sampler',
4069
4085
'bzrlib.tests.test_scenarios',
4070
4086
'bzrlib.tests.test_script',
4114
4130
'bzrlib.tests.test_version',
4115
4131
'bzrlib.tests.test_version_info',
4116
4132
'bzrlib.tests.test_versionedfile',
4133
'bzrlib.tests.test_vf_search',
4117
4134
'bzrlib.tests.test_weave',
4118
4135
'bzrlib.tests.test_whitebox',
4119
4136
'bzrlib.tests.test_win32utils',
4480
4497
from subunit.test_results import AutoTimingTestResultDecorator
4481
4498
class SubUnitBzrProtocolClient(TestProtocolClient):
4500
def stopTest(self, test):
4501
super(SubUnitBzrProtocolClient, self).stopTest(test)
4502
_clear__type_equality_funcs(test)
4483
4504
def addSuccess(self, test, details=None):
4484
4505
# The subunit client always includes the details in the subunit
4485
4506
# stream, but we don't want to include it in ours.
4501
@deprecated_function(deprecated_in((2, 5, 0)))
4502
def ModuleAvailableFeature(name):
4503
from bzrlib.tests import features
4504
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')