~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/__init__.py

[merge] jam-integration 1527, including branch-formats, help text, misc bug fixes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
37
37
 
38
38
import bzrlib.branch
39
39
import bzrlib.commands
40
 
from bzrlib.errors import BzrError
 
40
from bzrlib.errors import (BzrError,
 
41
                           FileExists,
 
42
                           UninitializableFormat,
 
43
                           )
41
44
import bzrlib.inventory
42
45
import bzrlib.iterablefile
43
46
import bzrlib.merge3
47
50
import bzrlib.store
48
51
import bzrlib.trace
49
52
from bzrlib.transport import urlescape
 
53
import bzrlib.transport
 
54
from bzrlib.transport.local import LocalRelpathServer
 
55
from bzrlib.transport.readonly import ReadonlyServer
50
56
from bzrlib.trace import mutter
51
57
from bzrlib.tests.TestUtil import TestLoader, TestSuite
52
58
from bzrlib.tests.treeshape import build_tree_contents
 
59
from bzrlib.workingtree import WorkingTree
 
60
 
 
61
default_transport = LocalRelpathServer
53
62
 
54
63
MODULES_TO_TEST = []
55
64
MODULES_TO_DOCTEST = [
64
73
                      bzrlib.store
65
74
                      ]
66
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
67
82
    import bzrlib.tests.blackbox
 
83
    import bzrlib.tests.branch_implementations
68
84
    return [
69
 
            bzrlib.tests.blackbox
 
85
            bzrlib.doc,
 
86
            bzrlib.tests.branch_implementations,
70
87
            ]
71
88
 
72
89
 
73
 
class EarlyStoppingTestResultAdapter(object):
74
 
    """An adapter for TestResult to stop at the first first failure or error"""
75
 
 
76
 
    def __init__(self, result):
77
 
        self._result = result
78
 
 
79
 
    def addError(self, test, err):
80
 
        self._result.addError(test, err)
81
 
        self._result.stop()
82
 
 
83
 
    def addFailure(self, test, err):
84
 
        self._result.addFailure(test, err)
85
 
        self._result.stop()
86
 
 
87
 
    def __getattr__(self, name):
88
 
        return getattr(self._result, name)
89
 
 
90
 
    def __setattr__(self, name, value):
91
 
        if name == '_result':
92
 
            object.__setattr__(self, name, value)
93
 
        return setattr(self._result, name, value)
94
 
 
95
 
 
96
90
class _MyResult(unittest._TextTestResult):
97
91
    """Custom TestResult.
98
92
 
99
93
    Shows output in a different format, including displaying runtime for tests.
100
94
    """
 
95
    stop_early = False
101
96
 
102
97
    def _elapsedTime(self):
103
98
        return "%5dms" % (1000 * (time.time() - self._start_time))
137
132
        elif self.dots:
138
133
            self.stream.write('E')
139
134
        self.stream.flush()
 
135
        if self.stop_early:
 
136
            self.stop()
140
137
 
141
138
    def addFailure(self, test, err):
142
139
        unittest.TestResult.addFailure(self, test, err)
145
142
        elif self.dots:
146
143
            self.stream.write('F')
147
144
        self.stream.flush()
 
145
        if self.stop_early:
 
146
            self.stop()
148
147
 
149
148
    def addSuccess(self, test):
150
149
        if self.showAll:
169
168
        for test, err in errors:
170
169
            self.stream.writeln(self.separator1)
171
170
            self.stream.writeln("%s: %s" % (flavour, self.getDescription(test)))
172
 
            if hasattr(test, '_get_log'):
 
171
            if getattr(test, '_get_log', None) is not None:
173
172
                print >>self.stream
174
173
                print >>self.stream, \
175
174
                        ('vvvv[log from %s]' % test.id()).ljust(78,'-')
185
184
 
186
185
    def _makeResult(self):
