/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

[merge] update from bzr.dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
28
28
import os
29
29
import re
30
30
import shutil
 
31
import stat
31
32
import sys
32
33
import tempfile
33
34
import unittest
36
37
 
37
38
import bzrlib.branch
38
39
import bzrlib.commands
39
 
from bzrlib.errors import BzrError
 
40
from bzrlib.errors import (BzrError,
 
41
                           FileExists,
 
42
                           UninitializableFormat,
 
43
                           )
40
44
import bzrlib.inventory
 
45
import bzrlib.iterablefile
41
46
import bzrlib.merge3
42
47
import bzrlib.osutils
43
48
import bzrlib.osutils as osutils
44
49
import bzrlib.plugin
45
50
import bzrlib.store
46
51
import bzrlib.trace
 
52
from bzrlib.transport import urlescape
 
53
import bzrlib.transport
 
54
from bzrlib.transport.local import LocalRelpathServer
 
55
from bzrlib.transport.readonly import ReadonlyServer
47
56
from bzrlib.trace import mutter
48
57
from bzrlib.tests.TestUtil import TestLoader, TestSuite
49
58
from bzrlib.tests.treeshape import build_tree_contents
 
59
from bzrlib.workingtree import WorkingTree
 
60
 
 
61
default_transport = LocalRelpathServer
50
62
 
51
63
MODULES_TO_TEST = []
52
64
MODULES_TO_DOCTEST = [
54
66
                      bzrlib.commands,
55
67
                      bzrlib.errors,
56
68
                      bzrlib.inventory,
 
69
                      bzrlib.iterablefile,
57
70
                      bzrlib.merge3,
 
71
                      bzrlib.option,
58
72
                      bzrlib.osutils,
59
 
                      bzrlib.store,
 
73
                      bzrlib.store
60
74
                      ]
61
75
def packages_to_test():
 
76
    """Return a list of packages to test.
 
77
 
 
78
    The packages are not globally imported so that import failures are
 
79
    triggered when running selftest, not when importing the command.
 
80
    """
 
81
    import bzrlib.doc
62
82
    import bzrlib.tests.blackbox
 
83
    import bzrlib.tests.branch_implementations
63
84
    return [
64
 
            bzrlib.tests.blackbox
 
85
            bzrlib.doc,
 
86
            bzrlib.tests.branch_implementations,
65
87
            ]
66
88
 
67
89
 
68
 
class EarlyStoppingTestResultAdapter(object):
69
 
    """An adapter for TestResult to stop at the first first failure or error"""
70
 
 
71
 
    def __init__(self, result):
72
 
        self._result = result
73
 
 
74
 
    def addError(self, test, err):
75
 
        self._result.addError(test, err)
76
 
        self._result.stop()
77
 
 
78
 
    def addFailure(self, test, err):
79
 
        self._result.addFailure(test, err)
80
 
        self._result.stop()
81
 
 
82
 
    def __getattr__(self, name):
83
 
        return getattr(self._result, name)
84
 
 
85
 
    def __setattr__(self, name, value):
86
 
        if name == '_result':
87
 
            object.__setattr__(self, name, value)
88
 
        return setattr(self._result, name, value)
89
 
 
90
 
 
91
90
class _MyResult(unittest._TextTestResult):
92
91
    """Custom TestResult.
93
92
 
94
93
    Shows output in a different format, including displaying runtime for tests.
95
94
    """
 
95
    stop_early = False
96
96
 
97
97
    def _elapsedTime(self):
98
98
        return "%5dms" % (1000 * (time.time() - self._start_time))
132
132
        elif self.dots:
133
133
            self.stream.write('E')
134
134
        self.stream.flush()
 
135
        if self.stop_early:
 
136
            self.stop()
135
137
 
136
138
    def addFailure(self, test, err):
137
139
        unittest.TestResult.addFailure(self, test, err)
140
142
        elif self.dots:
141
143
            self.stream.write('F')
142
144
        self.stream.flush()
 
145
        if self.stop_early:
 
146
            self.stop()
143
147
 
144
148
    def addSuccess(self, test):
145
149
        if self.showAll:
163
167
    def printErrorList(self, flavour, errors):
164
168
        for test, err in errors:
