/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/tests/__init__.py

  • Committer: Martin Pool
  • Date: 2009-03-13 07:54:48 UTC
  • mfrom: (4144 +trunk)
  • mto: This revision was merged to the branch mainline in revision 4189.
  • Revision ID: mbp@sourcefrog.net-20090313075448-jlz1t7baz7gzipqn
merge trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006, 2007, 2008 Canonical Ltd
 
1
# Copyright (C) 2005, 2006, 2007, 2008, 2009 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
53
53
    bzrdir,
54
54
    debug,
55
55
    errors,
 
56
    hooks,
56
57
    memorytree,
57
58
    osutils,
58
59
    progress,
76
77
from bzrlib.merge import merge_inner
77
78
import bzrlib.merge3
78
79
import bzrlib.plugin
 
80
from bzrlib.smart import client, server
79
81
import bzrlib.store
80
82
from bzrlib import symbol_versioning
81
83
from bzrlib.symbol_versioning import (
126
128
    """
127
129
 
128
130
    stop_early = False
129
 
    
 
131
 
130
132
    def __init__(self, stream, descriptions, verbosity,
131
133
                 bench_history=None,
132
134
                 num_tests=None,
162
164
        self.unsupported = {}
163
165
        self.count = 0
164
166
        self._overall_start_time = time.time()
165
 
    
 
167
 
166
168
    def _extractBenchmarkTime(self, testCase):
167
169
        """Add a benchmark time for the current test case."""
168
170
        return getattr(testCase, "_benchtime", None)
169
 
    
 
171
 
170
172
    def _elapsedTestTimeString(self):
171
173
        """Return a time string for the overall time the current test has taken."""
172
174
        return self._formatTime(time.time() - self._start_time)
215
217
        fails with an unexpected error.
216
218
        """
217
219
        self._testConcluded(test)
218
 
        if isinstance(err[1], TestSkipped):
219
 
            return self._addSkipped(test, err)
 
220
        if isinstance(err[1], TestNotApplicable):
 
221
            return self._addNotApplicable(test, err)
220
222
        elif isinstance(err[1], UnavailableFeature):
221
223
            return self.addNotSupported(test, err[1].args[0])
222
224
        else:
276
278
        """The test will not be run because of a missing feature.
277
279
        """
278
280
        # this can be called in two different ways: it may be that the
279
 
        # test started running, and then raised (through addError) 
 
281
        # test started running, and then raised (through addError)
280
282
        # UnavailableFeature.  Alternatively this method can be called
281
283
        # while probing for features before running the tests; in that
282
284
        # case we will see startTest and stopTest, but the test will never
285
287
        self.unsupported[str(feature)] += 1
286
288
        self.report_unsupported(test, feature)
287
289
 
288
 
    def _addSkipped(self, test, skip_excinfo):
 
290
    def addSkip(self, test, reason):
 
291
        """A test has not run for 'reason'."""
 
292
        self.skip_count += 1
 
293
        self.report_skip(test, reason)
 
294
 
 
295
    def _addNotApplicable(self, test, skip_excinfo):
289
296
        if isinstance(skip_excinfo[1], TestNotApplicable):
290
297
            self.not_applicable_count += 1
291
298
            self.report_not_applicable(test, skip_excinfo)
292
 
        else:
293
 
            self.skip_count += 1
294
 
            self.report_skip(test, skip_excinfo)
295
299
        try:
296
300
            test.tearDown()
297
301
        except KeyboardInterrupt:
298
302
            raise
299
303
        except:
300
 
            self.addError(test, test._exc_info())
 
304
            self.addError(test, test.exc_info())
301
305
        else:
302
306
            # seems best to treat this as success from point-of-view of unittest
303
307
            # -- it actually does nothing so it barely matters :)
360
364
        self.pb.show_bar = False
361
365
 
362
366
    def report_starting(self):
363
 
        self.pb.update('[test 0/%d] starting...' % (self.num_tests))
 
367
        self.pb.update('[test 0/%d] Starting' % (self.num_tests))
364
368
 
365
369
    def _progress_prefix_text(self):
366
370
        # the longer this text, the less space we have to show the test
393
397
        self.count += 1
394
398
        self.pb.update(
395
399
                self._progress_prefix_text()
396
 
                + ' ' 
 
400
                + ' '
397
401
                + self._shortened_test_description(test))
398
402
 
399
403
    def _test_description(self, test):
400
404
        return self._shortened_test_description(test)
401
405
 
402
406
    def report_error(self, test, err):
403
 
        self.pb.note('ERROR: %s\n    %s\n', 
 
407
        self.pb.note('ERROR: %s\n    %s\n',
404
408
            self._test_description(test),
405
409
            err[1],
406
410
            )
407
411
 
408
412
    def report_failure(self, test, err):
409
 
        self.pb.note('FAIL: %s\n    %s\n', 
 
413
        self.pb.note('FAIL: %s\n    %s\n',
410
414
            self._test_description(test),
411
415
            err[1],
412
416
            )
415
419
        self.pb.note('XFAIL: %s\n%s\n',
416
420
            self._test_description(test), err[1])
417
421
 
418
 
    def report_skip(self, test, skip_excinfo):
 
422
    def report_skip(self, test, reason):
419
423
        pass
420
424
 
421
425
    def report_not_applicable(self, test, skip_excinfo):
423
427
 
424
428
    def report_unsupported(self, test, feature):
425
429
        """test cannot be run because feature is missing."""
426
 
                  
 
430
 
427
431
    def report_cleaning_up(self):
428
 
        self.pb.update('cleaning up...')
 
432
        self.pb.update('Cleaning up')
429
433
 
430
434
    def finished(self):
431
435
        if not self._supplied_pb:
484
488
        # used to show the output in PQM.
485
489
        self.stream.flush()
486
490
 
487
 
    def report_skip(self, test, skip_excinfo):
 
491
    def report_skip(self, test, reason):
488
492
        self.stream.writeln(' SKIP %s\n%s'
489
 
                % (self._testTimeString(test),
490
 
                   self._error_summary(skip_excinfo)))
 
493
                % (self._testTimeString(test), reason))
491
494
 
492
495
    def report_not_applicable(self, test, skip_excinfo):
493
496
        self.stream.writeln('  N/A %s\n%s'
539
542
                self.stream.writeln("%s" % (t.id()))
540
543
                run += 1
541
544
            actionTaken = "Listed"
542
 
        else: 
 
545
        else:
543
546
            test.run(result)
544
547
            run = result.testsRun
545
548
            actionTaken = "Ran"
583
586
 
584
587
def iter_suite_tests(suite):
585
588
    """Return all tests in a suite, recursing through nested suites"""
586
 
    for item in suite._tests:
587
 
        if isinstance(item, unittest.TestCase):
588
 
            yield item
589
 
        elif isinstance(item, unittest.TestSuite):
 
589
    if isinstance(suite, unittest.TestCase):
 
590
        yield suite
 
591
    elif isinstance(suite, unittest.TestSuite):
 
592
        for item in suite._tests:
590
593
            for r in iter_suite_tests(item):
591
594
                yield r
592
 
        else:
593
 
            raise Exception('unknown object %r inside test suite %r'
594
 
                            % (item, suite))
 
595
    else:
 
596
        raise Exception('unknown type %r for object %r'
 
597
                        % (type(suite), suite))
595
598
 
596
599
 
597
600
class TestSkipped(Exception):
601
604
class TestNotApplicable(TestSkipped):
602
605
    """A test is not applicable to the situation where it was run.
603
606
 
604
 
    This is only normally raised by parameterized tests, if they find that 
605
 
    the instance they're constructed upon does not support one aspect 
 
607
    This is only normally raised by parameterized tests, if they find that
 
608
    the instance they're constructed upon does not support one aspect
606
609
    of its interface.
607
610
    """
608
611
 
630
633
 
631
634
class StringIOWrapper(object):
632
635
    """A wrapper around cStringIO which just adds an encoding attribute.
633
 
    
 
636
 
634
637
    Internally we can check sys.stdout to see what the output encoding
635
638
    should be. However, cStringIO has no encoding attribute that we can
636
639
    set. So we wrap it instead.
727
730
 
728
731
class TestCase(unittest.TestCase):
729
732
    """Base class for bzr unit tests.
730
 
    
731
 
    Tests that need access to disk resources should subclass 
 
733
 
 
734
    Tests that need access to disk resources should subclass
732
735
    TestCaseInTempDir not TestCase.
733
736
 
734
737
    Error and debug log messages are redirected from their usual
736
739
    retrieved by _get_log().  We use a real OS file, not an in-memory object,
737
740
    so that it can also capture file IO.  When the test completes this file
738
741
    is read into memory and removed from disk.
739
 
       
 
742
 
740
743
    There are also convenience functions to invoke bzr's command-line
741
744
    routine, and to build and check bzr trees.
742
 
   
 
745
 
743
746
    In addition to the usual method of overriding tearDown(), this class also
744
747
    allows subclasses to register functions into the _cleanups list, which is
745
748
    run in order as the object is torn down.  It's less likely this will be
774
777
        TestCase._active_threads = threading.activeCount()
775
778
        self.addCleanup(self._check_leaked_threads)
776
779
 
 
780
    def debug(self):
 
781
        # debug a frame up.
 
782
        import pdb
 
783
        pdb.Pdb().set_trace(sys._getframe().f_back)
 
784
 
 
785
    def exc_info(self):
 
786
        absent_attr = object()
 
787
        exc_info = getattr(self, '_exc_info', absent_attr)
 
788
        if exc_info is absent_attr:
 
789
            exc_info = getattr(self, '_TestCase__exc_info')
 
790
        return exc_info()
 
791
 
777
792
    def _check_leaked_threads(self):
778
793
        active = threading.activeCount()
779
794
        leaked_threads = active - TestCase._active_threads
800
815
 
801
816
    def _clear_hooks(self):
802
817
        # prevent hooks affecting tests
803
 
        import bzrlib.branch
804
 
        import bzrlib.smart.client
805
 
        import bzrlib.smart.server
806
 
        self._preserved_hooks = {
807
 
            bzrlib.branch.Branch: bzrlib.branch.Branch.hooks,
808
 
            bzrlib.mutabletree.MutableTree: bzrlib.mutabletree.MutableTree.hooks,
809
 
            bzrlib.smart.client._SmartClient: bzrlib.smart.client._SmartClient.hooks,
810
 
            bzrlib.smart.server.SmartTCPServer: bzrlib.smart.server.SmartTCPServer.hooks,
811
 
            }
 
818
        self._preserved_hooks = {}
 
819
        for key, factory in hooks.known_hooks.items():
 
820
            parent, name = hooks.known_hooks_key_to_parent_and_attribute(key)
 
821
            current_hooks = hooks.known_hooks_key_to_object(key)
 
822
            self._preserved_hooks[parent] = (name, current_hooks)
812
823
        self.addCleanup(self._restoreHooks)
813
 
        # reset all hooks to an empty instance of the appropriate type
814
 
        bzrlib.branch.Branch.hooks = bzrlib.branch.BranchHooks()
815
 
        bzrlib.smart.client._SmartClient.hooks = bzrlib.smart.client.SmartClientHooks()
816
 
        bzrlib.smart.server.SmartTCPServer.hooks = bzrlib.smart.server.SmartServerHooks()
 
824
        for key, factory in hooks.known_hooks.items():
 
825
            parent, name = hooks.known_hooks_key_to_parent_and_attribute(key)
 
826
            setattr(parent, name, factory())
817
827
 
818
828
    def _silenceUI(self):
819
829
        """Turn off UI for duration of test"""
826
836
 
827
837
    def _ndiff_strings(self, a, b):
828
838
        """Return ndiff between two strings containing lines.
829
 
        
 
839
 
830
840
        A trailing newline is added if missing to make the strings
831
841
        print properly."""
832
842
        if b and b[-1] != '\n':
857
867
 
858
868
    def assertEqualDiff(self, a, b, message=None):
859
869
        """Assert two texts are equal, if not raise an exception.
860
 
        
861
 
        This is intended for use with multi-line strings where it can 
 
870
 
 
871
        This is intended for use with multi-line strings where it can
862
872
        be hard to find the differences by eye.
863
873
        """
864
874
        # TODO: perhaps override assertEquals to call this for strings?
872
882
            message = 'second string is missing a final newline.\n'
873
883
        raise AssertionError(message +
874
884
                             self._ndiff_strings(a, b))
875
 
        
 
885
 
876
886
    def assertEqualMode(self, mode, mode_test):
877
887
        self.assertEqual(mode, mode_test,
878
888
                         'mode mismatch %o != %o' % (mode, mode_test))
936
946
 
937
947
    def assertListRaises(self, excClass, func, *args, **kwargs):
938
948
        """Fail unless excClass is raised when the iterator from func is used.
939
 
        
 
949
 
940
950
        Many functions can return generators this makes sure
941
951
        to wrap them in a list() call to make sure the whole generator
942
952
        is run, and that the proper exception is raised.
990
1000
 
991
1001
    def assertTransportMode(self, transport, path, mode):
992
1002
        """Fail if a path does not have mode mode.
993
 
        
 
1003
 
994
1004
        If modes are not supported on this transport, the assertion is ignored.
995
1005
        """
996
1006
        if not transport._can_roundtrip_unix_modebits():
1167
1177
    def callDeprecated(self, expected, callable, *args, **kwargs):
1168
1178
        """Assert that a callable is deprecated in a particular way.
1169
1179
 
1170
 
        This is a very precise test for unusual requirements. The 
 
1180
        This is a very precise test for unusual requirements. The
1171
1181
        applyDeprecated helper function is probably more suited for most tests
1172
1182
        as it allows you to simply specify the deprecation format being used
1173
1183
        and will ensure that that is issued for the function being called.
1218
1228
    def addCleanup(self, callable, *args, **kwargs):
1219
1229
        """Arrange to run a callable when this case is torn down.
1220
1230
 
1221
 
        Callables are run in the reverse of the order they are registered, 
 
1231
        Callables are run in the reverse of the order they are registered,
1222
1232
        ie last-in first-out.
1223
1233
        """
1224
1234
        self._cleanups.append((callable, args, kwargs))
1272
1282
            osutils.set_or_unset_env(name, value)
1273
1283
 
1274
1284
    def _restoreHooks(self):
1275
 
        for klass, hooks in self._preserved_hooks.items():
1276
 
            setattr(klass, 'hooks', hooks)
 
1285
        for klass, (name, hooks) in self._preserved_hooks.items():
 
1286
            setattr(klass, name, hooks)
1277
1287
 
1278
1288
    def knownFailure(self, reason):
1279
1289
        """This test has failed for some known reason."""
1280
1290
        raise KnownFailure(reason)
1281
1291
 
 
1292
    def _do_skip(self, result, reason):
 
1293
        addSkip = getattr(result, 'addSkip', None)
 
1294
        if not callable(addSkip):
 
1295
            result.addError(self, self.exc_info())
 
1296
        else:
 
1297
            addSkip(self, reason)
 
1298
 
1282
1299
    def run(self, result=None):
1283
1300
        if result is None: result = self.defaultTestResult()
1284
1301
        for feature in getattr(self, '_test_needs_features', []):
1291
1308
                result.stopTest(self)
1292
1309
                return
1293
1310
        try:
1294
 
            return unittest.TestCase.run(self, result)
 
1311
            try:
 
1312
                result.startTest(self)
 
1313
                absent_attr = object()
 
1314
                # Python 2.5
 
1315
                method_name = getattr(self, '_testMethodName', absent_attr)
 
1316
                if method_name is absent_attr:
 
1317
                    # Python 2.4
 
1318
                    method_name = getattr(self, '_TestCase__testMethodName')
 
1319
                testMethod = getattr(self, method_name)
 
1320
                try:
 
1321
                    try:
 
1322
                        self.setUp()
 
1323
                    except KeyboardInterrupt:
 
1324
                        raise
 
1325
                    except TestSkipped, e:
 
1326
                        self._do_skip(result, e.args[0])
 
1327
                        self.tearDown()
 
1328
                        return
 
1329
                    except:
 
1330
                        result.addError(self, self.exc_info())
 
1331
                        return
 
1332
 
 
1333
                    ok = False
 
1334
                    try:
 
1335
                        testMethod()
 
1336
                        ok = True
 
1337
                    except self.failureException:
 
1338
                        result.addFailure(self, self.exc_info())
 
1339
                    except TestSkipped, e:
 
1340
                        if not e.args:
 
1341
                            reason = "No reason given."
 
1342
                        else:
 
1343
                            reason = e.args[0]
 
1344
                        self._do_skip(result, reason)
 
1345
                    except KeyboardInterrupt:
 
1346
                        raise
 
1347
                    except:
 
1348
                        result.addError(self, self.exc_info())
 
1349
 
 
1350
                    try:
 
1351
                        self.tearDown()
 
1352
                    except KeyboardInterrupt:
 
1353
                        raise
 
1354
                    except:
 
1355
                        result.addError(self, self.exc_info())
 
1356
                        ok = False
 
1357
                    if ok: result.addSuccess(self)
 
1358
                finally:
 
1359
                    result.stopTest(self)
 
1360
                return
 
1361
            except TestNotApplicable:
 
1362
                # Not moved from the result [yet].
 
1363
                raise
 
1364
            except KeyboardInterrupt:
 
1365
                raise
1295
1366
        finally:
1296
1367
            saved_attrs = {}
1297
1368
            absent_attr = object()
1303
1374
 
1304
1375
    def tearDown(self):
1305
1376
        self._runCleanups()
 
1377
        self._log_contents = ''
1306
1378
        unittest.TestCase.tearDown(self)
1307
1379
 
1308
1380
    def time(self, callable, *args, **kwargs):
1309
1381
        """Run callable and accrue the time it takes to the benchmark time.
1310
 
        
 
1382
 
1311
1383
        If lsprofiling is enabled (i.e. by --lsprof-time to bzr selftest) then
1312
1384
        this will cause lsprofile statistics to be gathered and stored in
1313
1385
        self._benchcalls.
1328
1400
            self._benchtime += time.time() - start
1329
1401
 
1330
1402
    def _runCleanups(self):
1331
 
        """Run registered cleanup functions. 
 
1403
        """Run registered cleanup functions.
1332
1404
 
1333
1405
        This should only be called from TestCase.tearDown.
1334
1406
        """
1335
 
        # TODO: Perhaps this should keep running cleanups even if 
 
1407
        # TODO: Perhaps this should keep running cleanups even if
1336
1408
        # one of them fails?
1337
1409
 
1338
1410
        # Actually pop the cleanups from the list so tearDown running
1454
1526
        passed in three ways:
1455
1527
 
1456
1528
        1- A list of strings, eg ["commit", "a"].  This is recommended
1457
 
        when the command contains whitespace or metacharacters, or 
 
1529
        when the command contains whitespace or metacharacters, or
1458
1530
        is built up at run time.
1459
1531
 
1460
 
        2- A single string, eg "add a".  This is the most convenient 
 
1532
        2- A single string, eg "add a".  This is the most convenient
1461
1533
        for hardcoded commands.
1462
1534
 
1463
1535
        This runs bzr through the interface that catches and reports
1522
1594
    def run_bzr_subprocess(self, *args, **kwargs):
1523
1595
        """Run bzr in a subprocess for testing.
1524
1596
 
1525
 
        This starts a new Python interpreter and runs bzr in there. 
 
1597
        This starts a new Python interpreter and runs bzr in there.
1526
1598
        This should only be used for tests that have a justifiable need for
1527
1599
        this isolation: e.g. they are testing startup time, or signal
1528
 
        handling, or early startup code, etc.  Subprocess code can't be 
 
1600
        handling, or early startup code, etc.  Subprocess code can't be
1529
1601
        profiled or debugged so easily.
1530
1602
 
1531
1603
        :keyword retcode: The status code that is expected.  Defaults to 0.  If
1747
1819
        return sio
1748
1820
 
1749
1821
 
 
1822
class CapturedCall(object):
 
1823
    """A helper for capturing smart server calls for easy debug analysis."""
 
1824
 
 
1825
    def __init__(self, params, prefix_length):
 
1826
        """Capture the call with params and skip prefix_length stack frames."""
 
1827
        self.call = params
 
1828
        import traceback
 
1829
        # The last 5 frames are the __init__, the hook frame, and 3 smart
 
1830
        # client frames. Beyond this we could get more clever, but this is good
 
1831
        # enough for now.
 
1832
        stack = traceback.extract_stack()[prefix_length:-5]
 
1833
        self.stack = ''.join(traceback.format_list(stack))
 
1834
 
 
1835
    def __str__(self):
 
1836
        return self.call.method
 
1837
 
 
1838
    def __repr__(self):
 
1839
        return self.call.method
 
1840
 
 
1841
    def stack(self):
 
1842
        return self.stack
 
1843
 
 
1844
 
1750
1845
class TestCaseWithMemoryTransport(TestCase):
1751
1846
    """Common test class for tests that do not need disk resources.
1752
1847
 
1771
1866
 
1772
1867
    def __init__(self, methodName='runTest'):
1773
1868
        # allow test parameterization after test construction and before test
1774
 
        # execution. Variables that the parameterizer sets need to be 
 
1869
        # execution. Variables that the parameterizer sets need to be
1775
1870
        # ones that are not set by setUp, or setUp will trash them.
1776
1871
        super(TestCaseWithMemoryTransport, self).__init__(methodName)
1777
1872
        self.vfs_transport_factory = default_transport
1784
1879
 
1785
1880
        This transport is for the test scratch space relative to
1786
1881
        "self._test_root"
1787
 
        
 
1882
 
1788
1883
        :param relpath: a path relative to the base url.
1789
1884
        """
1790
1885
        t = get_transport(self.get_url(relpath))
1793
1888
 
1794
1889
    def get_readonly_transport(self, relpath=None):
1795
1890
        """Return a readonly transport for the test scratch space
1796
 
        
 
1891
 
1797
1892
        This can be used to test that operations which should only need
1798
1893
        readonly access in fact do not try to write.
1799
1894
 
1830
1925
    def get_readonly_url(self, relpath=None):
1831
1926
        """Get a URL for the readonly transport.
1832
1927
 
1833
 
        This will either be backed by '.' or a decorator to the transport 
 
1928
        This will either be backed by '.' or a decorator to the transport
1834
1929
        used by self.get_url()
1835
1930
        relpath provides for clients to get a path relative to the base url.
1836
1931
        These should only be downwards relative, not upwards.
1969
2064
 
1970
2065
    def makeAndChdirToTestDir(self):
1971
2066
        """Create a temporary directories for this one test.
1972
 
        
 
2067
 
1973
2068
        This must set self.test_home_dir and self.test_dir and chdir to
1974
2069
        self.test_dir.
1975
 
        
 
2070
 
1976
2071
        For TestCaseWithMemoryTransport we chdir to the TEST_ROOT for this test.
1977
2072
        """
1978
2073
        os.chdir(TestCaseWithMemoryTransport.TEST_ROOT)
1979
2074
        self.test_dir = TestCaseWithMemoryTransport.TEST_ROOT
1980
2075
        self.test_home_dir = self.test_dir + "/MemoryTransportMissingHomeDir"
1981
 
        
 
2076
 
1982
2077
    def make_branch(self, relpath, format=None):
1983
2078
        """Create a branch on the transport at relpath."""
1984
2079
        repo = self.make_repository(relpath, format=format)
2002
2097
 
2003
2098
    def make_repository(self, relpath, shared=False, format=None):
2004
2099
        """Create a repository on our default transport at relpath.
2005
 
        
 
2100
 
2006
2101
        Note that relpath must be a relative path, not a full url.
2007
2102
        """
2008
2103
        # FIXME: If you create a remoterepository this returns the underlying
2009
 
        # real format, which is incorrect.  Actually we should make sure that 
 
2104
        # real format, which is incorrect.  Actually we should make sure that
2010
2105
        # RemoteBzrDir returns a RemoteRepository.
2011
2106
        # maybe  mbp 20070410
2012
2107
        made_control = self.make_bzrdir(relpath, format=format)
2018
2113
        return memorytree.MemoryTree.create_on_branch(b)
2019
2114
 
2020
2115
    def make_branch_builder(self, relpath, format=None):
2021
 
        url = self.get_url(relpath)
2022
 
        tran = get_transport(url)
2023
 
        return branchbuilder.BranchBuilder(get_transport(url), format=format)
 
2116
        return branchbuilder.BranchBuilder(self.get_transport(relpath),
 
2117
            format=format)
2024
2118
 
2025
2119
    def overrideEnvironmentForTesting(self):
2026
2120
        os.environ['HOME'] = self.test_home_dir
2027
2121
        os.environ['BZR_HOME'] = self.test_home_dir
2028
 
        
 
2122
 
2029
2123
    def setUp(self):
2030
2124
        super(TestCaseWithMemoryTransport, self).setUp()
2031
2125
        self._make_test_root()
2039
2133
        self.__server = None
2040
2134
        self.reduceLockdirTimeout()
2041
2135
 
2042
 
     
 
2136
    def setup_smart_server_with_call_log(self):
 
2137
        """Sets up a smart server as the transport server with a call log."""
 
2138
        self.transport_server = server.SmartTCPServer_for_testing
 
2139
        self.hpss_calls = []
 
2140
        import traceback
 
2141
        # Skip the current stack down to the caller of
 
2142
        # setup_smart_server_with_call_log
 
2143
        prefix_length = len(traceback.extract_stack()) - 2
 
2144
        def capture_hpss_call(params):
 
2145
            self.hpss_calls.append(
 
2146
                CapturedCall(params, prefix_length))
 
2147
        client._SmartClient.hooks.install_named_hook(
 
2148
            'call', capture_hpss_call, None)
 
2149
 
 
2150
    def reset_smart_call_log(self):
 
2151
        self.hpss_calls = []
 
2152
 
 
2153
 
2043
2154
class TestCaseInTempDir(TestCaseWithMemoryTransport):
2044
2155
    """Derived class that runs a test within a temporary directory.
2045
2156
 
2050
2161
    All test cases create their own directory within that.  If the
2051
2162
    tests complete successfully, the directory is removed.
2052
2163
 
2053
 
    :ivar test_base_dir: The path of the top-level directory for this 
 
2164
    :ivar test_base_dir: The path of the top-level directory for this
2054
2165
    test, which contains a home directory and a work directory.
2055
2166
 
2056
2167
    :ivar test_home_dir: An initially empty directory under test_base_dir
2082
2193
 
2083
2194
    def makeAndChdirToTestDir(self):
2084
2195
        """See TestCaseWithMemoryTransport.makeAndChdirToTestDir().
2085
 
        
 
2196
 
2086
2197
        For TestCaseInTempDir we create a temporary directory based on the test
2087
2198
        name and then create two subdirs - test and home under it.
2088
2199
        """
2187
2298
    ReadonlyTransportDecorator is used instead which allows the use of non disk
2188
2299
    based read write transports.
2189
2300
 
2190
 
    If an explicit class is provided for readonly access, that server and the 
 
2301
    If an explicit class is provided for readonly access, that server and the
2191
2302
    readwrite one must both define get_url() as resolving to os.getcwd().
2192
2303
    """
2193
2304
 
2279
2390
    for readonly urls.
2280
2391
 
2281
2392
    TODO RBC 20060127: make this an option to TestCaseWithTransport so it can
2282
 
                       be used without needed to redo it when a different 
 
2393
                       be used without needed to redo it when a different
2283
2394
                       subclass is in use ?
2284
2395
    """
2285
2396
 
2291
2402
 
2292
2403
def condition_id_re(pattern):
2293
2404
    """Create a condition filter which performs a re check on a test's id.
2294
 
    
 
2405
 
2295
2406
    :param pattern: A regular expression string.
2296
2407
    :return: A callable that returns True if the re matches.
2297
2408
    """
2304
2415
 
2305
2416
def condition_isinstance(klass_or_klass_list):
2306
2417
    """Create a condition filter which returns isinstance(param, klass).
2307
 
    
 
2418
 
2308
2419
    :return: A callable which when called with one parameter obj return the
2309
2420
        result of isinstance(obj, klass_or_klass_list).
2310
2421
    """
2315
2426
 
2316
2427
def condition_id_in_list(id_list):
2317
2428
    """Create a condition filter which verify that test's id in a list.
2318
 
    
 
2429
 
2319
2430
    :param id_list: A TestIdList object.
2320
2431
    :return: A callable that returns True if the test's id appears in the list.
2321
2432
    """
2326
2437
 
2327
2438
def condition_id_startswith(starts):
2328
2439
    """Create a condition filter verifying that test's id starts with a string.
2329
 
    
 
2440
 
2330
2441
    :param starts: A list of string.
2331
 
    :return: A callable that returns True if the test's id starts with one of 
 
2442
    :return: A callable that returns True if the test's id starts with one of
2332
2443
        the given strings.
2333
2444
    """
2334
2445
    def condition(test):
2357
2468
 
2358
2469
def filter_suite_by_condition(suite, condition):
2359
2470
    """Create a test suite by filtering another one.
2360
 
    
 
2471
 
2361
2472
    :param suite: The source suite.
2362
2473
    :param condition: A callable whose result evaluates True when called with a
2363
2474
        test case which should be included in the result.
2373
2484
 
2374
2485
def filter_suite_by_re(suite, pattern):
2375
2486
    """Create a test suite by filtering another one.
2376
 
    
 
2487
 
2377
2488
    :param suite:           the source suite
2378
2489
    :param pattern:         pattern that names must match
2379
2490
    :returns: the newly created suite
2431
2542
 
2432
2543
def randomize_suite(suite):
2433
2544
    """Return a new TestSuite with suite's tests in random order.
2434
 
    
 
2545
 
2435
2546
    The tests in the input suite are flattened into a single suite in order to
2436
2547
    accomplish this. Any nested TestSuites are removed to provide global
2437
2548
    randomness.
2443
2554
 
2444
2555
def split_suite_by_condition(suite, condition):
2445
2556
    """Split a test suite into two by a condition.
2446
 
    
 
2557
 
2447
2558
    :param suite: The suite to split.
2448
2559
    :param condition: The condition to match on. Tests that match this
2449
2560
        condition are returned in the first test suite, ones that do not match
2465
2576
 
2466
2577
def split_suite_by_re(suite, pattern):
2467
2578
    """Split a test suite into two by a regular expression.
2468
 
    
 
2579
 
2469
2580
    :param suite: The suite to split.
2470
2581
    :param pattern: A regular expression string. Test ids that match this
2471
2582
        pattern will be in the first test suite returned, and the others in the
2485
2596
              list_only=False,
2486
2597
              random_seed=None,
2487
2598
              exclude_pattern=None,
2488
 
              strict=False):
 
2599
              strict=False,
 
2600
              runner_class=None):
 
2601
    """Run a test suite for bzr selftest.
 
2602
 
 
2603
    :param runner_class: The class of runner to use. Must support the
 
2604
        constructor arguments passed by run_suite which are more than standard
 
2605
        python uses.
 
2606
    :return: A boolean indicating success.
 
2607
    """
2489
2608
    TestCase._gather_lsprof_in_benchmarks = lsprof_timed
2490
2609
    if verbose:
2491
2610
        verbosity = 2
2492
2611
    else:
2493
2612
        verbosity = 1
2494
 
    runner = TextTestRunner(stream=sys.stdout,
 
2613
    if runner_class is None:
 
2614
        runner_class = TextTestRunner
 
2615
    runner = runner_class(stream=sys.stdout,
2495
2616
                            descriptions=0,
2496
2617
                            verbosity=verbosity,
2497
2618
                            bench_history=bench_history,
2553
2674
             load_list=None,
2554
2675
             debug_flags=None,
2555
2676
             starting_with=None,
 
2677
             runner_class=None,
2556
2678
             ):
2557
2679
    """Run the whole test suite under the enhanced runner"""
2558
2680
    # XXX: Very ugly way to do this...
2588
2710
                     list_only=list_only,
2589
2711
                     random_seed=random_seed,
2590
2712
                     exclude_pattern=exclude_pattern,
2591
 
                     strict=strict)
 
2713
                     strict=strict,
 
2714
                     runner_class=runner_class,
 
2715
                     )
2592
2716
    finally:
2593
2717
        default_transport = old_transport
2594
2718
        selftest_debug_flags = old_debug_flags
2621
2745
    """Warns about tests not appearing or appearing more than once.
2622
2746
 
2623
2747
    :param test_suite: A TestSuite object.
2624
 
    :param test_id_list: The list of test ids that should be found in 
 
2748
    :param test_id_list: The list of test ids that should be found in
2625
2749
         test_suite.
2626
2750
 
2627
2751
    :return: (absents, duplicates) absents is a list containing the test found
2769
2893
                   'bzrlib.tests.interrepository_implementations',
2770
2894
                   'bzrlib.tests.intertree_implementations',
2771
2895
                   'bzrlib.tests.inventory_implementations',
 
2896
                   'bzrlib.tests.per_interbranch',
2772
2897
                   'bzrlib.tests.per_lock',
2773
2898
                   'bzrlib.tests.per_repository',
2774
2899
                   'bzrlib.tests.per_repository_reference',
2787
2912
                   'bzrlib.tests.test_bundle',
2788
2913
                   'bzrlib.tests.test_bzrdir',
2789
2914
                   'bzrlib.tests.test_cache_utf8',
 
2915
                   'bzrlib.tests.test_clean_tree',
2790
2916
                   'bzrlib.tests.test_chunk_writer',
2791
2917
                   'bzrlib.tests.test__chunks_to_lines',
2792
2918
                   'bzrlib.tests.test_commands',
2797
2923
                   'bzrlib.tests.test_counted_lock',
2798
2924
                   'bzrlib.tests.test_decorators',
2799
2925
                   'bzrlib.tests.test_delta',
 
2926
                   'bzrlib.tests.test_debug',
2800
2927
                   'bzrlib.tests.test_deprecated_graph',
2801
2928
                   'bzrlib.tests.test_diff',
2802
2929
                   'bzrlib.tests.test_directory_service',
2803
2930
                   'bzrlib.tests.test_dirstate',
2804
2931
                   'bzrlib.tests.test_email_message',
2805
2932
                   'bzrlib.tests.test_errors',
 
2933
                   'bzrlib.tests.test_export',
2806
2934
                   'bzrlib.tests.test_extract',
2807
2935
                   'bzrlib.tests.test_fetch',
2808
2936
                   'bzrlib.tests.test_fifo_cache',
2874
3002
                   'bzrlib.tests.test_shelf_ui',
2875
3003
                   'bzrlib.tests.test_smart',
2876
3004
                   'bzrlib.tests.test_smart_add',
 
3005
                   'bzrlib.tests.test_smart_request',
2877
3006
                   'bzrlib.tests.test_smart_transport',
2878
3007
                   'bzrlib.tests.test_smtp_connection',
2879
3008
                   'bzrlib.tests.test_source',
2975
3104
            # No tests to keep here, move along
2976
3105
            continue
2977
3106
        try:
2978
 
            # note that this really does mean "report only" -- doctest 
 
3107
            # note that this really does mean "report only" -- doctest
2979
3108
            # still runs the rest of the examples
2980
3109
            doc_suite = doctest.DocTestSuite(mod,
2981
3110
                optionflags=doctest.REPORT_ONLY_FIRST_FAILURE)
3030
3159
    return suite
3031
3160
 
3032
3161
 
3033
 
def multiply_tests_from_modules(module_name_list, scenario_iter, loader=None):
3034
 
    """Adapt all tests in some given modules to given scenarios.
3035
 
 
3036
 
    This is the recommended public interface for test parameterization.
3037
 
    Typically the test_suite() method for a per-implementation test
3038
 
    suite will call multiply_tests_from_modules and return the 
3039
 
    result.
3040
 
 
3041
 
    :param module_name_list: List of fully-qualified names of test
3042
 
        modules.
3043
 
    :param scenario_iter: Iterable of pairs of (scenario_name, 
3044
 
        scenario_param_dict).
3045
 
    :param loader: If provided, will be used instead of a new 
3046
 
        bzrlib.tests.TestLoader() instance.
3047
 
 
3048
 
    This returns a new TestSuite containing the cross product of
3049
 
    all the tests in all the modules, each repeated for each scenario.
3050
 
    Each test is adapted by adding the scenario name at the end 
3051
 
    of its name, and updating the test object's __dict__ with the
3052
 
    scenario_param_dict.
3053
 
 
3054
 
    >>> r = multiply_tests_from_modules(
3055
 
    ...     ['bzrlib.tests.test_sampler'],
3056
 
    ...     [('one', dict(param=1)), 
3057
 
    ...      ('two', dict(param=2))])
3058
 
    >>> tests = list(iter_suite_tests(r))
3059
 
    >>> len(tests)
3060
 
    2
3061
 
    >>> tests[0].id()
3062
 
    'bzrlib.tests.test_sampler.DemoTest.test_nothing(one)'
3063
 
    >>> tests[0].param
3064
 
    1
3065
 
    >>> tests[1].param
3066
 
    2
3067
 
    """
3068
 
    # XXX: Isn't load_tests() a better way to provide the same functionality
3069
 
    # without forcing a predefined TestScenarioApplier ? --vila 080215
3070
 
    if loader is None:
3071
 
        loader = TestUtil.TestLoader()
3072
 
 
3073
 
    suite = loader.suiteClass()
3074
 
 
3075
 
    adapter = TestScenarioApplier()
3076
 
    adapter.scenarios = list(scenario_iter)
3077
 
    adapt_modules(module_name_list, adapter, loader, suite)
3078
 
    return suite
3079
 
 
3080
 
 
3081
3162
def multiply_scenarios(scenarios_left, scenarios_right):
3082
3163
    """Multiply two sets of scenarios.
3083
3164
 
3092
3173
        for right_name, right_dict in scenarios_right]
3093
3174
 
3094
3175
 
3095
 
 
3096
 
def adapt_modules(mods_list, adapter, loader, suite):
3097
 
    """Adapt the modules in mods_list using adapter and add to suite."""
3098
 
    tests = loader.loadTestsFromModuleNames(mods_list)
3099
 
    adapt_tests(tests, adapter, suite)
3100
 
 
3101
 
 
3102
 
def adapt_tests(tests_list, adapter, suite):
3103
 
    """Adapt the tests in tests_list using adapter and add to suite."""
3104
 
    for test in iter_suite_tests(tests_list):
3105
 
        suite.addTests(adapter.adapt(test))
 
3176
def multiply_tests(tests, scenarios, result):
 
3177
    """Multiply tests_list by scenarios into result.
 
3178
 
 
3179
    This is the core workhorse for test parameterisation.
 
3180
 
 
3181
    Typically the load_tests() method for a per-implementation test suite will
 
3182
    call multiply_tests and return the result.
 
3183
 
 
3184
    :param tests: The tests to parameterise.
 
3185
    :param scenarios: The scenarios to apply: pairs of (scenario_name,
 
3186
        scenario_param_dict).
 
3187
    :param result: A TestSuite to add created tests to.
 
3188
 
 
3189
    This returns the passed in result TestSuite with the cross product of all
 
3190
    the tests repeated once for each scenario.  Each test is adapted by adding
 
3191
    the scenario name at the end of its id(), and updating the test object's
 
3192
    __dict__ with the scenario_param_dict.
 
3193
 
 
3194
    >>> r = multiply_tests(
 
3195
    ...     bzrlib.tests.test_sampler.DemoTest('test_nothing'),
 
3196
    ...     [('one', dict(param=1)),
 
3197
    ...      ('two', dict(param=2))],
 
3198
    ...     TestSuite())
 
3199
    >>> tests = list(iter_suite_tests(r))
 
3200
    >>> len(tests)
 
3201
    2
 
3202
    >>> tests[0].id()
 
3203
    'bzrlib.tests.test_sampler.DemoTest.test_nothing(one)'
 
3204
    >>> tests[0].param
 
3205
    1
 
3206
    >>> tests[1].param
 
3207
    2
 
3208
    """
 
3209
    for test in iter_suite_tests(tests):
 
3210
        apply_scenarios(test, scenarios, result)
 
3211
    return result
 
3212
 
 
3213
 
 
3214
def apply_scenarios(test, scenarios, result):
 
3215
    """Apply the scenarios in scenarios to test and add to result.
 
3216
 
 
3217
    :param test: The test to apply scenarios to.
 
3218
    :param scenarios: An iterable of scenarios to apply to test.
 
3219
    :return: result
 
3220
    :seealso: apply_scenario
 
3221
    """
 
3222
    for scenario in scenarios:
 
3223
        result.addTest(apply_scenario(test, scenario))
 
3224
    return result
 
3225
 
 
3226
 
 
3227
def apply_scenario(test, scenario):
 
3228
    """Copy test and apply scenario to it.
 
3229
 
 
3230
    :param test: A test to adapt.
 
3231
    :param scenario: A tuple describing the scenarion.
 
3232
        The first element of the tuple is the new test id.
 
3233
        The second element is a dict containing attributes to set on the
 
3234
        test.
 
3235
    :return: The adapted test.
 
3236
    """
 
3237
    new_id = "%s(%s)" % (test.id(), scenario[0])
 
3238
    new_test = clone_test(test, new_id)
 
3239
    for name, value in scenario[1].items():
 
3240
        setattr(new_test, name, value)
 
3241
    return new_test
 
3242
 
 
3243
 
 
3244
def clone_test(test, new_id):
 
3245
    """Clone a test giving it a new id.
 
3246
 
 
3247
    :param test: The test to clone.
 
3248
    :param new_id: The id to assign to it.
 
3249
    :return: The new test.
 
3250
    """
 
3251
    from copy import deepcopy
 
3252
    new_test = deepcopy(test)
 
3253
    new_test.id = lambda: new_id
 
3254
    return new_test
3106
3255
 
3107
3256
 
3108
3257
def _rmtree_temp_dir(dirname):
3213
3362
UnicodeFilenameFeature = _UnicodeFilenameFeature()
3214
3363
 
3215
3364
 
3216
 
class TestScenarioApplier(object):
3217
 
    """A tool to apply scenarios to tests."""
3218
 
 
3219
 
    def adapt(self, test):
3220
 
        """Return a TestSuite containing a copy of test for each scenario."""
3221
 
        result = unittest.TestSuite()
3222
 
        for scenario in self.scenarios:
3223
 
            result.addTest(self.adapt_test_to_scenario(test, scenario))
3224
 
        return result
3225
 
 
3226
 
    def adapt_test_to_scenario(self, test, scenario):
3227
 
        """Copy test and apply scenario to it.
3228
 
 
3229
 
        :param test: A test to adapt.
3230
 
        :param scenario: A tuple describing the scenarion.
3231
 
            The first element of the tuple is the new test id.
3232
 
            The second element is a dict containing attributes to set on the
3233
 
            test.
3234
 
        :return: The adapted test.
3235
 
        """
3236
 
        from copy import deepcopy
3237
 
        new_test = deepcopy(test)
3238
 
        for name, value in scenario[1].items():
3239
 
            setattr(new_test, name, value)
3240
 
        new_id = "%s(%s)" % (new_test.id(), scenario[0])
3241
 
        new_test.id = lambda: new_id
3242
 
        return new_test
3243
 
 
3244
 
 
3245
3365
def probe_unicode_in_user_encoding():
3246
3366
    """Try to encode several unicode strings to use in unicode-aware tests.
3247
3367
    Return first successfull match.