187
186
        result = _MyResult(self.stream, self.descriptions, self.verbosity)
188
 
        if self.stop_on_failure:
189
 
            result = EarlyStoppingTestResultAdapter(result)
 
187
        result.stop_early = self.stop_on_failure
190
188
        return result
191
189
 
192
190
 
263
261
    _log_file_name = None
264
262
    _log_contents = ''
265
263
 
 
264
    def __init__(self, methodName='testMethod'):
 
265
        super(TestCase, self).__init__(methodName)
 
266
        self._cleanups = []
 
267
 
266
268
    def setUp(self):
267
269
        unittest.TestCase.setUp(self)
268
 
        self._cleanups = []
269
270
        self._cleanEnvironment()
270
271
        bzrlib.trace.disable_default_logging()
271
272
        self._startLogFile()
345
346
        fileno, name = tempfile.mkstemp(suffix='.log', prefix='testbzr')
346
347
        encoder, decoder, stream_reader, stream_writer = codecs.lookup('UTF-8')
347
348
        self._log_file = stream_writer(os.fdopen(fileno, 'w+'))
348
 
        bzrlib.trace.enable_test_log(self._log_file)
 
349
        self._log_nonce = bzrlib.trace.enable_test_log(self._log_file)
349
350
        self._log_file_name = name
350
351
        self.addCleanup(self._finishLogFile)
351
352
 
354
355
 
355
356
        Read contents into memory, close, and delete.
356
357
        """
357
 
        bzrlib.trace.disable_test_log()
 
358
        bzrlib.trace.disable_test_log(self._log_nonce)
358
359
        self._log_file.seek(0)
359
360
        self._log_contents = self._log_file.read()
360
361
        self._log_file.close()
541
542
        if stdin is None:
542
543
            stdin = StringIO("")
543
544
        if stdout is None:
544
 
            if hasattr(self, "_log_file"):
 
545
            if getattr(self, "_log_file", None) is not None:
545
546
                stdout = self._log_file
546
547
            else:
547
548
                stdout = StringIO()
548
549
        if stderr is None:
549
 
            if hasattr(self, "_log_file"):
 
550
            if getattr(self, "_log_file", None is not None):
550
551
                stderr = self._log_file
551
552
            else:
552
553
                stderr = StringIO()
678
679
        self.assertEqualDiff(content, open(path, 'r').read())
679
680
 
680
681
 
 
682
class TestCaseWithTransport(TestCaseInTempDir):
 
683
    """A test case that provides get_url and get_readonly_url facilities.
 
684
 
 
685
    These back onto two transport servers, one for readonly access and one for
 
686
    read write access.
 
687
 
 
688
    If no explicit class is provided for readonly access, a
 
689
    ReadonlyTransportDecorator is used instead which allows the use of non disk
 
690
    based read write transports.
 
691
 
 
692
    If an explicit class is provided for readonly access, that server and the 
 
693
    readwrite one must both define get_url() as resolving to os.getcwd().
 
694
    """
 
695
 
 
696
    def __init__(self, methodName='testMethod'):
 
697
        super(TestCaseWithTransport, self).__init__(methodName)
 
698
        self.__readonly_server = None
 
699
        self.__server = None
 
700
        self.transport_server = default_transport
 
701
        self.transport_readonly_server = None
 
702
 
 
703
    def get_readonly_url(self, relpath=None):
 
704
        """Get a URL for the readonly transport.
 
705
 
 
706
        This will either be backed by '.' or a decorator to the transport 
 
707
        used by self.get_url()
 
708
        relpath provides for clients to get a path relative to the base url.
 
709
        These should only be downwards relative, not upwards.
 