165
169
            self.stream.writeln(self.separator1)
166
 
            self.stream.writeln("%s: %s" % (flavour,self.getDescription(test)))
167
 
            if hasattr(test, '_get_log'):
 
170
            self.stream.writeln("%s: %s" % (flavour, self.getDescription(test)))
 
171
            if getattr(test, '_get_log', None) is not None:
168
172
                print >>self.stream
169
173
                print >>self.stream, \
170
 
                        ('vvvv[log from %s]' % test).ljust(78,'-')
 
174
                        ('vvvv[log from %s]' % test.id()).ljust(78,'-')
171
175
                print >>self.stream, test._get_log()
172
176
                print >>self.stream, \
173
 
                        ('^^^^[log from %s]' % test).ljust(78,'-')
 
177
                        ('^^^^[log from %s]' % test.id()).ljust(78,'-')
174
178
            self.stream.writeln(self.separator2)
175
179
            self.stream.writeln("%s" % err)
176
180
 
180
184
 
181
185
    def _makeResult(self):
182
186
        result = _MyResult(self.stream, self.descriptions, self.verbosity)
183
 
        if self.stop_on_failure:
184
 
            result = EarlyStoppingTestResultAdapter(result)
 
187
        result.stop_early = self.stop_on_failure
185
188
        return result
186
189
 
187
190
 
231
234
    _log_file_name = None
232
235
    _log_contents = ''
233
236
 
 
237
    def __init__(self, methodName='testMethod'):
 
238
        super(TestCase, self).__init__(methodName)
 
239
        self._cleanups = []
 
240
 
234
241
    def setUp(self):
235
242
        unittest.TestCase.setUp(self)
236
 
        self._cleanups = []
237
243
        self._cleanEnvironment()
238
244
        bzrlib.trace.disable_default_logging()
239
245
        self._startLogFile()
279
285
            raise AssertionError('pattern "%s" not found in "%s"'
280
286
                    % (needle_re, haystack))
281
287
 
282
 
    def AssertSubset(self, sublist, superlist):
 
288
    def assertSubset(self, sublist, superlist):
283
289
        """Assert that every entry in sublist is present in superlist."""
284
290
        missing = []
285
291
        for entry in sublist:
289
295
            raise AssertionError("value(s) %r not present in container %r" % 
290
296
                                 (missing, superlist))
291
297
 
 
298
    def assertIs(self, left, right):
 
299
        if not (left is right):
 
300
            raise AssertionError("%r is not %r." % (left, right))
 
301
 
 
302
    def assertTransportMode(self, transport, path, mode):
 
303
        """Fail if a path does not have mode mode.
 
304
        
 
305
        If modes are not supported on this platform, the test is skipped.
 
306
        """
 
307
        if sys.platform == 'win32':
 
308
            return
 
309
        path_stat = transport.stat(path)
 
310
        actual_mode = stat.S_IMODE(path_stat.st_mode)
 
311
        self.assertEqual(mode, actual_mode,
 
312
            'mode of %r incorrect (%o != %o)' % (path, mode, actual_mode))
 
313
 
292
314
    def _startLogFile(self):
293
315
        """Send bzr and test log messages to a temporary file.
294
316
 
297
319
        fileno, name = tempfile.mkstemp(suffix='.log', prefix='testbzr')
298
320
        encoder, decoder, stream_reader, stream_writer = codecs.lookup('UTF-8')
299
321
        self._log_file = stream_writer(os.fdopen(fileno, 'w+'))
300
 
        bzrlib.trace.enable_test_log(self._log_file)
 
322
        self._log_nonce = bzrlib.trace.enable_test_log(self._log_file)
301
323
        self._log_file_name = name
302
324
        self.addCleanup(self._finishLogFile)
303
325
 
306
328
 
307
329
        Read contents into memory, close, and delete.
308
330
        """
309
 
        bzrlib.trace.disable_test_log()
 
331
        bzrlib.trace.disable_test_log(self._log_nonce)
310
332
        self._log_file.seek(0)
311
333
        self._log_contents = self._log_file.read()
312
334
        self._log_file.close()
367
389
 
368
390
        This should only be called from TestCase.tearDown.
