~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/__init__.py

  • Committer: Martin Pool
  • Date: 2006-02-22 04:29:54 UTC
  • mfrom: (1566 +trunk)
  • mto: This revision was merged to the branch mainline in revision 1569.
  • Revision ID: mbp@sourcefrog.net-20060222042954-60333f08dd56a646
[merge] from bzr.dev before integration
Fix undefined ordering in sign_my_revisions breaking tests

Show diffs side-by-side

added added

removed removed

Lines of Context:
21
21
# little as possible, so this should be used rarely if it's added at all.
22
22
# (Suggestion from j-a-meinel, 2005-11-24)
23
23
 
24
 
# NOTE: Some classes in here use camelCaseNaming() rather than
25
 
# underscore_naming().  That's for consistency with unittest; it's not the
26
 
# general style of bzrlib.  Please continue that consistency when adding e.g.
27
 
# new assertFoo() methods.
28
 
 
29
24
import codecs
30
25
from cStringIO import StringIO
31
26
import difflib
32
 
import doctest
33
27
import errno
34
28
import logging
35
29
import os
36
30
import re
37
 
import shlex
 
31
import shutil
38
32
import stat
39
 
from subprocess import Popen, PIPE
40
33
import sys
41
34
import tempfile
42
35
import unittest
46
39
import bzrlib.branch
47
40
import bzrlib.bzrdir as bzrdir
48
41
import bzrlib.commands
49
 
import bzrlib.bundle.serializer
50
42
import bzrlib.errors as errors
51
43
import bzrlib.inventory
52
44
import bzrlib.iterablefile
53
45
import bzrlib.lockdir
54
 
try:
55
 
    import bzrlib.lsprof
56
 
except ImportError:
57
 
    # lsprof not available
58
 
    pass
59
 
from bzrlib.merge import merge_inner
60
46
import bzrlib.merge3
61
47
import bzrlib.osutils
62
48
import bzrlib.osutils as osutils
63
49
import bzrlib.plugin
64
 
import bzrlib.progress as progress
65
 
from bzrlib.revision import common_ancestor
66
50
import bzrlib.store
67
51
import bzrlib.trace
68
 
from bzrlib.transport import get_transport
 
52
from bzrlib.transport import urlescape, get_transport
69
53
import bzrlib.transport
70
54
from bzrlib.transport.local import LocalRelpathServer
71
55
from bzrlib.transport.readonly import ReadonlyServer
72
56
from bzrlib.trace import mutter
73
 
from bzrlib.tests import TestUtil
74
 
from bzrlib.tests.TestUtil import (
75
 
                          TestSuite,
76
 
                          TestLoader,
77
 
                          )
 
57
from bzrlib.tests.TestUtil import TestLoader, TestSuite
78
58
from bzrlib.tests.treeshape import build_tree_contents
79
 
import bzrlib.urlutils as urlutils
80
59
from bzrlib.workingtree import WorkingTree, WorkingTreeFormat2
81
60
 
82
61
default_transport = LocalRelpathServer
84
63
MODULES_TO_TEST = []
85
64
MODULES_TO_DOCTEST = [
86
65
                      bzrlib.branch,
87
 
                      bzrlib.bundle.serializer,
88
66
                      bzrlib.commands,
89
67
                      bzrlib.errors,
90
68
                      bzrlib.inventory,
95
73
                      bzrlib.osutils,
96
74
                      bzrlib.store
97
75
                      ]
98
 
 
99
 
 
100
76
def packages_to_test():
101
77
    """Return a list of packages to test.
102
78
 
108
84
    import bzrlib.tests.branch_implementations
109
85
    import bzrlib.tests.bzrdir_implementations
110
86
    import bzrlib.tests.interrepository_implementations
111
 
    import bzrlib.tests.interversionedfile_implementations
112
87
    import bzrlib.tests.repository_implementations
113
 
    import bzrlib.tests.revisionstore_implementations
114
88
    import bzrlib.tests.workingtree_implementations
115
89
    return [
116
90
            bzrlib.doc,
118
92
            bzrlib.tests.branch_implementations,
119
93
            bzrlib.tests.bzrdir_implementations,
120
94
            bzrlib.tests.interrepository_implementations,
121
 
            bzrlib.tests.interversionedfile_implementations,
122
95
            bzrlib.tests.repository_implementations,
123
 
            bzrlib.tests.revisionstore_implementations,
124
96
            bzrlib.tests.workingtree_implementations,
125
97
            ]
126
98
 
131
103
    Shows output in a different format, including displaying runtime for tests.
132
104
    """
133
105
    stop_early = False
134
 
    
135
 
    def __init__(self, stream, descriptions, verbosity, pb=None):
136
 
        unittest._TextTestResult.__init__(self, stream, descriptions, verbosity)
137
 
        self.pb = pb
138
 
    
139
 
    def extractBenchmarkTime(self, testCase):
140
 
        """Add a benchmark time for the current test case."""
141
 
        self._benchmarkTime = getattr(testCase, "_benchtime", None)
142
 
    
143
 
    def _elapsedTestTimeString(self):
144
 
        """Return a time string for the overall time the current test has taken."""
145
 
        return self._formatTime(time.time() - self._start_time)
146
 
 
147
 
    def _testTimeString(self):
148
 
        if self._benchmarkTime is not None:
149
 
            return "%s/%s" % (
150
 
                self._formatTime(self._benchmarkTime),
151
 
                self._elapsedTestTimeString())
152
 
        else:
153
 
            return "      %s" % self._elapsedTestTimeString()
154
 
 
155
 
    def _formatTime(self, seconds):
156
 
        """Format seconds as milliseconds with leading spaces."""
157
 
        return "%5dms" % (1000 * seconds)
158
 
 
159
 
    def _ellipsise_unimportant_words(self, a_string, final_width,
160
 
                                   keep_start=False):
161
 
        """Add ellipses (sp?) for overly long strings.
162
 
        
163
 
        :param keep_start: If true preserve the start of a_string rather
164
 
                           than the end of it.
165
 
        """
