/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: Daniel Watkins
  • Date: 2007-11-06 09:33:05 UTC
  • mfrom: (2967 +trunk)
  • mto: This revision was merged to the branch mainline in revision 2993.
  • Revision ID: d.m.watkins@warwick.ac.uk-20071106093305-zfef3c0jbcvunnuz
Merged bzr.dev.

Show diffs side-by-side

added added

removed removed

Lines of Context:
72
72
    pass
73
73
from bzrlib.merge import merge_inner
74
74
import bzrlib.merge3
75
 
import bzrlib.osutils
76
75
import bzrlib.plugin
77
76
from bzrlib.revision import common_ancestor
78
77
import bzrlib.store
79
78
from bzrlib import symbol_versioning
80
79
from bzrlib.symbol_versioning import (
81
80
    deprecated_method,
82
 
    zero_eighteen,
83
81
    zero_ninetyone,
 
82
    zero_ninetytwo,
84
83
    )
85
84
import bzrlib.trace
86
85
from bzrlib.transport import get_transport
162
161
class ExtendedTestResult(unittest._TextTestResult):
163
162
    """Accepts, reports and accumulates the results of running tests.
164
163
 
165
 
    Compared to this unittest version this class adds support for
 
164
    Compared to the unittest version this class adds support for
166
165
    profiling, benchmarking, stopping as soon as a test fails,  and
167
166
    skipping tests.  There are further-specialized subclasses for
168
167
    different types of display.
343
342
        except KeyboardInterrupt:
344
343
            raise
345
344
        except:
346
 
            self.addError(test, test.__exc_info())
 
345
            self.addError(test, test._exc_info())
347
346
        else:
348
347
            # seems best to treat this as success from point-of-view of unittest
349
348
            # -- it actually does nothing so it barely matters :)
355
354
            self.stream.write("%s: " % flavour)
356
355
            self.stream.writeln(self.getDescription(test))
357
356
            if getattr(test, '_get_log', None) is not None:
358
 
                print >>self.stream
359
 
                print >>self.stream, \
360
 
                        ('vvvv[log from %s]' % test.id()).ljust(78,'-')
361
 
                print >>self.stream, test._get_log()
362
 
                print >>self.stream, \
363
 
                        ('^^^^[log from %s]' % test.id()).ljust(78,'-')
 
357
                self.stream.write('\n')
 
358
                self.stream.write(
 
359
                        ('vvvv[log from %s]' % test.id()).ljust(78,'-'))
 
360
                self.stream.write('\n')
 
361
                self.stream.write(test._get_log())
 
362
                self.stream.write('\n')
 
363
                self.stream.write(
 
364
                        ('^^^^[log from %s]' % test.id()).ljust(78,'-'))
 
365
                self.stream.write('\n')
364
366
            self.stream.writeln(self.separator2)
365
367
            self.stream.writeln("%s" % err)
366
368
 
983
985
        self.assertEqual(mode, actual_mode,
984
986
            'mode of %r incorrect (%o != %o)' % (path, mode, actual_mode))
985
987
 
 
988
    def assertIsSameRealPath(self, path1, path2):
 
989
        """Fail if path1 and path2 points to different files"""
 
990
        self.assertEqual(osutils.realpath(path1),
 
991
                         osutils.realpath(path2),
 
992
                         "apparent paths:\na = %s\nb = %s\n," % (path1, path2))
 
993
 
986
994
    def assertIsInstance(self, obj, kls):
987
995
        """Fail if obj is not an instance of kls"""
988
996
        if not isinstance(obj, kls):
1024
1032
        else:
1025
1033
            self.fail('Unexpected success.  Should have failed: %s' % reason)
1026
1034
 
1027
 
    def _capture_warnings(self, a_callable, *args, **kwargs):
 
1035
    def _capture_deprecation_warnings(self, a_callable, *args, **kwargs):
1028
1036
        """A helper for callDeprecated and applyDeprecated.
1029
1037
 
1030
1038
        :param a_callable: A callable to call.
1072
1080
        :param kwargs: The keyword arguments for the callable
1073
1081
        :return: The result of a_callable(``*args``, ``**kwargs``)