369
391
        """
 
392
        # TODO: Perhaps this should keep running cleanups even if 
 
393
        # one of them fails?
370
394
        for cleanup_fn in reversed(self._cleanups):
371
395
            cleanup_fn()
372
396
 
473
497
        if stdin is None:
474
498
            stdin = StringIO("")
475
499
        if stdout is None:
476
 
            if hasattr(self, "_log_file"):
 
500
            if getattr(self, "_log_file", None) is not None:
477
501
                stdout = self._log_file
478
502
            else:
479
503
                stdout = StringIO()
480
504
        if stderr is None:
481
 
            if hasattr(self, "_log_file"):
 
505
            if getattr(self, "_log_file", None is not None):
482
506
                stderr = self._log_file
483
507
            else:
484
508
                stderr = StringIO()
560
584
            os.chdir(_currentdir)
561
585
        self.addCleanup(_leaveDirectory)
562
586
        
563
 
    def build_tree(self, shape, line_endings='native'):
 
587
    def build_tree(self, shape, line_endings='native', transport=None):
564
588
        """Build a test tree according to a pattern.
565
589
 
566
590
        shape is a sequence of file specifications.  If the final
571
595
                             in binary mode, exact contents are written
572
596
                             in native mode, the line endings match the
573
597
                             default platform endings.
 
598
 
 
599
        :param transport: A transport to write to, for building trees on 
 
600
                          VFS's. If the transport is readonly or None,
 
601
                          "." is opened automatically.
574
602
        """
575
603
        # XXX: It's OK to just create them using forward slashes on windows?
 
604
        if transport is None or transport.is_readonly():
 
605
            transport = bzrlib.transport.get_transport(".")
576
606
        for name in shape:
577
607
            self.assert_(isinstance(name, basestring))
578
608
            if name[-1] == '/':
579
 
                os.mkdir(name[:-1])
 
609
                transport.mkdir(urlescape(name[:-1]))
580
610
            else:
581
611
                if line_endings == 'binary':
582
 
                    f = file(name, 'wb')
 
612
                    end = '\n'
583
613
                elif line_endings == 'native':
584
 
                    f = file(name, 'wt')
 
614
                    end = os.linesep
585
615
                else:
586
616
                    raise BzrError('Invalid line ending request %r' % (line_endings,))
587
 
                print >>f, "contents of", name
588
 
                f.close()
 
617
                content = "contents of %s%s" % (name, end)
 
618
                transport.put(urlescape(name), StringIO(content))
589
619
 
590
620
    def build_tree_contents(self, shape):
591
621
        build_tree_contents(shape)
604
634
        self.assertEqualDiff(content, open(path, 'r').read())
605
635
 
606
636
 
 
637
class TestCaseWithTransport(TestCaseInTempDir):
 
638
    """A test case that provides get_url and get_readonly_url facilities.
 
639
 
 
640
    These back onto two transport servers, one for readonly access and one for
 
641
    read write access.
 
642
 
 
643
    If no explicit class is provided for readonly access, a
 
644
    ReadonlyTransportDecorator is used instead which allows the use of non disk
 
645
    based read write transports.
 
646
 
 
647
    If an explicit class is provided for readonly access, that server and the 
 
648
    readwrite one must both define get_url() as resolving to os.getcwd().
 
649
    """
 
650
 
 
651
    def __init__(self, methodName='testMethod'):
 
652
        super(TestCaseWithTransport, self).__init__(methodName)
 
653
        self.__readonly_server = None
 
654
        self.__server = None
 
655
        self.transport_server = default_transport
 
656
        self.transport_readonly_server = None
 
657
 
 
658
    def get_readonly_url(self, relpath=None):
 
659
        """Get a URL for the readonly transport.
 
660
 
 
661
        This will either be backed by '.' or a decorator to the transport 
 
662
        used by self.get_url()
 
663
        relpath provides for clients to get a path relative to the base url.
 
664
        These should only be downwards relative, not upwards.
 