166
 
        if keep_start:
167
 
            if len(a_string) > final_width:
168
 
                result = a_string[:final_width-3] + '...'
169
 
            else:
170
 
                result = a_string
171
 
        else:
172
 
            if len(a_string) > final_width:
173
 
                result = '...' + a_string[3-final_width:]
174
 
            else:
175
 
                result = a_string
176
 
        return result.ljust(final_width)
 
106
 
 
107
    def _elapsedTime(self):
 
108
        return "%5dms" % (1000 * (time.time() - self._start_time))
177
109
 
178
110
    def startTest(self, test):
179
111
        unittest.TestResult.startTest(self, test)
181
113
        # the beginning, but in an id, the important words are
182
114
        # at the end
183
115
        SHOW_DESCRIPTIONS = False
184
 
 
185
 
        if not self.showAll and self.dots and self.pb is not None:
186
 
            final_width = 13
187
 
        else:
188
 
            final_width = osutils.terminal_width()
189
 
            final_width = final_width - 15 - 8
190
 
        what = None
191
 
        if SHOW_DESCRIPTIONS:
192
 
            what = test.shortDescription()
193
 
            if what:
194
 
                what = self._ellipsise_unimportant_words(what, final_width, keep_start=True)
195
 
        if what is None:
196
 
            what = test.id()
197
 
            if what.startswith('bzrlib.tests.'):
198
 
                what = what[13:]
199
 
            what = self._ellipsise_unimportant_words(what, final_width)
200
116
        if self.showAll:
 
117
            width = osutils.terminal_width()
 
118
            name_width = width - 15
 
119
            what = None
 
120
            if SHOW_DESCRIPTIONS:
 
121
                what = test.shortDescription()
 
122
                if what:
 
123
                    if len(what) > name_width:
 
124
                        what = what[:name_width-3] + '...'
 
125
            if what is None:
 
126
                what = test.id()
 
127
                if what.startswith('bzrlib.tests.'):
 
128
                    what = what[13:]
 
129
                if len(what) > name_width:
 
130
                    what = '...' + what[3-name_width:]
 
131
            what = what.ljust(name_width)
201
132
            self.stream.write(what)
202
 
        elif self.dots and self.pb is not None:
203
 
            self.pb.update(what, self.testsRun - 1, None)
204
133
        self.stream.flush()
205
 
        self._recordTestStartTime()
206
 
 
207
 
    def _recordTestStartTime(self):
208
 
        """Record that a test has started."""
209
134
        self._start_time = time.time()
210
135
 
211
136
    def addError(self, test, err):
212
137
        if isinstance(err[1], TestSkipped):
213
138
            return self.addSkipped(test, err)    
214
139
        unittest.TestResult.addError(self, test, err)
215
 
        self.extractBenchmarkTime(test)
216
140
        if self.showAll:
217
 
            self.stream.writeln("ERROR %s" % self._testTimeString())
218
 
        elif self.dots and self.pb is None:
 
141
            self.stream.writeln("ERROR %s" % self._elapsedTime())
 
142
        elif self.dots:
219
143
            self.stream.write('E')
220
 
        elif self.dots:
221
 
            self.pb.update(self._ellipsise_unimportant_words('ERROR', 13), self.testsRun, None)
222
144
        self.stream.flush()
223
145
        if self.stop_early:
224
146
            self.stop()
225
147
 
226
148
    def addFailure(self, test, err):
227
149
        unittest.TestResult.addFailure(self, test, err)
228
 
        self.extractBenchmarkTime(test)
229
150
        if self.showAll:
230
 
            self.stream.writeln(" FAIL %s" % self._testTimeString())
231
 
        elif self.dots and self.pb is None:
 
151
            self.stream.writeln(" FAIL %s" % self._elapsedTime())
 
152
        elif self.dots:
232
153
            self.stream.write('F')
233
 
        elif self.dots:
234
 
            self.pb.update(self._ellipsise_unimportant_words('FAIL', 13), self.testsRun, None)
235
154
        self.stream.flush()
236
155
        if self.stop_early:
237
156
            self.stop()
238
157
 
239
158
    def addSuccess(self, test):
240
 
        self.extractBenchmarkTime(test)
241
159
        if self.showAll:
242
 
            self.stream.writeln('   OK %s' % self._testTimeString())
243
 
            for bench_called, stats in getattr(test, '_benchcalls', []):
244
 
                self.stream.writeln('LSProf output for %s(%s, %s)' % bench_called)
245
 
                stats.pprint(file=self.stream)
246
 
        elif self.dots and self.pb is None:
 
160
            self.stream.writeln('   OK %s' % self._elapsedTime())
 
161
        elif self.dots:
247
162
            self.stream.write('~')
248
 
        elif self.dots:
249
 
            self.pb.update(self._ellipsise_unimportant_words('OK', 13), self.testsRun, None)
250
163
        self.stream.flush()
251
164
        unittest.TestResult.addSuccess(self, test)
252
165
 
253
166
    def addSkipped(self, test, skip_excinfo):
254
 
        self.extractBenchmarkTime(test)
255
167
        if self.showAll:
256
 
            print >>self.stream, ' SKIP %s' % self._testTimeString()
 
168
            print >>self.stream, ' SKIP %s' % self._elapsedTime()
257
169
            print >>self.stream, '     %s' % skip_excinfo[1]
258
 
        elif self.dots and self.pb is None:
 
170
        elif self.dots:
259
171
            self.stream.write('S')
260
 
        elif self.dots:
261
 
            self.pb.update(self._ellipsise_unimportant_words('SKIP', 13), self.testsRun, None)
262
172
        self.stream.flush()
263
173
        # seems best to treat this as success from point-of-view of unittest
264
174
        # -- it actually does nothing so it barely matters :)
265
 
        try:
266
 
            test.tearDown()
267
 
        except KeyboardInterrupt:
268
 
            raise
269
 
        except:
270
 
            self.addError(test, test.__exc_info())
271
 
        else:
272
 
            unittest.TestResult.addSuccess(self, test)
 
175
        unittest.TestResult.addSuccess(self, test)
273
176
 
274
177
    def printErrorList(self, flavour, errors):
275
178
        for test, err in errors:
286
189
            self.stream.writeln("%s" % err)
287
190
 
288
191
 
289
 
class TextTestRunner(object):
 
192
class TextTestRunner(unittest.TextTestRunner):
290
193
    stop_on_failure = False
291
194
 
292
 
    def __init__(self,
293
 
                 stream=sys.stderr,
294
 
                 descriptions=0,
295
 
                 verbosity=1,
296
 
                 keep_output=False,
297
 
                 pb=None):
298
 
        self.stream = unittest._WritelnDecorator(stream)
299
 
        self.descriptions = descriptions
300
 
        self.verbosity = verbosity
301
 
        self.keep_output = keep_output
302
 
        self.pb = pb
303
 
 
304
195
    def _makeResult(self):
305
 
        result = _MyResult(self.stream,
306
 
                           self.descriptions,
307
 
                           self.verbosity,
308
 
                           pb=self.pb)
 
196
        result = _MyResult(self.stream, self.descriptions, self.verbosity)
309
197
        result.stop_early = self.stop_on_failure
310
198
        return result
311
199
 
312
 
    def run(self, test):
313
 
        "Run the given test case or test suite."
314
 
        result = self._makeResult()
315
 
        startTime = time.time()
316
 
        if self.pb is not None:
317
 
            self.pb.update('Running tests', 0, test.countTestCases())
318
 
        test.run(result)
319
 
        stopTime = time.time()
320
 
        timeTaken = stopTime - startTime
321
 
        result.printErrors()
322
 
        self.stream.writeln(result.separator2)
323
 
        run = result.testsRun
324
 
        self.stream.writeln("Ran %d test%s in %.3fs" %
325
 
                            (run, run != 1 and "s" or "", timeTaken))
326
 
        self.stream.writeln()
327
 
        if not result.wasSuccessful():
328
 
            self.stream.write("FAILED (")
329
 
            failed, errored = map(len, (result.failures, result.errors))
330
 
            if failed:
331
 
                self.stream.write("failures=%d" % failed)
332
 
            if errored:
333
 
                if failed: self.stream.write(", ")
334
 
                self.stream.write("errors=%d" % errored)
335
 
            self.stream.writeln(")")
336
 
        else:
337
 
            self.stream.writeln("OK")
338
 
        if self.pb is not None:
339
 
            self.pb.update('Cleaning up', 0, 1)
340
 
        # This is still a little bogus, 
341
 
        # but only a little. Folk not using our testrunner will
342
 
        # have to delete their temp directories themselves.
343
 
        test_root = TestCaseInTempDir.TEST_ROOT
344
 
        if result.wasSuccessful() or not self.keep_output:
345
 
            if test_root is not None:
346
 
                # If LANG=C we probably have created some bogus paths
347
 
                # which rmtree(unicode) will fail to delete
348
 
                # so make sure we are using rmtree(str) to delete everything
349
 
                # except on win32, where rmtree(str) will fail
350
 
                # since it doesn't have the property of byte-stream paths
351
 
                # (they are either ascii or mbcs)
352
 
                if sys.platform == 'win32':
353
 
                    # make sure we are using the unicode win32 api
354
 
                    test_root = unicode(test_root)
355
 
                else:
356
 
                    test_root = test_root.encode(
357
 
                        sys.getfilesystemencoding())
358
 
                osutils.rmtree(test_root)
359
 
        else:
360
 
            if self.pb is not None:
361
 
                self.pb.note("Failed tests working directories are in '%s'\n",
362
 
                             test_root)
363
 
            else:
364
 
                self.stream.writeln(
365
 
                    "Failed tests working directories are in '%s'\n" %
366
 
                    test_root)
367
 
        TestCaseInTempDir.TEST_ROOT = None
368
 
        if self.pb is not None:
369
 
            self.pb.clear()
370
 
        return result
371
 
 
372
200
 
373
201
def iter_suite_tests(suite):
374
202
    """Return all tests in a suite, recursing through nested suites"""
391
219
class CommandFailed(Exception):
392
220
    pass
393
221
 
394
 
 
395
 
class StringIOWrapper(object):
396
 
    """A wrapper around cStringIO which just adds an encoding attribute.
397
 
    
398
 
    Internally we can check sys.stdout to see what the output encoding
399
 
    should be. However, cStringIO has no encoding attribute that we can
400
 
    set. So we wrap it instead.
401
 
    """
402
 
    encoding='ascii'
403
 
    _cstring = None
404
 
 
405
 
    def __init__(self, s=None):
406
 
        if s is not None:
407
 
            self.__dict__['_cstring'] = StringIO(s)
408
 
        else:
409
 
            self.__dict__['_cstring'] = StringIO()
410
 
 
411
 
    def __getattr__(self, name, getattr=getattr):
412
 
        return getattr(self.__dict__['_cstring'], name)
413
 
 
414
 
    def __setattr__(self, name, val):
415
 
        if name == 'encoding':
416
 
            self.__dict__['encoding'] = val
417
 
        else:
418
 
            return setattr(self._cstring, name, val)
419
 
 
420
 
 
421
222
class TestCase(unittest.TestCase):
422
223
    """Base class for bzr unit tests.
423
224
    
439
240
    accidentally overlooked.
440
241
    """
441
242
 
 
243
    BZRPATH = 'bzr'
442
244
    _log_file_name = None
443
245
    _log_contents = ''
444
 
    # record lsprof data when performing benchmark calls.
445
 
    _gather_lsprof_in_benchmarks = False
446
246
 
447
247
    def __init__(self, methodName='testMethod'):
448
248
        super(TestCase, self).__init__(methodName)
