~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/__init__.py

  • Committer: Andrew Bennetts
  • Date: 2008-03-27 06:10:18 UTC
  • mfrom: (3309 +trunk)
  • mto: This revision was merged to the branch mainline in revision 3320.
  • Revision ID: andrew.bennetts@canonical.com-20080327061018-dxztpxyv6yoeg3am
Merge from bzr.dev.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006, 2007 Canonical Ltd
 
1
# Copyright (C) 2005, 2006, 2007, 2008 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
43
43
import sys
44
44
import tempfile
45
45
import time
46
 
import trace
47
46
import unittest
48
47
import warnings
49
48
 
112
111
 
113
112
MODULES_TO_TEST = []
114
113
MODULES_TO_DOCTEST = [
 
114
        bzrlib,
115
115
        bzrlib.timestamp,
116
116
        bzrlib.errors,
117
117
        bzrlib.export,
276
276
        elif isinstance(err[1], UnavailableFeature):
277
277
            return self.addNotSupported(test, err[1].args[0])
278
278
        else:
 
279
            self._cleanupLogFile(test)
279
280
            unittest.TestResult.addError(self, test, err)
280
281
            self.error_count += 1
281
282
            self.report_error(test, err)
292
293
        if isinstance(err[1], KnownFailure):
293
294
            return self._addKnownFailure(test, err)
294
295
        else:
 
296
            self._cleanupLogFile(test)
295
297
            unittest.TestResult.addFailure(self, test, err)
296
298
            self.failure_count += 1
297
299
            self.report_failure(test, err)
311
313
                    self._formatTime(benchmark_time),
312
314
                    test.id()))
313
315
        self.report_success(test)
 
316
        self._cleanupLogFile(test)
314
317
        unittest.TestResult.addSuccess(self, test)
 
318
        test._log_contents = ''
315
319
 
316
320
    def _testConcluded(self, test):
317
321
        """Common code when a test has finished.
318
322
 
319
323
        Called regardless of whether it succeded, failed, etc.
320
324
        """
321
 
        self._cleanupLogFile(test)
 
325
        pass
322
326
 
323
327
    def _addKnownFailure(self, test, err):
324
328
        self.known_failure_count += 1
354
358
            # seems best to treat this as success from point-of-view of unittest
355
359
            # -- it actually does nothing so it barely matters :)
356
360
            unittest.TestResult.addSuccess(self, test)
 
361
            test._log_contents = ''
357
362
 
358
363
    def printErrorList(self, flavour, errors):
359
364
        for test, err in errors:
787
792
    _keep_log_file = False
788
793
    # record lsprof data when performing benchmark calls.
789
794
    _gather_lsprof_in_benchmarks = False
 
795
    attrs_to_keep = ('_testMethodName', '_testMethodDoc',
 
796
                     '_log_contents', '_log_file_name', '_benchtime',
 
797
                     '_TestCase__testMethodName')
790
798
 
791
799
    def __init__(self, methodName='testMethod'):
792
800
        super(TestCase, self).__init__(methodName)
795
803
    def setUp(self):
796
804
        unittest.TestCase.setUp(self)
797
805
        self._cleanEnvironment()
798
 
        bzrlib.trace.disable_default_logging()
799
806
        self._silenceUI()
800
807
        self._startLogFile()
801
808
        self._benchcalls = []
809
816
        Tests that want to use debug flags can just set them in the
810
817
        debug_flags set during setup/teardown.
811
818
        """
812
 
        self._preserved_debug_flags = set(debug.debug_flags)
813
 
        debug.debug_flags.clear()
814
 
        self.addCleanup(self._restore_debug_flags)
 
819
        if 'selftest_debug' not in debug.debug_flags:
 
820
            self._preserved_debug_flags = set(debug.debug_flags)
 
821
            debug.debug_flags.clear()
 
822
            self.addCleanup(self._restore_debug_flags)
815
823
 
816
824
    def _clear_hooks(self):
817
825
        # prevent hooks affecting tests
1039
1047
        else:
1040
1048
            self.fail('Unexpected success.  Should have failed: %s' % reason)
1041
1049
 
 
1050
    def assertFileEqual(self, content, path):
 
1051
        """Fail if path does not contain 'content'."""
 
1052
        self.failUnlessExists(path)
 
1053
        f = file(path, 'rb')
 
1054
        try:
 
1055
            s = f.read()
 
1056
        finally:
 
1057
            f.close()
 
1058
        self.assertEqualDiff(content, s)
 
1059
 
 
1060
    def failUnlessExists(self, path):
 
1061
        """Fail unless path or paths, which may be abs or relative, exist."""
 
1062
        if not isinstance(path, basestring):
 
1063
            for p in path:
 
1064
                self.failUnlessExists(p)
 
1065
        else:
 
1066
            self.failUnless(osutils.lexists(path),path+" does not exist")
 
1067
 
 
1068
    def failIfExists(self, path):
 
1069
        """Fail if path or paths, which may be abs or relative, exist."""
 
1070
        if not isinstance(path, basestring):
 
1071
            for p in path:
 
1072
                self.failIfExists(p)
 
1073
        else:
 
1074
            self.failIf(osutils.lexists(path),path+" exists")
 
1075
 
1042
1076
    def _capture_deprecation_warnings(self, a_callable, *args, **kwargs):
1043
1077
        """A helper for callDeprecated and applyDeprecated.