1074
1082
        """
1075
 
        call_warnings, result = self._capture_warnings(a_callable,
 
1083
        call_warnings, result = self._capture_deprecation_warnings(a_callable,
1076
1084
            *args, **kwargs)
1077
1085
        expected_first_warning = symbol_versioning.deprecation_string(
1078
1086
            a_callable, deprecation_format)
1082
1090
        self.assertEqual(expected_first_warning, call_warnings[0])
1083
1091
        return result
1084
1092
 
 
1093
    def callCatchWarnings(self, fn, *args, **kw):
 
1094
        """Call a callable that raises python warnings.
 
1095
 
 
1096
        The caller's responsible for examining the returned warnings.
 
1097
 
 
1098
        If the callable raises an exception, the exception is not
 
1099
        caught and propagates up to the caller.  In that case, the list
 
1100
        of warnings is not available.
 
1101
 
 
1102
        :returns: ([warning_object, ...], fn_result)
 
1103
        """
 
1104
        # XXX: This is not perfect, because it completely overrides the
 
1105
        # warnings filters, and some code may depend on suppressing particular
 
1106
        # warnings.  It's the easiest way to insulate ourselves from -Werror,
 
1107
        # though.  -- Andrew, 20071062
 
1108
        wlist = []
 
1109
        def _catcher(message, category, filename, lineno, file=None):
 
1110
            # despite the name, 'message' is normally(?) a Warning subclass
 
1111
            # instance
 
1112
            wlist.append(message)
 
1113
        saved_showwarning = warnings.showwarning
 
1114
        saved_filters = warnings.filters
 
1115
        try:
 
1116
            warnings.showwarning = _catcher
 
1117
            warnings.filters = []
 
1118
            result = fn(*args, **kw)
 
1119
        finally:
 
1120
            warnings.showwarning = saved_showwarning
 
1121
            warnings.filters = saved_filters
 
1122
        return wlist, result
 
1123
 
1085
1124
    def callDeprecated(self, expected, callable, *args, **kwargs):
1086
1125
        """Assert that a callable is deprecated in a particular way.
1087
1126
 
1091
1130
        and will ensure that that is issued for the function being called.
1092
1131
 
1093
1132
        Note that this only captures warnings raised by symbol_versioning.warn,
1094
 
        not other callers that go direct to the warning module.
 
1133
        not other callers that go direct to the warning module.  To catch
 
1134
        general warnings, use callCatchWarnings.
1095
1135
 
1096
1136
        :param expected: a list of the deprecation warnings expected, in order
1097
1137
        :param callable: The callable to call
1098
1138
        :param args: The positional arguments for the callable
1099
1139
        :param kwargs: The keyword arguments for the callable
1100
1140
        """
1101
 
        call_warnings, result = self._capture_warnings(callable,
 
1141
        call_warnings, result = self._capture_deprecation_warnings(callable,
1102
1142
            *args, **kwargs)
1103
1143
        self.assertEqual(expected, call_warnings)
1104
1144
        return result
1148
1188
            'BZR_HOME': None, # Don't inherit BZR_HOME to all the tests.
1149
1189
            'HOME': os.getcwd(),
1150
1190
            'APPDATA': None,  # bzr now use Win32 API and don't rely on APPDATA
 
1191
            'BZR_EDITOR': None, # test_msgeditor manipulates this variable
1151
1192
            'BZR_EMAIL': None,
1152
1193
            'BZREMAIL': None, # may still be present in the environment
1153
1194
            'EMAIL': None,
1276
1317
                    os.remove(self._log_file_name)
1277
1318
                except OSError, e:
1278
1319
                    if sys.platform == 'win32' and e.errno == errno.EACCES:
1279
 
                        print >>sys.stderr, ('Unable to delete log file '
1280
 
                                             ' %r' % self._log_file_name)
 
1320
                        sys.stderr.write(('Unable to delete log file '
 
1321
                                             ' %r\n' % self._log_file_name))
1281
1322
                    else:
1282
1323
                        raise
1283
1324
            return log_contents
1284
1325
        else:
1285
1326
            return "DELETED log file to reduce memory footprint"
1286
1327
 
1287
 
    @deprecated_method(zero_eighteen)
1288
 
    def capture(self, cmd, retcode=0):
1289
 
        """Shortcut that splits cmd into words, runs, and returns stdout"""
1290
 
        return self.run_bzr_captured(cmd.split(), retcode=retcode)[0]
1291
 
 
1292
1328
    def requireFeature(self, feature):
1293
1329
        """This test requires a specific feature is available.
1294
1330
 
1297
1333
        if not feature.available():
1298
1334
            raise UnavailableFeature(feature)