453
253
        self._cleanEnvironment()
454
254
        bzrlib.trace.disable_default_logging()
455
255
        self._startLogFile()
456
 
        self._benchcalls = []
457
 
        self._benchtime = None
458
256
 
459
257
    def _ndiff_strings(self, a, b):
460
258
        """Return ndiff between two strings containing lines.
494
292
            raise AssertionError('string %r does not start with %r' % (s, prefix))
495
293
 
496
294
    def assertEndsWith(self, s, suffix):
497
 
        """Asserts that s ends with suffix."""
498
 
        if not s.endswith(suffix):
 
295
        if not s.endswith(prefix):
499
296
            raise AssertionError('string %r does not end with %r' % (s, suffix))
500
297
 
501
298
    def assertContainsRe(self, haystack, needle_re):
504
301
            raise AssertionError('pattern "%s" not found in "%s"'
505
302
                    % (needle_re, haystack))
506
303
 
507
 
    def assertNotContainsRe(self, haystack, needle_re):
508
 
        """Assert that a does not match a regular expression"""
509
 
        if re.search(needle_re, haystack):
510
 
            raise AssertionError('pattern "%s" found in "%s"'
511
 
                    % (needle_re, haystack))
512
 
 
513
304
    def assertSubset(self, sublist, superlist):
514
305
        """Assert that every entry in sublist is present in superlist."""
515
306
        missing = []
527
318
    def assertTransportMode(self, transport, path, mode):
528
319
        """Fail if a path does not have mode mode.
529
320
        
530
 
        If modes are not supported on this transport, the assertion is ignored.
 
321
        If modes are not supported on this platform, the test is skipped.
531
322
        """
532
 
        if not transport._can_roundtrip_unix_modebits():
 
323
        if sys.platform == 'win32':
533
324
            return
534
325
        path_stat = transport.stat(path)
535
326
        actual_mode = stat.S_IMODE(path_stat.st_mode)
536
327
        self.assertEqual(mode, actual_mode,
537
328
            'mode of %r incorrect (%o != %o)' % (path, mode, actual_mode))
538
329
 
539
 
    def assertIsInstance(self, obj, kls):
540
 
        """Fail if obj is not an instance of kls"""
541
 
        if not isinstance(obj, kls):
542
 
            self.fail("%r is an instance of %s rather than %s" % (
543
 
                obj, obj.__class__, kls))
544
 
 
545
330
    def _startLogFile(self):
546
331
        """Send bzr and test log messages to a temporary file.
547
332
 
559
344
 
560
345
        Read contents into memory, close, and delete.
561
346
        """
562
 
        if self._log_file is None:
563
 
            return
564
347
        bzrlib.trace.disable_test_log(self._log_nonce)
565
348
        self._log_file.seek(0)
566
349
        self._log_contents = self._log_file.read()
617
400
        self._runCleanups()
618
401
        unittest.TestCase.tearDown(self)
619
402
 
620
 
    def time(self, callable, *args, **kwargs):
621
 
        """Run callable and accrue the time it takes to the benchmark time.
622
 
        
623
 
        If lsprofiling is enabled (i.e. by --lsprof-time to bzr selftest) then
624
 
        this will cause lsprofile statistics to be gathered and stored in
625
 
        self._benchcalls.
626
 
        """
627
 
        if self._benchtime is None:
628
 
            self._benchtime = 0
629
 
        start = time.time()
630
 
        try:
631
 
            if not self._gather_lsprof_in_benchmarks:
632
 
                return callable(*args, **kwargs)
633
 
            else:
634
 
                # record this benchmark
635
 
                ret, stats = bzrlib.lsprof.profile(callable, *args, **kwargs)
636
 
                stats.sort()
637
 
                self._benchcalls.append(((callable, args, kwargs), stats))
638
 
                return ret
639
 
        finally:
640
 
            self._benchtime += time.time() - start
641
 
 
642
403
    def _runCleanups(self):
643
404
        """Run registered cleanup functions. 
644
405
 
664
425
        """Shortcut that splits cmd into words, runs, and returns stdout"""
665
426
        return self.run_bzr_captured(cmd.split(), retcode=retcode)[0]
666
427
 
667
 
    def run_bzr_captured(self, argv, retcode=0, encoding=None, stdin=None):
 
428
    def run_bzr_captured(self, argv, retcode=0):
668
429
        """Invoke bzr and return (stdout, stderr).
669
430
 
670
431
        Useful for code that wants to check the contents of the
681
442
        errors, and with logging set to something approximating the
682
443
        default, so that error reporting can be checked.
683
444
 
684
 
        :param argv: arguments to invoke bzr
685
 
        :param retcode: expected return code, or None for don't-care.
686
 
        :param encoding: encoding for sys.stdout and sys.stderr
687
 
        :param stdin: A string to be used as stdin for the command.
 
445
        argv -- arguments to invoke bzr
 
446
        retcode -- expected return code, or None for don't-care.
688
447
        """
689
 
        if encoding is None:
690
 
            encoding = bzrlib.user_encoding
691
 
        if stdin is not None:
692
 
            stdin = StringIO(stdin)
693
 
        stdout = StringIOWrapper()
694
 
        stderr = StringIOWrapper()
695
 
        stdout.encoding = encoding
696
 
        stderr.encoding = encoding
697
 
 
698
 
        self.log('run bzr: %r', argv)
 
448
        stdout = StringIO()
 
449
        stderr = StringIO()
 
450
        self.log('run bzr: %s', ' '.join(argv))
699
451
        # FIXME: don't call into logging here
700
452
        handler = logging.StreamHandler(stderr)
 
453
        handler.setFormatter(bzrlib.trace.QuietFormatter())
701
454
        handler.setLevel(logging.INFO)
702
455
        logger = logging.getLogger('')
703
456
        logger.addHandler(handler)
704
 
        old_ui_factory = bzrlib.ui.ui_factory