1044
1078
 
1157
1191
        """
1158
1192
        fileno, name = tempfile.mkstemp(suffix='.log', prefix='testbzr')
1159
1193
        self._log_file = os.fdopen(fileno, 'w+')
1160
 
        self._log_nonce = bzrlib.trace.enable_test_log(self._log_file)
 
1194
        self._log_memento = bzrlib.trace.push_log_file(self._log_file)
1161
1195
        self._log_file_name = name
1162
1196
        self.addCleanup(self._finishLogFile)
1163
1197
 
1168
1202
        """
1169
1203
        if self._log_file is None:
1170
1204
            return
1171
 
        bzrlib.trace.disable_test_log(self._log_nonce)
 
1205
        bzrlib.trace.pop_log_file(self._log_memento)
1172
1206
        self._log_file.close()
1173
1207
        self._log_file = None
1174
1208
        if not self._keep_log_file:
1200
1234
            'BZREMAIL': None, # may still be present in the environment
1201
1235
            'EMAIL': None,
1202
1236
            'BZR_PROGRESS_BAR': None,
 
1237
            'BZR_LOG': None,
1203
1238
            # SSH Agent
1204
1239
            'SSH_AUTH_SOCK': None,
1205
1240
            # Proxies
1254
1289
                    result.addSuccess(self)
1255
1290
                result.stopTest(self)
1256
1291
                return
1257
 
        return unittest.TestCase.run(self, result)
 
1292
        try:
 
1293
            return unittest.TestCase.run(self, result)
 
1294
        finally:
 
1295
            saved_attrs = {}
 
1296
            absent_attr = object()
 
1297
            for attr_name in self.attrs_to_keep:
 
1298
                attr = getattr(self, attr_name, absent_attr)
 
1299
                if attr is not absent_attr:
 
1300
                    saved_attrs[attr_name] = attr
 
1301
            self.__dict__ = saved_attrs
1258
1302
 
1259
1303
    def tearDown(self):
1260
1304
        self._runCleanups()
1311
1355
        import bzrlib.trace
1312
1356
        bzrlib.trace._trace_file.flush()
1313
1357
        if self._log_contents:
 
1358
            # XXX: this can hardly contain the content flushed above --vila
 
1359
            # 20080128
1314
1360
            return self._log_contents
1315
1361
        if self._log_file_name is not None:
1316
1362
            logfile = open(self._log_file_name)
2084
2130
    def build_tree_contents(self, shape):
2085
2131
        build_tree_contents(shape)
2086
2132
 
2087
 
    def assertFileEqual(self, content, path):
2088
 
        """Fail if path does not contain 'content'."""
2089
 
        self.failUnlessExists(path)
2090
 
        f = file(path, 'rb')
2091
 
        try:
2092
 
            s = f.read()
2093
 
        finally:
2094
 
            f.close()
2095
 
        self.assertEqualDiff(content, s)
2096
 
 
2097
 
    def failUnlessExists(self, path):
2098
 
        """Fail unless path or paths, which may be abs or relative, exist."""
2099
 
        if not isinstance(path, basestring):
2100
 
            for p in path:
2101
 
                self.failUnlessExists(p)
2102
 
        else:
2103
 
            self.failUnless(osutils.lexists(path),path+" does not exist")
2104
 
 
2105
 
    def failIfExists(self, path):
2106
 
        """Fail if path or paths, which may be abs or relative, exist."""
2107
 
        if not isinstance(path, basestring):
2108
 
            for p in path:
2109
 
                self.failIfExists(p)
2110
 
        else:
2111
 
            self.failIf(osutils.lexists(path),path+" exists")
2112
 
 
2113
2133
    def assertInWorkingTree(self, path, root_path='.', tree=None):
2114
2134
        """Assert whether path or paths are in the WorkingTree"""
2115
2135
        if tree is None:
2261
2281
    return condition
2262
2282
 
2263
2283
 
 
2284
def condition_id_in_list(id_list):
 
2285
    """Create a condition filter which verify that test's id in a list.
 
2286
    
 
2287
    :param name: A TestIdList object.
 
2288
    :return: A callable that returns True if the test's id appears in the list.
 
2289
    """
 
2290
    def condition(test):
 
2291
        return id_list.test_in(test.id())
 
2292
    return condition
 
2293
 
 
2294
 
2264
2295
def exclude_tests_by_condition(suite, condition):
2265
2296
    """Create a test suite which excludes some tests from suite.
2266
2297
 
2324
2355
    return result_suite
2325
2356
 
2326
2357
 
 
2358
def filter_suite_by_id_list(suite, test_id_list):
 
2359
    """Create a test suite by filtering another one.
 
2360
 
 
2361
    :param suite: The source suite.
 
2362
    :param test_id_list: A list of the test ids to keep as strings.
 
2363
    :returns: the newly created suite
 
2364
    """
 
2365
    condition = condition_id_in_list(test_id_list)
 
2366
    result_suite = filter_suite_by_condition(suite, condition)
 
2367
    return result_suite
 
2368
 
 
2369
 
2327
2370
def exclude_tests_by_re(suite, pattern):
2328
2371
    """Create a test suite which excludes some tests from suite.
2329
2372
 
2425
2468
              list_only=False,
2426
2469
              random_seed=None,
2427
2470
              exclude_pattern=None,
2428
 
              strict=False,
2429
 
              coverage_dir=None,
2430
 
              ):
 
2471
              strict=False):
2431
2472
    TestCase._gather_lsprof_in_benchmarks = lsprof_timed
2432
2473
    if verbose:
2433
2474
        verbosity = 2
2470
2511
        else:
2471
2512
            suite = order_changer(filter_suite_by_re(suite, pattern))
2472
2513
 
2473
 
    # Activate code coverage.
2474
 
    if coverage_dir is not None:
2475
 
        tracer = trace.Trace(count=1, trace=0)
2476
 
        sys.settrace(tracer.globaltrace)
2477
 
 
2478
2514
    result = runner.run(suite)
2479
2515
 
2480
 
    if coverage_dir is not None:
2481
 
        sys.settrace(None)
2482
 
        results = tracer.results()
2483
 
        results.write_results(show_missing=1, summary=False,
2484
 
                              coverdir=coverage_dir)
2485
 
 
2486
2516
    if strict:
2487
2517
        return result.wasStrictlySuccessful()
2488
2518
 
2499
2529
             random_seed=None,
2500
2530
             exclude_pattern=None,
2501
2531
             strict=False,
2502
 
             coverage_dir=None,
 
2532
             load_list=None,
2503
2533
             ):
2504
2534
    """Run the whole test suite under the enhanced runner"""
2505
2535
    # XXX: Very ugly way to do this...
2514
2544
    old_transport = default_transport
2515
2545
    default_transport = transport
2516
2546
    try:
 
2547
        if load_list is None:
 
2548
            keep_only = None
 
2549
        else:
 
2550
            keep_only = load_test_id_list(load_list)
2517
2551
        if test_suite_factory is None:
2518
 
            suite = test_suite()
 
2552
            suite = test_suite(keep_only)
2519
2553
        else:
2520
2554
            suite = test_suite_factory()
2521
2555
        return run_suite(suite, 'testbzr', verbose=verbose, pattern=pattern,
2527
2561
                     list_only=list_only,
2528
2562
                     random_seed=random_seed,
2529
2563
                     exclude_pattern=exclude_pattern,
2530
 
                     strict=strict,
2531
 
                     coverage_dir=coverage_dir)
 
2564
                     strict=strict)
2532
2565
    finally:
2533
2566
        default_transport = old_transport
2534
2567
 
2535
2568
 
2536
 
def test_suite():
 
2569
def load_test_id_list(file_name):
 
2570
    """Load a test id list from a text file.
 
2571
 
 
2572
    The format is one test id by line.  No special care is taken to impose
 
2573
    strict rules, these test ids are used to filter the test suite so a test id
 
2574
    that do not match an existing test will do no harm. This allows user to add
 
2575
    comments, leave blank lines, etc.
 
2576
    """
 
2577
    test_list = []
 
2578
    try:
 
2579
        ftest = open(file_name, 'rt')
 
2580
    except IOError, e:
 
2581
        if e.errno != errno.ENOENT:
 
2582
            raise
 
2583
        else:
 
2584
            raise errors.NoSuchFile(file_name)
 