665
        """
 
666
        if self.__readonly_server is None:
 
667
            if self.transport_readonly_server is None:
 
668
                # readonly decorator requested
 
669
                # bring up the server
 
670
                self.get_url()
 
671
                self.__readonly_server = ReadonlyServer()
 
672
                self.__readonly_server.setUp(self.__server)
 
673
            else:
 
674
                self.__readonly_server = self.transport_readonly_server()
 
675
                self.__readonly_server.setUp()
 
676
            self.addCleanup(self.__readonly_server.tearDown)
 
677
        base = self.__readonly_server.get_url()
 
678
        if relpath is not None:
 
679
            if not base.endswith('/'):
 
680
                base = base + '/'
 
681
            base = base + relpath
 
682
        return base
 
683
 
 
684
    def get_url(self, relpath=None):
 
685
        """Get a URL for the readwrite transport.
 
686
 
 
687
        This will either be backed by '.' or to an equivalent non-file based
 
688
        facility.
 
689
        relpath provides for clients to get a path relative to the base url.
 
690
        These should only be downwards relative, not upwards.
 
691
        """
 
692
        if self.__server is None:
 
693
            self.__server = self.transport_server()
 
694
            self.__server.setUp()
 
695
            self.addCleanup(self.__server.tearDown)
 
696
        base = self.__server.get_url()
 
697
        if relpath is not None and relpath != '.':
 
698
            if not base.endswith('/'):
 
699
                base = base + '/'
 
700
            base = base + relpath
 
701
        return base
 
702
 
 
703
    def make_branch(self, relpath):
 
704
        """Create a branch on the transport at relpath."""
 
705
        try:
 
706
            url = self.get_url(relpath)
 
707
            segments = relpath.split('/')
 
708
            if segments and segments[-1] not in ('', '.'):
 
709
                parent = self.get_url('/'.join(segments[:-1]))
 
710
                t = bzrlib.transport.get_transport(parent)
 
711
                try:
 
712
                    t.mkdir(segments[-1])
 
713
                except FileExists:
 
714
                    pass
 
715
            return bzrlib.branch.Branch.create(url)
 
716
        except UninitializableFormat:
 
717
            raise TestSkipped("Format %s is not initializable.")
 
718
 
 
719
    def make_branch_and_tree(self, relpath):
 
720
        """Create a branch on the transport and a tree locally.
 
721
 
 
722
        Returns the tree.
 
723
        """
 
724
        b = self.make_branch(relpath)
 
725
        return WorkingTree.create(b, relpath)
 
726
 
 
727
 
 
728
class ChrootedTestCase(TestCaseWithTransport):
 
729
    """A support class that provides readonly urls outside the local namespace.
 
730
 
 
731
    This is done by checking if self.transport_server is a MemoryServer. if it
 
732
    is then we are chrooted already, if it is not then an HttpServer is used
 
733
    for readonly urls.
 
734
 
 
735
    TODO RBC 20060127: make this an option to TestCaseWithTransport so it can
 
736
                       be used without needed to redo it when a different 
 
737
                       subclass is in use ?
 