1299
1335
 
1300
 
    @deprecated_method(zero_eighteen)
1301
 
    def run_bzr_captured(self, argv, retcode=0, encoding=None, stdin=None,
1302
 
                         working_dir=None):
1303
 
        """Invoke bzr and return (stdout, stderr).
1304
 
 
1305
 
        Don't call this method, just use run_bzr() which is equivalent.
1306
 
 
1307
 
        :param argv: Arguments to invoke bzr.  This may be either a 
1308
 
            single string, in which case it is split by shlex into words, 
1309
 
            or a list of arguments.
1310
 
        :param retcode: Expected return code, or None for don't-care.
1311
 
        :param encoding: Encoding for sys.stdout and sys.stderr
1312
 
        :param stdin: A string to be used as stdin for the command.
1313
 
        :param working_dir: Change to this directory before running
1314
 
        """
1315
 
        return self._run_bzr_autosplit(argv, retcode=retcode,
1316
 
                encoding=encoding, stdin=stdin, working_dir=working_dir,
1317
 
                )
1318
 
 
1319
1336
    def _run_bzr_autosplit(self, args, retcode, encoding, stdin,
1320
1337
            working_dir):
1321
1338
        """Run bazaar command line, splitting up a string command line."""
1322
1339
        if isinstance(args, basestring):
1323
 
            args = list(shlex.split(args))
 
1340
            # shlex don't understand unicode strings,
 
1341
            # so args should be plain string (bialix 20070906)
 
1342
            args = list(shlex.split(str(args)))
1324
1343
        return self._run_bzr_core(args, retcode=retcode,
1325
1344
                encoding=encoding, stdin=stdin, working_dir=working_dir,
1326
1345
                )
1351
1370
        try:
1352
1371
            result = self.apply_redirected(ui.ui_factory.stdin,
1353
1372
                stdout, stderr,
1354
 
                bzrlib.commands.run_bzr_catch_errors,
 
1373
                bzrlib.commands.run_bzr_catch_user_errors,
1355
1374
                args)
1356
1375
        finally:
1357
1376
            logger.removeHandler(handler)
1370
1389
                              message='Unexpected return code')
1371
1390
        return out, err
1372
1391
 
1373
 
    def run_bzr(self, *args, **kwargs):
 
1392
    def run_bzr(self, args, retcode=0, encoding=None, stdin=None,
 
1393
                working_dir=None, error_regexes=[], output_encoding=None):
1374
1394
        """Invoke bzr, as if it were run from the command line.
1375
1395
 
1376
1396
        The argument list should not include the bzr program name - the
1384
1404
        2- A single string, eg "add a".  This is the most convenient 
1385
1405
        for hardcoded commands.
1386
1406
 
1387
 
        3- Several varargs parameters, eg run_bzr("add", "a").  
1388
 
        This is not recommended for new code.
1389
 
 
1390
1407
        This runs bzr through the interface that catches and reports
1391
1408
        errors, and with logging set to something approximating the
1392
1409
        default, so that error reporting can be checked.
1405
1422
        :keyword error_regexes: A list of expected error messages.  If
1406
1423
            specified they must be seen in the error output of the command.
1407
1424
        """
1408
 
        retcode = kwargs.pop('retcode', 0)
1409
 
        encoding = kwargs.pop('encoding', None)
1410
 
        stdin = kwargs.pop('stdin', None)
1411
 
        working_dir = kwargs.pop('working_dir', None)
1412
 
        error_regexes = kwargs.pop('error_regexes', [])
1413
 
 
1414
 
        if kwargs:
1415
 
            raise TypeError("run_bzr() got unexpected keyword arguments '%s'"
1416
 
                            % kwargs.keys())
1417
 
 
1418
 
        if len(args) == 1:
1419
 
            if isinstance(args[0], (list, basestring)):
1420
 
                args = args[0]
1421
 
        else:
1422
 
            symbol_versioning.warn(zero_eighteen % "passing varargs to run_bzr",
1423
 
                                   DeprecationWarning, stacklevel=3)