2585
 
 
2586
    for test_name in ftest.readlines():
 
2587
        test_list.append(test_name.strip())
 
2588
    ftest.close()
 
2589
    return test_list
 
2590
 
 
2591
 
 
2592
class TestIdList(object):
 
2593
    """Test id list to filter a test suite.
 
2594
 
 
2595
    Relying on the assumption that test ids are built as:
 
2596
    <module>[.<class>.<method>][(<param>+)], <module> being in python dotted
 
2597
    notation, this class offers methods to :
 
2598
    - avoid building a test suite for modules not refered to in the test list,
 
2599
    - keep only the tests listed from the module test suite.
 
2600
    """
 
2601
 
 
2602
    def __init__(self, test_id_list):
 
2603
        # When a test suite needs to be filtered against us we compare test ids
 
2604
        # for equality, so a simple dict offers a quick and simple solution.
 
2605
        self.tests = dict().fromkeys(test_id_list, True)
 
2606
 
 
2607
        # While unittest.TestCase have ids like:
 
2608
        # <module>.<class>.<method>[(<param+)],
 
2609
        # doctest.DocTestCase can have ids like:
 
2610
        # <module>
 
2611
        # <module>.<class>
 
2612
        # <module>.<function>
 
2613
        # <module>.<class>.<method>
 
2614
 
 
2615
        # Since we can't predict a test class from its name only, we settle on
 
2616
        # a simple constraint: a test id always begins with its module name.
 
2617
 
 
2618
        modules = {}
 
2619
        for test_id in test_id_list:
 
2620
            parts = test_id.split('.')
 
2621
            mod_name = parts.pop(0)
 
2622
            modules[mod_name] = True
 
2623
            for part in parts:
 
2624
                mod_name += '.' + part
 
2625
                modules[mod_name] = True
 
2626
        self.modules = modules
 
2627
 
 
2628
    def is_module_name_used(self, module_name):
 
2629
        """Is there tests for the module or one of its sub modules."""
 
2630
        return self.modules.has_key(module_name)
 
2631
 
 
2632
    def test_in(self, test_id):
 
2633
        return self.tests.has_key(test_id)
 
2634
 
 
2635
 
 
2636
def test_suite(keep_only=None):
2537
2637
    """Build and return TestSuite for the whole of bzrlib.
2538
 
    
 
2638
 
 
2639
    :param keep_only: A list of test ids limiting the suite returned.
 
2640
 
2539
2641
    This function can be replaced if you need to change the default test
2540
2642
    suite on a global basis, but it is not encouraged.
2541
2643
    """
2565
2667
                   'bzrlib.tests.test_deprecated_graph',
2566
2668
                   'bzrlib.tests.test_diff',
2567
2669
                   'bzrlib.tests.test_dirstate',
 
2670
                   'bzrlib.tests.test_directory_service',
2568
2671
                   'bzrlib.tests.test_email_message',
2569
2672
                   'bzrlib.tests.test_errors',
2570
2673
                   'bzrlib.tests.test_escaped_store',
2655
2758
                   'bzrlib.tests.test_tsort',
2656
2759
                   'bzrlib.tests.test_tuned_gzip',
2657
2760
                   'bzrlib.tests.test_ui',
 
2761
                   'bzrlib.tests.test_uncommit',
2658
2762
                   'bzrlib.tests.test_upgrade',
2659
2763
                   'bzrlib.tests.test_urlutils',
2660
2764
                   'bzrlib.tests.test_versionedfile',
2674
2778
        ]
2675
2779
    suite = TestUtil.TestSuite()
2676
2780
    loader = TestUtil.TestLoader()
2677
 
    suite.addTest(loader.loadTestsFromModuleNames(testmod_names))
 
2781
 
 
2782
    if keep_only is not None:
 
2783
        id_filter = TestIdList(keep_only)
 
2784
 
 
2785
    # modules building their suite with loadTestsFromModuleNames
 
2786
    if keep_only is None:
 
2787
        suite.addTest(loader.loadTestsFromModuleNames(testmod_names))
 
2788
    else:
 
2789
        for mod in [m for m in testmod_names
 
2790
                    if id_filter.is_module_name_used(m)]:
 
2791
            mod_suite = loader.loadTestsFromModuleNames([mod])
 
2792
            mod_suite = filter_suite_by_id_list(mod_suite, id_filter)
 
2793
            suite.addTest(mod_suite)
 
2794
 
 
2795
    # modules adapted for transport implementations
2678
2796
    from bzrlib.tests.test_transport_implementations import TransportTestProviderAdapter
2679
2797
    adapter = TransportTestProviderAdapter()