710
        """
 
711
        if self.__readonly_server is None:
 
712
            if self.transport_readonly_server is None:
 
713
                # readonly decorator requested
 
714
                # bring up the server
 
715
                self.get_url()
 
716
                self.__readonly_server = ReadonlyServer()
 
717
                self.__readonly_server.setUp(self.__server)
 
718
            else:
 
719
                self.__readonly_server = self.transport_readonly_server()
 
720
                self.__readonly_server.setUp()
 
721
            self.addCleanup(self.__readonly_server.tearDown)
 
722
        base = self.__readonly_server.get_url()
 
723
        if relpath is not None:
 
724
            if not base.endswith('/'):
 
725
                base = base + '/'
 
726
            base = base + relpath
 
727
        return base
 
728
 
 
729
    def get_url(self, relpath=None):
 
730
        """Get a URL for the readwrite transport.
 
731
 
 
732
        This will either be backed by '.' or to an equivalent non-file based
 
733
        facility.
 
734
        relpath provides for clients to get a path relative to the base url.
 
735
        These should only be downwards relative, not upwards.
 
736
        """
 
737
        if self.__server is None:
 
738
            self.__server = self.transport_server()
 
739
            self.__server.setUp()
 
740
            self.addCleanup(self.__server.tearDown)
 
741
        base = self.__server.get_url()
 
742
        if relpath is not None and relpath != '.':
 
743
            if not base.endswith('/'):
 
744
                base = base + '/'
 
745
            base = base + relpath
 
746
        return base
 
747
 
 
748
    def make_branch(self, relpath):
 
749
        """Create a branch on the transport at relpath."""
 
750
        try:
 
751
            url = self.get_url(relpath)
 
752
            segments = relpath.split('/')
 
753
            if segments and segments[-1] not in ('', '.'):
 
754
                parent = self.get_url('/'.join(segments[:-1]))
 
755
                t = bzrlib.transport.get_transport(parent)
 
756
                try:
 
757
                    t.mkdir(segments[-1])
 
758
                except FileExists:
 
759
                    pass
 
760
            return bzrlib.branch.Branch.create(url)
 
761
        except UninitializableFormat:
 
762
            raise TestSkipped("Format %s is not initializable.")
 
763
 
 
764
    def make_branch_and_tree(self, relpath):
 
765
        """Create a branch on the transport and a tree locally.
 
766
 
 
767
        Returns the tree.
 
768
        """
 
769
        b = self.make_branch(relpath)
 
770
        return WorkingTree.create(b, relpath)
 
771
 
 
772
 
 
773
class ChrootedTestCase(TestCaseWithTransport):
 
774
    """A support class that provides readonly urls outside the local namespace.
 
775
 
 
776
    This is done by checking if self.transport_server is a MemoryServer. if it
 
777
    is then we are chrooted already, if it is not then an HttpServer is used
 
778
    for readonly urls.
 
779
 
 
780
    TODO RBC 20060127: make this an option to TestCaseWithTransport so it can
 
781
                       be used without needed to redo it when a different 
 
782
                       subclass is in use ?
 