1424
 
 
1425
 
        out, err = self._run_bzr_autosplit(args=args,
 
1425
        out, err = self._run_bzr_autosplit(
 
1426
            args=args,
1426
1427
            retcode=retcode,
1427
 
            encoding=encoding, stdin=stdin, working_dir=working_dir,
 
1428
            encoding=encoding,
 
1429
            stdin=stdin,
 
1430
            working_dir=working_dir,
1428
1431
            )
1429
 
 
1430
1432
        for regex in error_regexes:
1431
1433
            self.assertContainsRe(err, regex)
1432
1434
        return out, err
1433
1435
 
1434
 
    def run_bzr_decode(self, *args, **kwargs):
1435
 
        if 'encoding' in kwargs:
1436
 
            encoding = kwargs['encoding']
1437
 
        else:
1438
 
            encoding = bzrlib.user_encoding
1439
 
        return self.run_bzr(*args, **kwargs)[0].decode(encoding)
1440
 
 
1441
1436
    def run_bzr_error(self, error_regexes, *args, **kwargs):
1442
1437
        """Run bzr, and check that stderr contains the supplied regexes
1443
1438
 
1875
1870
        base = self.get_vfs_only_server().get_url()
1876
1871
        return self._adjust_url(base, relpath)
1877
1872
 
 
1873
    def _create_safety_net(self):
 
1874
        """Make a fake bzr directory.
 
1875
 
 
1876
        This prevents any tests propagating up onto the TEST_ROOT directory's
 
1877
        real branch.
 
1878
        """
 
1879
        root = TestCaseWithMemoryTransport.TEST_ROOT
 
1880
        bzrdir.BzrDir.create_standalone_workingtree(root)
 
1881
 
 
1882
    def _check_safety_net(self):
 
1883
        """Check that the safety .bzr directory have not been touched.
 
1884
 
 
1885
        _make_test_root have created a .bzr directory to prevent tests from
 
1886
        propagating. This method ensures than a test did not leaked.
 
1887
        """
 
1888
        root = TestCaseWithMemoryTransport.TEST_ROOT
 
1889
        wt = workingtree.WorkingTree.open(root)
 
1890
        last_rev = wt.last_revision()
 
1891
        if last_rev != 'null:':
 
1892
            # The current test have modified the /bzr directory, we need to
 
1893
            # recreate a new one or all the followng tests will fail.
 
1894
            # If you need to inspect its content uncomment the following line
 
1895
            # import pdb; pdb.set_trace()
 
1896
            _rmtree_temp_dir(root + '/.bzr')
 
1897
            self._create_safety_net()
 
1898
            raise AssertionError('%s/.bzr should not be modified' % root)
 
1899
 
1878
1900
    def _make_test_root(self):
1879
 
        if TestCaseWithMemoryTransport.TEST_ROOT is not None:
1880
 
            return
1881
 
        root = tempfile.mkdtemp(prefix='testbzr-', suffix='.tmp')
1882
 
        TestCaseWithMemoryTransport.TEST_ROOT = root
1883
 
        
1884
 
        # make a fake bzr directory there to prevent any tests propagating
1885
 
        # up onto the source directory's real branch
1886
 
        bzrdir.BzrDir.create_standalone_workingtree(root)
1887
 
 
1888
 
        # The same directory is used by all tests, and we're not specifically
1889
 
        # told when all tests are finished.  This will do.
1890
 
        atexit.register(_rmtree_temp_dir, root)
 
1901
        if TestCaseWithMemoryTransport.TEST_ROOT is None:
 
1902
            root = osutils.mkdtemp(prefix='testbzr-', suffix='.tmp')
 
1903
            TestCaseWithMemoryTransport.TEST_ROOT = root
 
1904
 
 
1905
            self._create_safety_net()
 
1906
 
 
1907
            # The same directory is used by all tests, and we're not
 
1908
            # specifically told when all tests are finished.  This will do.
 
1909
            atexit.register(_rmtree_temp_dir, root)
 
1910
 
 
1911
        self.addCleanup(self._check_safety_net)
1891
1912
 
1892
1913
    def makeAndChdirToTestDir(self):
1893
1914
        """Create a temporary directories for this one test.
1994
2015
        name and then create two subdirs - test and home under it.
1995
2016
        """
1996
2017
        # create a directory within the top level test directory
1997
 
        candidate_dir = tempfile.mkdtemp(dir=self.TEST_ROOT)
 
2018
        candidate_dir = osutils.mkdtemp(dir=self.TEST_ROOT)
1998
2019
        # now create test and home directories within this dir
1999
2020
        self.test_base_dir = candidate_dir
2000
2021
        self.test_home_dir = self.test_base_dir + '/home'
2361
2382
                   'bzrlib.tests.test_api',
2362
2383
                   'bzrlib.tests.test_atomicfile',
2363
2384
                   'bzrlib.tests.test_bad_files',
 
2385
                   'bzrlib.tests.test_bisect_multi',
2364
2386
                   'bzrlib.tests.test_branch',
2365
2387
                   'bzrlib.tests.test_branchbuilder',
2366
2388
                   'bzrlib.tests.test_bugtracker',
2426
2448
                   'bzrlib.tests.test_permissions',
2427
2449
                   'bzrlib.tests.test_plugins',
2428
2450
                   'bzrlib.tests.test_progress',
 
2451
                   'bzrlib.tests.test_reconfigure',
2429
2452
                   'bzrlib.tests.test_reconcile',
2430
2453
                   'bzrlib.tests.test_registry',
2431
2454
                   'bzrlib.tests.test_remote',
2557
2580
    return suite
2558
2581
 
2559
2582
 
 
2583
def multiply_scenarios(scenarios_left, scenarios_right):
 
2584
    """Multiply two sets of scenarios.
 
2585
 
 
2586
    :returns: the cartesian product of the two sets of scenarios, that is
 
2587
        a scenario for every possible combination of a left scenario and a
 
2588
        right scenario.
 
2589
    """
 
2590
    return [
 
2591
        ('%s,%s' % (left_name, right_name),
 
2592
         dict(left_dict.items() + right_dict.items()))
 
2593
        for left_name, left_dict in scenarios_left
 
2594
        for right_name, right_dict in scenarios_right]
 
2595
 
 
2596
 
 
2597
 
2560
2598
def adapt_modules(mods_list, adapter, loader, suite):
2561
2599
    """Adapt the modules in mods_list using adapter and add to suite."""
2562
2600
    for test in iter_suite_tests(loader.loadTestsFromModuleNames(mods_list)):
2579
2617
        osutils.rmtree(dirname)
2580
2618
    except OSError, e:
2581
2619
        if sys.platform == 'win32' and e.errno == errno.EACCES:
2582
 
            print >>sys.stderr, ('Permission denied: '
 
2620
            sys.stderr.write(('Permission denied: '
2583
2621
                                 'unable to remove testing dir '
2584
 
                                 '%s' % os.path.basename(dirname))
 
2622
                                 '%s\n' % os.path.basename(dirname)))
2585
2623
        else:
2586
2624
            raise
2587
2625
 
2625
2663
SymlinkFeature = _SymlinkFeature()
2626
2664
 
2627
2665
 
 
2666
class _OsFifoFeature(Feature):
 
2667
 
 
2668
    def _probe(self):
 
2669
        return getattr(os, 'mkfifo', None)
 
2670
 
 
2671
    def feature_name(self):
 
2672
        return 'filesystem fifos'
 
2673
 
 
2674
OsFifoFeature = _OsFifoFeature()
 
2675
 
 
2676
 
2628
2677
class TestScenarioApplier(object):
2629
2678
    """A tool to apply scenarios to tests."""
2630
2679
 
2670
2719
        else:
2671
2720
            return uni_val, str_val
2672
2721
    return None, None
 
2722
 
 
2723
 
 
2724
def probe_bad_non_ascii(encoding):
 
2725
    """Try to find [bad] character with code [128..255]
 
2726
    that cannot be decoded to unicode in some encoding.
 
2727
    Return None if all non-ascii characters is valid
 
2728
    for given encoding.
 
2729
    """
 
2730
    for i in xrange(128, 256):
 
2731
        char = chr(i)
 
2732
        try:
 
2733
            char.decode(encoding)
 
2734
        except UnicodeDecodeError:
 
2735
            return char
 
2736
    return None
 
2737
 
 
2738
 
 
2739
class _FTPServerFeature(Feature):
 
2740
    """Some tests want an FTP Server, check if one is available.
 
2741
 
 
2742
    Right now, the only way this is available is if 'medusa' is installed.
 
2743
    http://www.amk.ca/python/code/medusa.html
 
2744
    """
 
2745
 
 
2746
    def _probe(self):
 
2747
        try:
 
2748
            import bzrlib.tests.ftp_server
 
2749
            return True
 
2750
        except ImportError:
 
2751
            return False
 
2752
 
 
2753
    def feature_name(self):
 
2754
        return 'FTPServer'
 
2755
 
 
2756
FTPServerFeature = _FTPServerFeature()