738
    """
 
739
 
 
740
    def setUp(self):
 
741
        super(ChrootedTestCase, self).setUp()
 
742
        if not self.transport_server == bzrlib.transport.memory.MemoryServer:
 
743
            self.transport_readonly_server = bzrlib.transport.http.HttpServer
 
744
 
 
745
 
607
746
def filter_suite_by_re(suite, pattern):
608
747
    result = TestSuite()
609
748
    filter_re = re.compile(pattern)
614
753
 
615
754
 
616
755
def run_suite(suite, name='test', verbose=False, pattern=".*",
617
 
              stop_on_failure=False, keep_output=False):
 
756
              stop_on_failure=False, keep_output=False,
 
757
              transport=None):
618
758
    TestCaseInTempDir._TEST_NAME = name
619
759
    if verbose:
620
760
        verbosity = 2
639
779
 
640
780
 
641
781
def selftest(verbose=False, pattern=".*", stop_on_failure=True,
642
 
             keep_output=False):
 
782
             keep_output=False,
 
783
             transport=None):
643
784
    """Run the whole test suite under the enhanced runner"""
644
 
    return run_suite(test_suite(), 'testbzr', verbose=verbose, pattern=pattern,
645
 
                     stop_on_failure=stop_on_failure, keep_output=keep_output)
 
785
    global default_transport
 
786
    if transport is None:
 
787
        transport = default_transport
 
788
    old_transport = default_transport
 
789
    default_transport = transport
 
790
    suite = test_suite()
 
791
    try:
 
792
        return run_suite(suite, 'testbzr', verbose=verbose, pattern=pattern,
 
793
                     stop_on_failure=stop_on_failure, keep_output=keep_output,
 
794
                     transport=transport)
 
795
    finally:
 
796
        default_transport = old_transport
 
797
 
646
798
 
647
799
 
648
800
def test_suite():
663
815
                   'bzrlib.tests.test_commit_merge',
664
816
                   'bzrlib.tests.test_config',
665
817
                   'bzrlib.tests.test_conflicts',
 
818
                   'bzrlib.tests.test_decorators',
666
819
                   'bzrlib.tests.test_diff',
 
820
                   'bzrlib.tests.test_doc_generate',
667
821
                   'bzrlib.tests.test_fetch',
 
822
                   'bzrlib.tests.test_fileid_involved',
668
823
                   'bzrlib.tests.test_gpg',
669
824
                   'bzrlib.tests.test_graph',
670
825
                   'bzrlib.tests.test_hashcache',
671
826
                   'bzrlib.tests.test_http',
672
827
                   'bzrlib.tests.test_identitymap',
673
828
                   'bzrlib.tests.test_inv',
 
829
                   'bzrlib.tests.test_lockable_files',
674
830
                   'bzrlib.tests.test_log',
675
831
                   'bzrlib.tests.test_merge',
676
832
                   'bzrlib.tests.test_merge3',
683
839
                   'bzrlib.tests.test_parent',
684
840
                   'bzrlib.tests.test_permissions',
685
841
                   'bzrlib.tests.test_plugins',
686
 
                   'bzrlib.tests.test_remove',
687
842
                   'bzrlib.tests.test_revision',
688
843
                   'bzrlib.tests.test_revisionnamespaces',
689
844
                   'bzrlib.tests.test_revprops',
695
850
                   'bzrlib.tests.test_sftp_transport',
696
851
                   'bzrlib.tests.test_smart_add',
697
852
                   'bzrlib.tests.test_source',
698
 
                   'bzrlib.tests.test_status',
699
853
                   'bzrlib.tests.test_store',
700
854
                   'bzrlib.tests.test_symbol_versioning',
701
855
                   'bzrlib.tests.test_testament',
711
865
                   'bzrlib.tests.test_workingtree',
712
866
                   'bzrlib.tests.test_xml',
713
867
                   ]
 
868
    test_transport_implementations = [
 
869
        'bzrlib.tests.test_transport_implementations']
714
870
 
715
871
    TestCase.BZRPATH = osutils.pathjoin(
716
872
            osutils.realpath(osutils.dirname(bzrlib.__path__[0])), 'bzr')
723
879
    # actually wrong, just "no such module".  We should probably override that
724
880
    # class, but for the moment just load them ourselves. (mbp 20051202)
725
881
    loader = TestLoader()
 
882
    from bzrlib.transport import TransportTestProviderAdapter
 
883
    adapter = TransportTestProviderAdapter()
 
884
    adapt_modules(test_transport_implementations, adapter, loader, suite)
726
885
    for mod_name in testmod_names:
727
886
        mod = _load_module_by_name(mod_name)
728
887
        suite.addTest(loader.loadTestsFromModule(mod))
733
892
    for m in (MODULES_TO_DOCTEST):
734
893
        suite.addTest(DocTestSuite(m))
735
894
    for name, plugin in bzrlib.plugin.all_plugins().items():
736
 
        if hasattr(plugin, 'test_suite'):
 
895
        if getattr(plugin, 'test_suite', None) is not None:
737
896
            suite.addTest(plugin.test_suite())
738
897
    return suite
739
898
 
740
899
 
 
900
def adapt_modules(mods_list, adapter, loader, suite):
 
901
    """Adapt the modules in mods_list using adapter and add to suite."""
 
902
    for mod_name in mods_list:
 
903
        mod = _load_module_by_name(mod_name)
 
904
        for test in iter_suite_tests(loader.loadTestsFromModule(mod)):
 
905
            suite.addTests(adapter.adapt(test))
 
906
 
 
907
 
741
908
def _load_module_by_name(mod_name):
742
909
    parts = mod_name.split('.')
743
910
    module = __import__(mod_name)