783
    """
 
784
 
 
785
    def setUp(self):
 
786
        super(ChrootedTestCase, self).setUp()
 
787
        if not self.transport_server == bzrlib.transport.memory.MemoryServer:
 
788
            self.transport_readonly_server = bzrlib.transport.http.HttpServer
 
789
 
 
790
 
681
791
def filter_suite_by_re(suite, pattern):
682
792
    result = TestSuite()
683
793
    filter_re = re.compile(pattern)
688
798
 
689
799
 
690
800
def run_suite(suite, name='test', verbose=False, pattern=".*",
691
 
              stop_on_failure=False, keep_output=False):
 
801
              stop_on_failure=False, keep_output=False,
 
802
              transport=None):
692
803
    TestCaseInTempDir._TEST_NAME = name
693
804
    if verbose:
694
805
        verbosity = 2
713
824
 
714
825
 
715
826
def selftest(verbose=False, pattern=".*", stop_on_failure=True,
716
 
             keep_output=False):
 
827
             keep_output=False,
 
828
             transport=None):
717
829
    """Run the whole test suite under the enhanced runner"""
718
 
    return run_suite(test_suite(), 'testbzr', verbose=verbose, pattern=pattern,
719
 
                     stop_on_failure=stop_on_failure, keep_output=keep_output)
 
830
    global default_transport
 
831
    if transport is None:
 
832
        transport = default_transport
 
833
    old_transport = default_transport
 
834
    default_transport = transport
 
835
    suite = test_suite()
 
836
    try:
 
837
        return run_suite(suite, 'testbzr', verbose=verbose, pattern=pattern,
 
838
                     stop_on_failure=stop_on_failure, keep_output=keep_output,
 
839
                     transport=transport)
 
840
    finally:
 
841
        default_transport = old_transport
 
842
 
720
843
 
721
844
 
722
845
def test_suite():
737
860
                   'bzrlib.tests.test_commit_merge',
738
861
                   'bzrlib.tests.test_config',
739
862
                   'bzrlib.tests.test_conflicts',
 
863
                   'bzrlib.tests.test_decorators',
740
864
                   'bzrlib.tests.test_diff',
741
 
                   'bzrlib.tests.test_decorators',
 
865
                   'bzrlib.tests.test_doc_generate',
742
866
                   'bzrlib.tests.test_fetch',
743
867
                   'bzrlib.tests.test_fileid_involved',
744
868
                   'bzrlib.tests.test_glob_matcher',
761
885
                   'bzrlib.tests.test_parent',
762
886
                   'bzrlib.tests.test_permissions',
763
887
                   'bzrlib.tests.test_plugins',
764
 
                   'bzrlib.tests.test_remove',
765
888
                   'bzrlib.tests.test_revision',
766
889
                   'bzrlib.tests.test_revisionnamespaces',
767
890
                   'bzrlib.tests.test_revprops',
773
896
                   'bzrlib.tests.test_sftp_transport',
774
897
                   'bzrlib.tests.test_smart_add',
775
898
                   'bzrlib.tests.test_source',
776
 
                   'bzrlib.tests.test_status',
777
899
                   'bzrlib.tests.test_store',
778
900
                   'bzrlib.tests.test_symbol_versioning',
779
901
                   'bzrlib.tests.test_testament',
805
927
    loader = TestLoader()
806
928
    from bzrlib.transport import TransportTestProviderAdapter
807
929
    adapter = TransportTestProviderAdapter()
808
 
    for mod_name in test_transport_implementations:
809
 
        mod = _load_module_by_name(mod_name)
810
 
        for test in iter_suite_tests(loader.loadTestsFromModule(mod)):
811
 
            suite.addTests(adapter.adapt(test))
 
930
    adapt_modules(test_transport_implementations, adapter, loader, suite)
812
931
    for mod_name in testmod_names:
813
932
        mod = _load_module_by_name(mod_name)
814
933
        suite.addTest(loader.loadTestsFromModule(mod))
819
938
    for m in (MODULES_TO_DOCTEST):
820
939
        suite.addTest(DocTestSuite(m))
821
940
    for name, plugin in bzrlib.plugin.all_plugins().items():
822
 
        if hasattr(plugin, 'test_suite'):
 
941
        if getattr(plugin, 'test_suite', None) is not None:
823
942
            suite.addTest(plugin.test_suite())
824
943
    return suite
825
944
 
826
945
 
 
946
def adapt_modules(mods_list, adapter, loader, suite):
 
947
    """Adapt the modules in mods_list using adapter and add to suite."""
 
948
    for mod_name in mods_list:
 
949
        mod = _load_module_by_name(mod_name)
 
950
        for test in iter_suite_tests(loader.loadTestsFromModule(mod)):
 
951
            suite.addTests(adapter.adapt(test))
 
952
 
 
953
 
827
954
def _load_module_by_name(mod_name):
828
955
    parts = mod_name.split('.')
829
956
    module = __import__(mod_name)