705
 
        bzrlib.ui.ui_factory = bzrlib.tests.blackbox.TestUIFactory(
706
 
            stdout=stdout,
707
 
            stderr=stderr)
708
 
        bzrlib.ui.ui_factory.stdin = stdin
709
457
        try:
710
 
            result = self.apply_redirected(stdin, stdout, stderr,
 
458
            result = self.apply_redirected(None, stdout, stderr,
711
459
                                           bzrlib.commands.run_bzr_catch_errors,
712
460
                                           argv)
713
461
        finally:
714
462
            logger.removeHandler(handler)
715
 
            bzrlib.ui.ui_factory = old_ui_factory
716
 
 
717
463
        out = stdout.getvalue()
718
464
        err = stderr.getvalue()
719
465
        if out:
720
 
            self.log('output:\n%r', out)
 
466
            self.log('output:\n%s', out)
721
467
        if err:
722
 
            self.log('errors:\n%r', err)
 
468
            self.log('errors:\n%s', err)
723
469
        if retcode is not None:
724
 
            self.assertEquals(retcode, result)
 
470
            self.assertEquals(result, retcode)
725
471
        return out, err
726
472
 
727
473
    def run_bzr(self, *args, **kwargs):
733
479
 
734
480
        This sends the stdout/stderr results into the test's log,
735
481
        where it may be useful for debugging.  See also run_captured.
736
 
 
737
 
        :param stdin: A string to be used as stdin for the command.
738
482
        """
739
483
        retcode = kwargs.pop('retcode', 0)
740
 
        encoding = kwargs.pop('encoding', None)
741
 
        stdin = kwargs.pop('stdin', None)
742
 
        return self.run_bzr_captured(args, retcode=retcode, encoding=encoding, stdin=stdin)
743
 
 
744
 
    def run_bzr_decode(self, *args, **kwargs):
745
 
        if kwargs.has_key('encoding'):
746
 
            encoding = kwargs['encoding']
747
 
        else:
748
 
            encoding = bzrlib.user_encoding
749
 
        return self.run_bzr(*args, **kwargs)[0].decode(encoding)
750
 
 
751
 
    def run_bzr_error(self, error_regexes, *args, **kwargs):
752
 
        """Run bzr, and check that stderr contains the supplied regexes
753
 
        
754
 
        :param error_regexes: Sequence of regular expressions which 
755
 
            must each be found in the error output. The relative ordering
756
 
            is not enforced.
757
 
        :param args: command-line arguments for bzr
758
 
        :param kwargs: Keyword arguments which are interpreted by run_bzr
759
 
            This function changes the default value of retcode to be 3,
760
 
            since in most cases this is run when you expect bzr to fail.
761
 
        :return: (out, err) The actual output of running the command (in case you
762
 
                 want to do more inspection)
763
 
 
764
 
        Examples of use:
765
 
            # Make sure that commit is failing because there is nothing to do
766
 
            self.run_bzr_error(['no changes to commit'],
767
 
                               'commit', '-m', 'my commit comment')
768
 
            # Make sure --strict is handling an unknown file, rather than
769
 
            # giving us the 'nothing to do' error
770
 
            self.build_tree(['unknown'])
771
 
            self.run_bzr_error(['Commit refused because there are unknown files'],
772
 
                               'commit', '--strict', '-m', 'my commit comment')
773
 
        """
774
 
        kwargs.setdefault('retcode', 3)
775
 
        out, err = self.run_bzr(*args, **kwargs)
776
 
        for regex in error_regexes:
777
 
            self.assertContainsRe(err, regex)
778
 
        return out, err
779
 
 
780
 
    def run_bzr_subprocess(self, *args, **kwargs):
781
 
        """Run bzr in a subprocess for testing.
782
 
 
783
 
        This starts a new Python interpreter and runs bzr in there. 
784
 
        This should only be used for tests that have a justifiable need for
785
 
        this isolation: e.g. they are testing startup time, or signal
786
 
        handling, or early startup code, etc.  Subprocess code can't be 
787
 
        profiled or debugged so easily.
788
 
 
789
 
        :param retcode: The status code that is expected.  Defaults to 0.  If
790
 
        None is supplied, the status code is not checked.
791
 
        """
792
 
        bzr_path = os.path.dirname(os.path.dirname(bzrlib.__file__))+'/bzr'
793
 
        args = list(args)
794
 
        process = Popen([sys.executable, bzr_path]+args, stdout=PIPE, 
795
 
                         stderr=PIPE)
796
 
        out = process.stdout.read()
797
 
        err = process.stderr.read()
798
 
        retcode = process.wait()
799
 
        supplied_retcode = kwargs.get('retcode', 0)
800
 
        if supplied_retcode is not None:
801
 
            assert supplied_retcode == retcode
802
 
        return [out, err]
 
484
        return self.run_bzr_captured(args, retcode)
803
485
 
804
486
    def check_inventory_shape(self, inv, shape):
805
487
        """Compare an inventory to a list of expected names.
853
535
            sys.stderr = real_stderr
854
536
            sys.stdin = real_stdin
855
537
 
856
 
    def merge(self, branch_from, wt_to):
857
 
        """A helper for tests to do a ui-less merge.
858
 
 
859
 
        This should move to the main library when someone has time to integrate
860
 
        it in.
861
 
        """
862
 
        # minimal ui-less merge.
863
 
        wt_to.branch.fetch(branch_from)
864
 
        base_rev = common_ancestor(branch_from.last_revision(),
865
 
                                   wt_to.branch.last_revision(),
866
 
                                   wt_to.branch.repository)
867
 
        merge_inner(wt_to.branch, branch_from.basis_tree(), 
868
 
                    wt_to.branch.repository.revision_tree(base_rev),
869
 
                    this_tree=wt_to)
870
 
        wt_to.add_pending_merge(branch_from.last_revision())
871
 
 
872
538
 
873
539
BzrTestBase = TestCase
874
540
 
923
589
        super(TestCaseInTempDir, self).setUp()
924
590
        self._make_test_root()
925
591
        _currentdir = os.getcwdu()
926
 
        # shorten the name, to avoid test failures due to path length
927
592
        short_id = self.id().replace('bzrlib.tests.', '') \
928
 
                   .replace('__main__.', '')[-100:]
929
 
        # it's possible the same test class is run several times for
930
 
        # parameterized tests, so make sure the names don't collide.  
931
 
        i = 0
932
 
        while True:
933
 
            if i > 0:
934
 
                candidate_dir = '%s/%s.%d' % (self.TEST_ROOT, short_id, i)
935
 
            else:
936
 
                candidate_dir = '%s/%s' % (self.TEST_ROOT, short_id)
937
 
            if os.path.exists(candidate_dir):
938
 
                i = i + 1
939
 
                continue
940
 
            else:
941
 
                self.test_dir = candidate_dir
942
 
                os.mkdir(self.test_dir)
943
 
                os.chdir(self.test_dir)
944
 
                break
 
593
                   .replace('__main__.', '')
 
594
        self.test_dir = osutils.pathjoin(self.TEST_ROOT, short_id)
 
595
        os.mkdir(self.test_dir)
 
596
        os.chdir(self.test_dir)
945
597
        os.environ['HOME'] = self.test_dir
946
598
        os.environ['APPDATA'] = self.test_dir
947
599
        def _leaveDirectory():
970
622
        for name in shape:
971
623
            self.assert_(isinstance(name, basestring))
972
624
            if name[-1] == '/':
973
 
                transport.mkdir(urlutils.escape(name[:-1]))
 
625
                transport.mkdir(urlescape(name[:-1]))
974
626
            else:
975
627
                if line_endings == 'binary':
976
628
                    end = '\n'
978
630
                    end = os.linesep
979
631
                else:
980
632
                    raise errors.BzrError('Invalid line ending request %r' % (line_endings,))
981
 
                content = "contents of %s%s" % (name.encode('utf-8'), end)
982
 
                transport.put(urlutils.escape(name), StringIO(content))
 
633
                content = "contents of %s%s" % (name, end)
 
634
                transport.put(urlescape(name), StringIO(content))
983
635
 
984
636
    def build_tree_contents(self, shape):
985
637
        build_tree_contents(shape)
995
647
    def assertFileEqual(self, content, path):
996
648
        """Fail if path does not contain 'content'."""
997
649
        self.failUnless(osutils.lexists(path))
998
 
        # TODO: jam 20060427 Shouldn't this be 'rb'?
999
650
        self.assertEqualDiff(content, open(path, 'r').read())
1000
651
 
1001
652
 
1077
728
        if relpath is not None and relpath != '.':
1078
729
            if not base.endswith('/'):
1079
730
                base = base + '/'
1080
 
            base = base + urlutils.escape(relpath)
 
731
            base = base + relpath
1081
732
        return base
1082
733
 
1083
734
    def get_transport(self):
1096
747
        self.assertTrue(t.is_readonly())
1097
748
        return t
1098
749
 
1099
 
    def make_branch(self, relpath, format=None):
 
750
    def make_branch(self, relpath):
1100
751
        """Create a branch on the transport at relpath."""
1101
 
        repo = self.make_repository(relpath, format=format)
 
752
        repo = self.make_repository(relpath)
1102
753
        return repo.bzrdir.create_branch()
1103
754
 
1104
 
    def make_bzrdir(self, relpath, format=None):
 
755
    def make_bzrdir(self, relpath):
1105
756
        try:
1106
757
            url = self.get_url(relpath)
1107
 
            mutter('relpath %r => url %r', relpath, url)
1108
 
            segments = url.split('/')
 
758
            segments = relpath.split('/')
1109
759
            if segments and segments[-1] not in ('', '.'):
1110
 
                parent = '/'.join(segments[:-1])
 
760
                parent = self.get_url('/'.join(segments[:-1]))
1111
761
                t = get_transport(parent)
1112
762
                try:
1113
763
                    t.mkdir(segments[-1])
1114
764
                except errors.FileExists:
1115
765
                    pass
1116
 
            if format is None:
1117
 
                format=bzrlib.bzrdir.BzrDirFormat.get_default_format()
1118
 
            # FIXME: make this use a single transport someday. RBC 20060418
1119
 
            return format.initialize_on_transport(get_transport(relpath))
 
766
            return bzrlib.bzrdir.BzrDir.create(url)
1120
767
        except errors.UninitializableFormat:
1121
 
            raise TestSkipped("Format %s is not initializable." % format)
 
768
            raise TestSkipped("Format %s is not initializable.")
1122
769
 
1123
 
    def make_repository(self, relpath, shared=False, format=None):
 
770
    def make_repository(self, relpath, shared=False):
1124
771
        """Create a repository on our default transport at relpath."""
1125
 
        made_control = self.make_bzrdir(relpath, format=format)
 
772
        made_control = self.make_bzrdir(relpath)
1126
773
        return made_control.create_repository(shared=shared)
1127
774
 
1128
 
    def make_branch_and_tree(self, relpath, format=None):
 
775
    def make_branch_and_tree(self, relpath):
1129
776
        """Create a branch on the transport and a tree locally.
1130
777
 
1131
778
        Returns the tree.
1134
781
        # this obviously requires a format that supports branch references
1135
782
        # so check for that by checking bzrdir.BzrDirFormat.get_default_format()
1136
783
        # RBC 20060208
1137
 
        b = self.make_branch(relpath, format=format)
 
784
        b = self.make_branch(relpath)
1138
785
        try:
1139
786
            return b.bzrdir.create_workingtree()
1140
787
        except errors.NotLocalUrl:
1144
791
            # TODO: rbc 20060208
1145
792
            return WorkingTreeFormat2().initialize(bzrdir.BzrDir.open(relpath))
1146
793
 
1147
 
    def assertIsDirectory(self, relpath, transport):
1148
 
        """Assert that relpath within transport is a directory.
1149
 
 
1150
 
        This may not be possible on all transports; in that case it propagates
1151
 
        a TransportNotPossible.
1152
 
        """
1153
 
        try:
1154
 
            mode = transport.stat(relpath).st_mode
1155
 
        except errors.NoSuchFile:
1156
 
            self.fail("path %s is not a directory; no such file"
1157
 
                      % (relpath))
1158
 
        if not stat.S_ISDIR(mode):
1159
 
            self.fail("path %s is not a directory; has mode %#o"
1160
 
                      % (relpath, mode))
1161
 
 
1162
794
 
1163
795
class ChrootedTestCase(TestCaseWithTransport):
1164
796
    """A support class that provides readonly urls outside the local namespace.
1179
811
 
1180
812
 
1181
813
def filter_suite_by_re(suite, pattern):
1182
 
    result = TestUtil.TestSuite()
 
814
    result = TestSuite()
1183
815
    filter_re = re.compile(pattern)
1184
816
    for test in iter_suite_tests(suite):
1185
817
        if filter_re.search(test.id()):
1189
821
 
1190
822
def run_suite(suite, name='test', verbose=False, pattern=".*",
1191
823
              stop_on_failure=False, keep_output=False,
1192
 
              transport=None, lsprof_timed=None):
 
824
              transport=None):