2680
 
    adapt_modules(test_transport_implementations, adapter, loader, suite)
2681
 
    for package in packages_to_test():
2682
 
        suite.addTest(package.test_suite())
2683
 
    for m in MODULES_TO_TEST:
2684
 
        suite.addTest(loader.loadTestsFromModule(m))
2685
 
    for m in MODULES_TO_DOCTEST:
 
2798
    if keep_only is None:
 
2799
        adapt_modules(test_transport_implementations, adapter, loader, suite)
 
2800
    else:
 
2801
        for mod in [m for m in test_transport_implementations
 
2802
                    if id_filter.is_module_name_used(m)]:
 
2803
            mod_suite = TestUtil.TestSuite()
 
2804
            adapt_modules([mod], adapter, loader, mod_suite)
 
2805
            mod_suite = filter_suite_by_id_list(mod_suite, id_filter)
 
2806
            suite.addTest(mod_suite)
 
2807
 
 
2808
    # modules defining their own test_suite()
 
2809
    for package in [p for p in packages_to_test()
 
2810
                    if (keep_only is None
 
2811
                        or id_filter.is_module_name_used(p.__name__))]:
 
2812
        pack_suite = package.test_suite()
 
2813
        if keep_only is not None:
 
2814
            pack_suite = filter_suite_by_id_list(pack_suite, id_filter)
 
2815
        suite.addTest(pack_suite)
 
2816
 
 
2817
    # XXX: MODULES_TO_TEST should be obsoleted ?
 
2818
    for mod in [m for m in MODULES_TO_TEST
 
2819
                if keep_only is None or id_filter.is_module_name_used(m)]:
 
2820
        mod_suite = loader.loadTestsFromModule(mod)
 
2821
        if keep_only is not None:
 
2822
            mod_suite = filter_suite_by_id_list(mod_suite, id_filter)
 
2823
        suite.addTest(mod_suite)
 
2824
 
 
2825
    for mod in MODULES_TO_DOCTEST:
2686
2826
        try:
2687
 
            suite.addTest(doctest.DocTestSuite(m))
 
2827
            doc_suite = doctest.DocTestSuite(mod)
2688
2828
        except ValueError, e:
2689
 
            print '**failed to get doctest for: %s\n%s' %(m,e)
 
2829
            print '**failed to get doctest for: %s\n%s' % (mod, e)
2690
2830
            raise
 
2831
        if keep_only is not None:
 
2832
            # DocTests may use ids which doesn't contain the module name
 
2833
            doc_suite = filter_suite_by_id_list(doc_suite, id_filter)
 
2834
        suite.addTest(doc_suite)
 
2835
 
2691
2836
    default_encoding = sys.getdefaultencoding()
2692
2837
    for name, plugin in bzrlib.plugin.plugins().items():
2693
 
        try:
2694
 
            plugin_suite = plugin.test_suite()
2695
 
        except ImportError, e:
2696
 
            bzrlib.trace.warning(
2697
 
                'Unable to test plugin "%s": %s', name, e)
2698
 
        else:
2699
 
            if plugin_suite is not None:
2700
 
                suite.addTest(plugin_suite)
 
2838
        if keep_only is not None:
 
2839
            if not id_filter.is_module_name_used(plugin.module.__name__):
 
2840
                continue
 
2841
        plugin_suite = plugin.test_suite()
 
2842
        # We used to catch ImportError here and turn it into just a warning,
 
2843
        # but really if you don't have --no-plugins this should be a failure.
 
2844
        # mbp 20080213 - see http://bugs.launchpad.net/bugs/189771
 
2845
        if plugin_suite is not None:
 
2846
            if keep_only is not None:
 
2847
                plugin_suite = filter_suite_by_id_list(plugin_suite,
 
2848
                                                       id_filter)
 
2849
            suite.addTest(plugin_suite)
2701
2850
        if default_encoding != sys.getdefaultencoding():
2702
2851
            bzrlib.trace.warning(
2703
2852
                'Plugin "%s" tried to reset default encoding to: %s', name,
2837
2986
SymlinkFeature = _SymlinkFeature()
2838
2987
 
2839
2988
 
 
2989
class _HardlinkFeature(Feature):
 
2990
 
 
2991
    def _probe(self):
 
2992
        return osutils.has_hardlinks()
 
2993
 
 
2994
    def feature_name(self):
 
2995
        return 'hardlinks'
 
2996
 
 
2997
HardlinkFeature = _HardlinkFeature()
 
2998
 
 
2999
 
2840
3000
class _OsFifoFeature(Feature):
2841
3001
 
2842
3002
    def _probe(self):