1193
825
    TestCaseInTempDir._TEST_NAME = name
1194
 
    TestCase._gather_lsprof_in_benchmarks = lsprof_timed
1195
826
    if verbose:
1196
827
        verbosity = 2
1197
 
        pb = None
1198
828
    else:
1199
829
        verbosity = 1
1200
 
        pb = progress.ProgressBar()
1201
830
    runner = TextTestRunner(stream=sys.stdout,
1202
831
                            descriptions=0,
1203
 
                            verbosity=verbosity,
1204
 
                            keep_output=keep_output,
1205
 
                            pb=pb)
 
832
                            verbosity=verbosity)
1206
833
    runner.stop_on_failure=stop_on_failure
1207
834
    if pattern != '.*':
1208
835
        suite = filter_suite_by_re(suite, pattern)
1209
836
    result = runner.run(suite)
 
837
    # This is still a little bogus, 
 
838
    # but only a little. Folk not using our testrunner will
 
839
    # have to delete their temp directories themselves.
 
840
    if result.wasSuccessful() or not keep_output:
 
841
        if TestCaseInTempDir.TEST_ROOT is not None:
 
842
            shutil.rmtree(TestCaseInTempDir.TEST_ROOT) 
 
843
    else:
 
844
        print "Failed tests working directories are in '%s'\n" % TestCaseInTempDir.TEST_ROOT
1210
845
    return result.wasSuccessful()
1211
846
 
1212
847
 
1213
848
def selftest(verbose=False, pattern=".*", stop_on_failure=True,
1214
849
             keep_output=False,
1215
 
             transport=None,
1216
 
             test_suite_factory=None,
1217
 
             lsprof_timed=None):
 
850
             transport=None):
1218
851
    """Run the whole test suite under the enhanced runner"""
1219
852
    global default_transport
1220
853
    if transport is None:
1221
854
        transport = default_transport
1222
855
    old_transport = default_transport
1223
856
    default_transport = transport
 
857
    suite = test_suite()
1224
858
    try:
1225
 
        if test_suite_factory is None:
1226
 
            suite = test_suite()
1227
 
        else:
1228
 
            suite = test_suite_factory()
1229
859
        return run_suite(suite, 'testbzr', verbose=verbose, pattern=pattern,
1230
860
                     stop_on_failure=stop_on_failure, keep_output=keep_output,
1231
 
                     transport=transport,
1232
 
                     lsprof_timed=lsprof_timed)
 
861
                     transport=transport)
1233
862
    finally:
1234
863
        default_transport = old_transport
1235
864
 
1236
865
 
 
866
 
1237
867
def test_suite():
1238
 
    """Build and return TestSuite for the whole of bzrlib.
1239
 
    
1240
 
    This function can be replaced if you need to change the default test
1241
 
    suite on a global basis, but it is not encouraged.
1242
 
    """
1243
 
    testmod_names = [
 
868
    """Build and return TestSuite for the whole program."""
 
869
    from doctest import DocTestSuite
 
870
 
 
871
    global MODULES_TO_DOCTEST
 
872
 
 
873
    testmod_names = [ \
1244
874
                   'bzrlib.tests.test_ancestry',
 
875
                   'bzrlib.tests.test_annotate',
1245
876
                   'bzrlib.tests.test_api',
1246
877
                   'bzrlib.tests.test_bad_files',
 
878
                   'bzrlib.tests.test_basis_inventory',
1247
879
                   'bzrlib.tests.test_branch',
1248
 
                   'bzrlib.tests.test_bundle',
1249
880
                   'bzrlib.tests.test_bzrdir',
1250
881
                   'bzrlib.tests.test_command',
1251
882
                   'bzrlib.tests.test_commit',
1255
886
                   'bzrlib.tests.test_decorators',
1256
887
                   'bzrlib.tests.test_diff',
1257
888
                   'bzrlib.tests.test_doc_generate',
1258
 
                   'bzrlib.tests.test_emptytree',
1259
889
                   'bzrlib.tests.test_errors',
1260
 
                   'bzrlib.tests.test_escaped_store',
1261
890
                   'bzrlib.tests.test_fetch',
1262
891
                   'bzrlib.tests.test_gpg',
1263
892
                   'bzrlib.tests.test_graph',
1264
893
                   'bzrlib.tests.test_hashcache',
1265
894
                   'bzrlib.tests.test_http',
1266
 
                   'bzrlib.tests.test_http_response',
1267
895
                   'bzrlib.tests.test_identitymap',
1268
896
                   'bzrlib.tests.test_inv',
1269
 
                   'bzrlib.tests.test_knit',
1270
897
                   'bzrlib.tests.test_lockdir',
1271
898
                   'bzrlib.tests.test_lockable_files',
1272
899
                   'bzrlib.tests.test_log',
1278
905
                   'bzrlib.tests.test_nonascii',
1279
906
                   'bzrlib.tests.test_options',
1280
907
                   'bzrlib.tests.test_osutils',
1281
 
                   'bzrlib.tests.test_patch',
1282
 
                   'bzrlib.tests.test_patches',
1283
908
                   'bzrlib.tests.test_permissions',
1284
909
                   'bzrlib.tests.test_plugins',
1285
 
                   'bzrlib.tests.test_progress',
1286
 
                   'bzrlib.tests.test_reconcile',
1287
910
                   'bzrlib.tests.test_repository',
1288
911
                   'bzrlib.tests.test_revision',
1289
912
                   'bzrlib.tests.test_revisionnamespaces',
1290
913
                   'bzrlib.tests.test_revprops',
1291
 
                   'bzrlib.tests.test_revisiontree',
 
914
                   'bzrlib.tests.test_reweave',
1292
915
                   'bzrlib.tests.test_rio',
1293
916
                   'bzrlib.tests.test_sampler',
1294
917
                   'bzrlib.tests.test_selftest',
1296
919
                   'bzrlib.tests.test_sftp_transport',
1297
920
                   'bzrlib.tests.test_smart_add',
1298
921
                   'bzrlib.tests.test_source',
1299
 
                   'bzrlib.tests.test_status',
1300
922
                   'bzrlib.tests.test_store',
1301
923
                   'bzrlib.tests.test_symbol_versioning',
1302
924
                   'bzrlib.tests.test_testament',
1303
 
                   'bzrlib.tests.test_textfile',
1304
 
                   'bzrlib.tests.test_textmerge',
1305
925
                   'bzrlib.tests.test_trace',
1306
926
                   'bzrlib.tests.test_transactions',
1307
927
                   'bzrlib.tests.test_transform',
1308
928
                   'bzrlib.tests.test_transport',
1309
929
                   'bzrlib.tests.test_tsort',
1310
 
                   'bzrlib.tests.test_tuned_gzip',
1311
930
                   'bzrlib.tests.test_ui',
 
931
                   'bzrlib.tests.test_uncommit',
1312
932
                   'bzrlib.tests.test_upgrade',
1313
 
                   'bzrlib.tests.test_urlutils',
1314
 
                   'bzrlib.tests.test_versionedfile',
1315
933
                   'bzrlib.tests.test_weave',
1316
934
                   'bzrlib.tests.test_whitebox',
1317
935
                   'bzrlib.tests.test_workingtree',
1318
936
                   'bzrlib.tests.test_xml',
1319
937
                   ]
1320
938
    test_transport_implementations = [
1321
 
        'bzrlib.tests.test_transport_implementations',
1322
 
        'bzrlib.tests.test_read_bundle',
1323
 
        ]
1324
 
    suite = TestUtil.TestSuite()
1325
 
    loader = TestUtil.TestLoader()
 
939
        'bzrlib.tests.test_transport_implementations']
 
940
 
 
941
    TestCase.BZRPATH = osutils.pathjoin(
 
942
            osutils.realpath(osutils.dirname(bzrlib.__path__[0])), 'bzr')
 
943
    print '%10s: %s' % ('bzr', osutils.realpath(sys.argv[0]))
 
944
    print '%10s: %s' % ('bzrlib', bzrlib.__path__[0])
 
945
    print
 
946
    suite = TestSuite()
 
947
    # python2.4's TestLoader.loadTestsFromNames gives very poor 
 
948
    # errors if it fails to load a named module - no indication of what's
 
949
    # actually wrong, just "no such module".  We should probably override that
 
950
    # class, but for the moment just load them ourselves. (mbp 20051202)
 
951
    loader = TestLoader()
1326
952
    from bzrlib.transport import TransportTestProviderAdapter
1327
953
    adapter = TransportTestProviderAdapter()
1328
954
    adapt_modules(test_transport_implementations, adapter, loader, suite)
1329
 
    suite.addTest(loader.loadTestsFromModuleNames(testmod_names))
 
955
    for mod_name in testmod_names:
 
956
        mod = _load_module_by_name(mod_name)
 
957
        suite.addTest(loader.loadTestsFromModule(mod))
1330
958
    for package in packages_to_test():
1331
959
        suite.addTest(package.test_suite())
1332
960
    for m in MODULES_TO_TEST:
1333
961
        suite.addTest(loader.loadTestsFromModule(m))
1334
 
    for m in MODULES_TO_DOCTEST:
1335
 
        suite.addTest(doctest.DocTestSuite(m))
 
962
    for m in (MODULES_TO_DOCTEST):
 
963
        suite.addTest(DocTestSuite(m))
1336
964
    for name, plugin in bzrlib.plugin.all_plugins().items():
1337
965
        if getattr(plugin, 'test_suite', None) is not None:
1338
966
            suite.addTest(plugin.test_suite())
1341
969
 
1342
970
def adapt_modules(mods_list, adapter, loader, suite):
1343
971
    """Adapt the modules in mods_list using adapter and add to suite."""
1344
 
    for test in iter_suite_tests(loader.loadTestsFromModuleNames(mods_list)):
1345
 
        suite.addTests(adapter.adapt(test))
 
972
    for mod_name in mods_list:
 
973
        mod = _load_module_by_name(mod_name)
 
974
        for test in iter_suite_tests(loader.loadTestsFromModule(mod)):
 
975
            suite.addTests(adapter.adapt(test))
 
976
 
 
977
 
 
978
def _load_module_by_name(mod_name):
 
979
    parts = mod_name.split('.')
 
980
    module = __import__(mod_name)
 
981
    del parts[0]
 
982
    # for historical reasons python returns the top-level module even though
 
983
    # it loads the submodule; we need to walk down to get the one we want.
 
984
    while parts:
 
985
        module = getattr(module, parts.pop(0))
 
986
    return module