/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 bzr.dev.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
# Copyright (C) 2005, 2006 by Canonical Ltd
2
 
 
 
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
5
5
# the Free Software Foundation; either version 2 of the License, or
6
6
# (at your option) any later version.
7
 
 
 
7
#
8
8
# This program is distributed in the hope that it will be useful,
9
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
11
# GNU General Public License for more details.
12
 
 
 
12
#
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
29
29
import codecs
30
30
from cStringIO import StringIO
31
31
import difflib
 
32
import doctest
32
33
import errno
33
34
import logging
34
35
import os
35
36
import re
36
 
import shutil
 
37
import shlex
37
38
import stat
 
39
from subprocess import Popen, PIPE
38
40
import sys
39
41
import tempfile
40
42
import unittest
44
46
import bzrlib.branch
45
47
import bzrlib.bzrdir as bzrdir
46
48
import bzrlib.commands
 
49
import bzrlib.bundle.serializer
47
50
import bzrlib.errors as errors
48
51
import bzrlib.inventory
49
52
import bzrlib.iterablefile
50
53
import bzrlib.lockdir
 
54
try:
 
55
    import bzrlib.lsprof
 
56
except ImportError:
 
57
    # lsprof not available
 
58
    pass
51
59
from bzrlib.merge import merge_inner
52
60
import bzrlib.merge3
53
61
import bzrlib.osutils
54
62
import bzrlib.osutils as osutils
55
63
import bzrlib.plugin
 
64
import bzrlib.progress as progress
56
65
from bzrlib.revision import common_ancestor
57
66
import bzrlib.store
58
67
import bzrlib.trace
59
 
from bzrlib.transport import urlescape, get_transport
 
68
from bzrlib.transport import get_transport
60
69
import bzrlib.transport
61
70
from bzrlib.transport.local import LocalRelpathServer
62
71
from bzrlib.transport.readonly import ReadonlyServer
63
72
from bzrlib.trace import mutter
64
 
from bzrlib.tests.TestUtil import TestLoader, TestSuite
 
73
from bzrlib.tests import TestUtil
 
74
from bzrlib.tests.TestUtil import (
 
75
                          TestSuite,
 
76
                          TestLoader,
 
77
                          )
65
78
from bzrlib.tests.treeshape import build_tree_contents
 
79
import bzrlib.urlutils as urlutils
66
80
from bzrlib.workingtree import WorkingTree, WorkingTreeFormat2
67
81
 
68
82
default_transport = LocalRelpathServer
70
84
MODULES_TO_TEST = []
71
85
MODULES_TO_DOCTEST = [
72
86
                      bzrlib.branch,
 
87
                      bzrlib.bundle.serializer,
73
88
                      bzrlib.commands,
74
89
                      bzrlib.errors,
75
90
                      bzrlib.inventory,
80
95
                      bzrlib.osutils,
81
96
                      bzrlib.store
82
97
                      ]
 
98
 
 
99
 
83
100
def packages_to_test():
84
101
    """Return a list of packages to test.
85
102
 
92
109
    import bzrlib.tests.bzrdir_implementations
93
110
    import bzrlib.tests.interrepository_implementations
94
111
    import bzrlib.tests.interversionedfile_implementations
 
112
    import bzrlib.tests.intertree_implementations
95
113
    import bzrlib.tests.repository_implementations
96
114
    import bzrlib.tests.revisionstore_implementations
 
115
    import bzrlib.tests.tree_implementations
97
116
    import bzrlib.tests.workingtree_implementations
98
117
    return [
99
118
            bzrlib.doc,
102
121
            bzrlib.tests.bzrdir_implementations,
103
122
            bzrlib.tests.interrepository_implementations,
104
123
            bzrlib.tests.interversionedfile_implementations,
 
124
            bzrlib.tests.intertree_implementations,
105
125
            bzrlib.tests.repository_implementations,
106
126
            bzrlib.tests.revisionstore_implementations,
 
127
            bzrlib.tests.tree_implementations,
107
128
            bzrlib.tests.workingtree_implementations,
108
129
            ]
109
130
 
114
135
    Shows output in a different format, including displaying runtime for tests.
115
136
    """
116
137
    stop_early = False
117
 
 
118
 
    def _elapsedTime(self):
119
 
        return "%5dms" % (1000 * (time.time() - self._start_time))
 
138
    
 
139
    def __init__(self, stream, descriptions, verbosity, pb=None):
 
140
        unittest._TextTestResult.__init__(self, stream, descriptions, verbosity)
 
141
        self.pb = pb
 
142
    
 
143
    def extractBenchmarkTime(self, testCase):
 
144
        """Add a benchmark time for the current test case."""
 
145
        self._benchmarkTime = getattr(testCase, "_benchtime", None)
 
146
    
 
147
    def _elapsedTestTimeString(self):
 
148
        """Return a time string for the overall time the current test has taken."""
 
149
        return self._formatTime(time.time() - self._start_time)
 
150
 
 
151
    def _testTimeString(self):
 
152
        if self._benchmarkTime is not None:
 
153
            return "%s/%s" % (
 
154
                self._formatTime(self._benchmarkTime),
 
155
                self._elapsedTestTimeString())
 
156
        else:
 
157
            return "      %s" % self._elapsedTestTimeString()
 
158
 
 
159
    def _formatTime(self, seconds):
 
160
        """Format seconds as milliseconds with leading spaces."""
 
161
        return "%5dms" % (1000 * seconds)
 
162
 
 
163
    def _ellipsise_unimportant_words(self, a_string, final_width,
 
164
                                   keep_start=False):
 
165
        """Add ellipses (sp?) for overly long strings.
 
166
        
 
167
        :param keep_start: If true preserve the start of a_string rather
 
168
                           than the end of it.
 
169
        """
 
170
        if keep_start:
 
171
            if len(a_string) > final_width:
 
172
                result = a_string[:final_width-3] + '...'
 
173
            else:
 
174
                result = a_string
 
175
        else:
 
176
            if len(a_string) > final_width:
 
177
                result = '...' + a_string[3-final_width:]
 
178
            else:
 
179
                result = a_string
 
180
        return result.ljust(final_width)
120
181
 
121
182
    def startTest(self, test):
122
183
        unittest.TestResult.startTest(self, test)
124
185
        # the beginning, but in an id, the important words are
125
186
        # at the end
126
187
        SHOW_DESCRIPTIONS = False
 
188
 
 
189
        if not self.showAll and self.dots and self.pb is not None:
 
190
            final_width = 13
 
191
        else:
 
192
            final_width = osutils.terminal_width()
 
193
            final_width = final_width - 15 - 8
 
194
        what = None
 
195
        if SHOW_DESCRIPTIONS:
 
196
            what = test.shortDescription()
 
197
            if what:
 
198
                what = self._ellipsise_unimportant_words(what, final_width, keep_start=True)
 
199
        if what is None:
 
200
            what = test.id()
 
201
            if what.startswith('bzrlib.tests.'):
 
202
                what = what[13:]
 
203
            what = self._ellipsise_unimportant_words(what, final_width)
127
204
        if self.showAll:
128
 
            width = osutils.terminal_width()
129
 
            name_width = width - 15
130
 
            what = None
131
 
            if SHOW_DESCRIPTIONS:
132
 
                what = test.shortDescription()
133
 
                if what:
134
 
                    if len(what) > name_width:
135
 
                        what = what[:name_width-3] + '...'
136
 
            if what is None:
137
 
                what = test.id()
138
 
                if what.startswith('bzrlib.tests.'):
139
 
                    what = what[13:]
140
 
                if len(what) > name_width:
141
 
                    what = '...' + what[3-name_width:]
142
 
            what = what.ljust(name_width)
143
205
            self.stream.write(what)
 
206
        elif self.dots and self.pb is not None:
 
207
            self.pb.update(what, self.testsRun - 1, None)
144
208
        self.stream.flush()
 
209
        self._recordTestStartTime()
 
210
 
 
211
    def _recordTestStartTime(self):
 
212
        """Record that a test has started."""
145
213
        self._start_time = time.time()
146
214
 
147
215
    def addError(self, test, err):
148
216
        if isinstance(err[1], TestSkipped):
149
217
            return self.addSkipped(test, err)    
150
218
        unittest.TestResult.addError(self, test, err)
 
219
        self.extractBenchmarkTime(test)
151
220
        if self.showAll:
152
 
            self.stream.writeln("ERROR %s" % self._elapsedTime())
153
 
        elif self.dots:
 
221
            self.stream.writeln("ERROR %s" % self._testTimeString())
 
222
        elif self.dots and self.pb is None:
154
223
            self.stream.write('E')
 
224
        elif self.dots:
 
225
            self.pb.update(self._ellipsise_unimportant_words('ERROR', 13), self.testsRun, None)
 
226
            self.pb.note(self._ellipsise_unimportant_words(
 
227
                            test.id() + ': ERROR',
 
228
                            osutils.terminal_width()))
155
229
        self.stream.flush()
156
230
        if self.stop_early:
157
231
            self.stop()
158
232
 
159
233
    def addFailure(self, test, err):
160
234
        unittest.TestResult.addFailure(self, test, err)
 
235
        self.extractBenchmarkTime(test)
161
236
        if self.showAll:
162
 
            self.stream.writeln(" FAIL %s" % self._elapsedTime())
163
 
        elif self.dots:
 
237
            self.stream.writeln(" FAIL %s" % self._testTimeString())
 
238
        elif self.dots and self.pb is None:
164
239
            self.stream.write('F')
 
240
        elif self.dots:
 
241
            self.pb.update(self._ellipsise_unimportant_words('FAIL', 13), self.testsRun, None)
 
242
            self.pb.note(self._ellipsise_unimportant_words(
 
243
                            test.id() + ': FAIL',
 
244
                            osutils.terminal_width()))
165
245
        self.stream.flush()
166
246
        if self.stop_early:
167
247
            self.stop()
168
248
 
169
249
    def addSuccess(self, test):
 
250
        self.extractBenchmarkTime(test)
170
251
        if self.showAll:
171
 
            self.stream.writeln('   OK %s' % self._elapsedTime())
172
 
        elif self.dots:
 
252
            self.stream.writeln('   OK %s' % self._testTimeString())
 
253
            for bench_called, stats in getattr(test, '_benchcalls', []):
 
254
                self.stream.writeln('LSProf output for %s(%s, %s)' % bench_called)
 
255
                stats.pprint(file=self.stream)
 
256
        elif self.dots and self.pb is None:
173
257
            self.stream.write('~')
 
258
        elif self.dots:
 
259
            self.pb.update(self._ellipsise_unimportant_words('OK', 13), self.testsRun, None)
174
260
        self.stream.flush()
175
261
        unittest.TestResult.addSuccess(self, test)
176
262
 
177
263
    def addSkipped(self, test, skip_excinfo):
 
264
        self.extractBenchmarkTime(test)
178
265
        if self.showAll:
179
 
            print >>self.stream, ' SKIP %s' % self._elapsedTime()
 
266
            print >>self.stream, ' SKIP %s' % self._testTimeString()
180
267
            print >>self.stream, '     %s' % skip_excinfo[1]
181
 
        elif self.dots:
 
268
        elif self.dots and self.pb is None:
182
269
            self.stream.write('S')
 
270
        elif self.dots:
 
271
            self.pb.update(self._ellipsise_unimportant_words('SKIP', 13), self.testsRun, None)
183
272
        self.stream.flush()
184
273
        # seems best to treat this as success from point-of-view of unittest
185
274
        # -- it actually does nothing so it barely matters :)
186
 
        unittest.TestResult.addSuccess(self, test)
 
275
        try:
 
276
            test.tearDown()
 
277
        except KeyboardInterrupt:
 
278
            raise
 
279
        except:
 
280
            self.addError(test, test.__exc_info())
 
281
        else:
 
282
            unittest.TestResult.addSuccess(self, test)
187
283
 
188
284
    def printErrorList(self, flavour, errors):
189
285
        for test, err in errors:
200
296
            self.stream.writeln("%s" % err)
201
297
 
202
298
 
203
 
class TextTestRunner(unittest.TextTestRunner):
 
299
class TextTestRunner(object):
204
300
    stop_on_failure = False
205
301
 
 
302
    def __init__(self,
 
303
                 stream=sys.stderr,
 
304
                 descriptions=0,
 
305
                 verbosity=1,
 
306
                 keep_output=False,
 
307
                 pb=None):
 
308
        self.stream = unittest._WritelnDecorator(stream)
 
309
        self.descriptions = descriptions
 
310
        self.verbosity = verbosity
 
311
        self.keep_output = keep_output
 
312
        self.pb = pb
 
313
 
206
314
    def _makeResult(self):
207
 
        result = _MyResult(self.stream, self.descriptions, self.verbosity)
 
315
        result = _MyResult(self.stream,
 
316
                           self.descriptions,
 
317
                           self.verbosity,
 
318
                           pb=self.pb)
208
319
        result.stop_early = self.stop_on_failure
209
320
        return result
210
321
 
 
322
    def run(self, test):
 
323
        "Run the given test case or test suite."
 
324
        result = self._makeResult()
 
325
        startTime = time.time()
 
326
        if self.pb is not None:
 
327
            self.pb.update('Running tests', 0, test.countTestCases())
 
328
        test.run(result)
 
329
        stopTime = time.time()
 
330
        timeTaken = stopTime - startTime
 
331
        result.printErrors()
 
332
        self.stream.writeln(result.separator2)
 
333
        run = result.testsRun
 
334
        self.stream.writeln("Ran %d test%s in %.3fs" %
 
335
                            (run, run != 1 and "s" or "", timeTaken))
 
336
        self.stream.writeln()
 
337
        if not result.wasSuccessful():
 
338
            self.stream.write("FAILED (")
 
339
            failed, errored = map(len, (result.failures, result.errors))
 
340
            if failed:
 
341
                self.stream.write("failures=%d" % failed)
 
342
            if errored:
 
343
                if failed: self.stream.write(", ")
 
344
                self.stream.write("errors=%d" % errored)
 
345
            self.stream.writeln(")")
 
346
        else:
 
347
            self.stream.writeln("OK")
 
348
        if self.pb is not None:
 
349
            self.pb.update('Cleaning up', 0, 1)
 
350
        # This is still a little bogus, 
 
351
        # but only a little. Folk not using our testrunner will
 
352
        # have to delete their temp directories themselves.
 
353
        test_root = TestCaseInTempDir.TEST_ROOT
 
354
        if result.wasSuccessful() or not self.keep_output:
 
355
            if test_root is not None:
 
356
                # If LANG=C we probably have created some bogus paths
 
357
                # which rmtree(unicode) will fail to delete
 
358
                # so make sure we are using rmtree(str) to delete everything
 
359
                # except on win32, where rmtree(str) will fail
 
360
                # since it doesn't have the property of byte-stream paths
 
361
                # (they are either ascii or mbcs)
 
362
                if sys.platform == 'win32':
 
363
                    # make sure we are using the unicode win32 api
 
364
                    test_root = unicode(test_root)
 
365
                else:
 
366
                    test_root = test_root.encode(
 
367
                        sys.getfilesystemencoding())
 
368
                osutils.rmtree(test_root)
 
369
        else:
 
370
            if self.pb is not None:
 
371
                self.pb.note("Failed tests working directories are in '%s'\n",
 
372
                             test_root)
 
373
            else:
 
374
                self.stream.writeln(
 
375
                    "Failed tests working directories are in '%s'\n" %
 
376
                    test_root)
 
377
        TestCaseInTempDir.TEST_ROOT = None
 
378
        if self.pb is not None:
 
379
            self.pb.clear()
 
380
        return result
 
381
 
211
382
 
212
383
def iter_suite_tests(suite):
213
384
    """Return all tests in a suite, recursing through nested suites"""
230
401
class CommandFailed(Exception):
231
402
    pass
232
403
 
 
404
 
 
405
class StringIOWrapper(object):
 
406
    """A wrapper around cStringIO which just adds an encoding attribute.
 
407
    
 
408
    Internally we can check sys.stdout to see what the output encoding
 
409
    should be. However, cStringIO has no encoding attribute that we can
 
410
    set. So we wrap it instead.
 
411
    """
 
412
    encoding='ascii'
 
413
    _cstring = None
 
414
 
 
415
    def __init__(self, s=None):
 
416
        if s is not None:
 
417
            self.__dict__['_cstring'] = StringIO(s)
 
418
        else:
 
419
            self.__dict__['_cstring'] = StringIO()
 
420
 
 
421
    def __getattr__(self, name, getattr=getattr):
 
422
        return getattr(self.__dict__['_cstring'], name)
 
423
 
 
424
    def __setattr__(self, name, val):
 
425
        if name == 'encoding':
 
426
            self.__dict__['encoding'] = val
 
427
        else:
 
428
            return setattr(self._cstring, name, val)
 
429
 
 
430
 
233
431
class TestCase(unittest.TestCase):
234
432
    """Base class for bzr unit tests.
235
433
    
251
449
    accidentally overlooked.
252
450
    """
253
451
 
254
 
    BZRPATH = 'bzr'
255
452
    _log_file_name = None
256
453
    _log_contents = ''
 
454
    # record lsprof data when performing benchmark calls.
 
455
    _gather_lsprof_in_benchmarks = False
257
456
 
258
457
    def __init__(self, methodName='testMethod'):
259
458
        super(TestCase, self).__init__(methodName)
264
463
        self._cleanEnvironment()
265
464
        bzrlib.trace.disable_default_logging()
266
465
        self._startLogFile()
 
466
        self._benchcalls = []
 
467
        self._benchtime = None
267
468
 
268
469
    def _ndiff_strings(self, a, b):
269
470
        """Return ndiff between two strings containing lines.
303
504
            raise AssertionError('string %r does not start with %r' % (s, prefix))
304
505
 
305
506
    def assertEndsWith(self, s, suffix):
306
 
        if not s.endswith(prefix):
 
507
        """Asserts that s ends with suffix."""
 
508
        if not s.endswith(suffix):
307
509
            raise AssertionError('string %r does not end with %r' % (s, suffix))
308
510
 
309
511
    def assertContainsRe(self, haystack, needle_re):
312
514
            raise AssertionError('pattern "%s" not found in "%s"'
313
515
                    % (needle_re, haystack))
314
516
 
 
517
    def assertNotContainsRe(self, haystack, needle_re):
 
518
        """Assert that a does not match a regular expression"""
 
519
        if re.search(needle_re, haystack):
 
520
            raise AssertionError('pattern "%s" found in "%s"'
 
521
                    % (needle_re, haystack))
 
522
 
315
523
    def assertSubset(self, sublist, superlist):
316
524
        """Assert that every entry in sublist is present in superlist."""
317
525
        missing = []
341
549
    def assertIsInstance(self, obj, kls):
342
550
        """Fail if obj is not an instance of kls"""
343
551
        if not isinstance(obj, kls):
344
 
            self.fail("%r is not an instance of %s" % (obj, kls))
 
552
            self.fail("%r is an instance of %s rather than %s" % (
 
553
                obj, obj.__class__, kls))
345
554
 
346
555
    def _startLogFile(self):
347
556
        """Send bzr and test log messages to a temporary file.
360
569
 
361
570
        Read contents into memory, close, and delete.
362
571
        """
 
572
        if self._log_file is None:
 
573
            return
363
574
        bzrlib.trace.disable_test_log(self._log_nonce)
364
575
        self._log_file.seek(0)
365
576
        self._log_contents = self._log_file.read()
382
593
        new_env = {
383
594
            'HOME': os.getcwd(),
384
595
            'APPDATA': os.getcwd(),
385
 
            'BZREMAIL': None,
 
596
            'BZR_EMAIL': None,
386
597
            'EMAIL': None,
387
598
        }
388
599
        self.__old_env = {}
416
627
        self._runCleanups()
417
628
        unittest.TestCase.tearDown(self)
418
629
 
 
630
    def time(self, callable, *args, **kwargs):
 
631
        """Run callable and accrue the time it takes to the benchmark time.
 
632
        
 
633
        If lsprofiling is enabled (i.e. by --lsprof-time to bzr selftest) then
 
634
        this will cause lsprofile statistics to be gathered and stored in
 
635
        self._benchcalls.
 
636
        """
 
637
        if self._benchtime is None:
 
638
            self._benchtime = 0
 
639
        start = time.time()
 
640
        try:
 
641
            if not self._gather_lsprof_in_benchmarks:
 
642
                return callable(*args, **kwargs)
 
643
            else:
 
644
                # record this benchmark
 
645
                ret, stats = bzrlib.lsprof.profile(callable, *args, **kwargs)
 
646
                stats.sort()
 
647
                self._benchcalls.append(((callable, args, kwargs), stats))
 
648
                return ret
 
649
        finally:
 
650
            self._benchtime += time.time() - start
 
651
 
419
652
    def _runCleanups(self):
420
653
        """Run registered cleanup functions. 
421
654
 
441
674
        """Shortcut that splits cmd into words, runs, and returns stdout"""
442
675
        return self.run_bzr_captured(cmd.split(), retcode=retcode)[0]
443
676
 
444
 
    def run_bzr_captured(self, argv, retcode=0):
 
677
    def run_bzr_captured(self, argv, retcode=0, encoding=None, stdin=None):
445
678
        """Invoke bzr and return (stdout, stderr).
446
679
 
447
680
        Useful for code that wants to check the contents of the
458
691
        errors, and with logging set to something approximating the
459
692
        default, so that error reporting can be checked.
460
693
 
461
 
        argv -- arguments to invoke bzr
462
 
        retcode -- expected return code, or None for don't-care.
 
694
        :param argv: arguments to invoke bzr
 
695
        :param retcode: expected return code, or None for don't-care.
 
696
        :param encoding: encoding for sys.stdout and sys.stderr
 
697
        :param stdin: A string to be used as stdin for the command.
463
698
        """
464
 
        stdout = StringIO()
465
 
        stderr = StringIO()
466
 
        self.log('run bzr: %s', ' '.join(argv))
 
699
        if encoding is None:
 
700
            encoding = bzrlib.user_encoding
 
701
        if stdin is not None:
 
702
            stdin = StringIO(stdin)
 
703
        stdout = StringIOWrapper()
 
704
        stderr = StringIOWrapper()
 
705
        stdout.encoding = encoding
 
706
        stderr.encoding = encoding
 
707
 
 
708
        self.log('run bzr: %r', argv)
467
709
        # FIXME: don't call into logging here
468
710
        handler = logging.StreamHandler(stderr)
469
 
        handler.setFormatter(bzrlib.trace.QuietFormatter())
470
711
        handler.setLevel(logging.INFO)
471
712
        logger = logging.getLogger('')
472
713
        logger.addHandler(handler)
 
714
        old_ui_factory = bzrlib.ui.ui_factory
 
715
        bzrlib.ui.ui_factory = bzrlib.tests.blackbox.TestUIFactory(
 
716
            stdout=stdout,
 
717
            stderr=stderr)
 
718
        bzrlib.ui.ui_factory.stdin = stdin
473
719
        try:
474
 
            result = self.apply_redirected(None, stdout, stderr,
 
720
            result = self.apply_redirected(stdin, stdout, stderr,
475
721
                                           bzrlib.commands.run_bzr_catch_errors,
476
722
                                           argv)
477
723
        finally:
478
724
            logger.removeHandler(handler)
 
725
            bzrlib.ui.ui_factory = old_ui_factory
 
726
 
479
727
        out = stdout.getvalue()
480
728
        err = stderr.getvalue()
481
729
        if out:
482
 
            self.log('output:\n%s', out)
 
730
            self.log('output:\n%r', out)
483
731
        if err:
484
 
            self.log('errors:\n%s', err)
 
732
            self.log('errors:\n%r', err)
485
733
        if retcode is not None:
486
 
            self.assertEquals(result, retcode)
 
734
            self.assertEquals(retcode, result)
487
735
        return out, err
488
736
 
489
737
    def run_bzr(self, *args, **kwargs):
495
743
 
496
744
        This sends the stdout/stderr results into the test's log,
497
745
        where it may be useful for debugging.  See also run_captured.
 
746
 
 
747
        :param stdin: A string to be used as stdin for the command.
498
748
        """
499
749
        retcode = kwargs.pop('retcode', 0)
500
 
        return self.run_bzr_captured(args, retcode)
 
750
        encoding = kwargs.pop('encoding', None)
 
751
        stdin = kwargs.pop('stdin', None)
 
752
        return self.run_bzr_captured(args, retcode=retcode, encoding=encoding, stdin=stdin)
 
753
 
 
754
    def run_bzr_decode(self, *args, **kwargs):
 
755
        if kwargs.has_key('encoding'):
 
756
            encoding = kwargs['encoding']
 
757
        else:
 
758
            encoding = bzrlib.user_encoding
 
759
        return self.run_bzr(*args, **kwargs)[0].decode(encoding)
 
760
 
 
761
    def run_bzr_error(self, error_regexes, *args, **kwargs):
 
762
        """Run bzr, and check that stderr contains the supplied regexes
 
763
        
 
764
        :param error_regexes: Sequence of regular expressions which 
 
765
            must each be found in the error output. The relative ordering
 
766
            is not enforced.
 
767
        :param args: command-line arguments for bzr
 
768
        :param kwargs: Keyword arguments which are interpreted by run_bzr
 
769
            This function changes the default value of retcode to be 3,
 
770
            since in most cases this is run when you expect bzr to fail.
 
771
        :return: (out, err) The actual output of running the command (in case you
 
772
                 want to do more inspection)
 
773
 
 
774
        Examples of use:
 
775
            # Make sure that commit is failing because there is nothing to do
 
776
            self.run_bzr_error(['no changes to commit'],
 
777
                               'commit', '-m', 'my commit comment')
 
778
            # Make sure --strict is handling an unknown file, rather than
 
779
            # giving us the 'nothing to do' error
 
780
            self.build_tree(['unknown'])
 
781
            self.run_bzr_error(['Commit refused because there are unknown files'],
 
782
                               'commit', '--strict', '-m', 'my commit comment')
 
783
        """
 
784
        kwargs.setdefault('retcode', 3)
 
785
        out, err = self.run_bzr(*args, **kwargs)
 
786
        for regex in error_regexes:
 
787
            self.assertContainsRe(err, regex)
 
788
        return out, err
 
789
 
 
790
    def run_bzr_subprocess(self, *args, **kwargs):
 
791
        """Run bzr in a subprocess for testing.
 
792
 
 
793
        This starts a new Python interpreter and runs bzr in there. 
 
794
        This should only be used for tests that have a justifiable need for
 
795
        this isolation: e.g. they are testing startup time, or signal
 
796
        handling, or early startup code, etc.  Subprocess code can't be 
 
797
        profiled or debugged so easily.
 
798
 
 
799
        :param retcode: The status code that is expected.  Defaults to 0.  If
 
800
        None is supplied, the status code is not checked.
 
801
        """
 
802
        bzr_path = os.path.dirname(os.path.dirname(bzrlib.__file__))+'/bzr'
 
803
        args = list(args)
 
804
        process = Popen([sys.executable, bzr_path]+args, stdout=PIPE, 
 
805
                         stderr=PIPE)
 
806
        out = process.stdout.read()
 
807
        err = process.stderr.read()
 
808
        retcode = process.wait()
 
809
        supplied_retcode = kwargs.get('retcode', 0)
 
810
        if supplied_retcode is not None:
 
811
            assert supplied_retcode == retcode
 
812
        return [out, err]
501
813
 
502
814
    def check_inventory_shape(self, inv, shape):
503
815
        """Compare an inventory to a list of expected names.
652
964
        shape is a sequence of file specifications.  If the final
653
965
        character is '/', a directory is created.
654
966
 
 
967
        This assumes that all the elements in the tree being built are new.
 
968
 
655
969
        This doesn't add anything to a branch.
656
970
        :param line_endings: Either 'binary' or 'native'
657
971
                             in binary mode, exact contents are written
662
976
                          VFS's. If the transport is readonly or None,
663
977
                          "." is opened automatically.
664
978
        """
665
 
        # XXX: It's OK to just create them using forward slashes on windows?
 
979
        # It's OK to just create them using forward slashes on windows.
666
980
        if transport is None or transport.is_readonly():
667
981
            transport = get_transport(".")
668
982
        for name in shape:
669
983
            self.assert_(isinstance(name, basestring))
670
984
            if name[-1] == '/':
671
 
                transport.mkdir(urlescape(name[:-1]))
 
985
                transport.mkdir(urlutils.escape(name[:-1]))
672
986
            else:
673
987
                if line_endings == 'binary':
674
988
                    end = '\n'
676
990
                    end = os.linesep
677
991
                else:
678
992
                    raise errors.BzrError('Invalid line ending request %r' % (line_endings,))
679
 
                content = "contents of %s%s" % (name, end)
680
 
                transport.put(urlescape(name), StringIO(content))
 
993
                content = "contents of %s%s" % (name.encode('utf-8'), end)
 
994
                # Technically 'put()' is the right command. However, put
 
995
                # uses an AtomicFile, which requires an extra rename into place
 
996
                # As long as the files didn't exist in the past, append() will
 
997
                # do the same thing as put()
 
998
                # On jam's machine, make_kernel_like_tree is:
 
999
                #   put:    4.5-7.5s (averaging 6s)
 
1000
                #   append: 2.9-4.5s
 
1001
                transport.append(urlutils.escape(name), StringIO(content))
681
1002
 
682
1003
    def build_tree_contents(self, shape):
683
1004
        build_tree_contents(shape)
693
1014
    def assertFileEqual(self, content, path):
694
1015
        """Fail if path does not contain 'content'."""
695
1016
        self.failUnless(osutils.lexists(path))
 
1017
        # TODO: jam 20060427 Shouldn't this be 'rb'?
696
1018
        self.assertEqualDiff(content, open(path, 'r').read())
697
1019
 
698
1020
 
774
1096
        if relpath is not None and relpath != '.':
775
1097
            if not base.endswith('/'):
776
1098
                base = base + '/'
777
 
            base = base + relpath
 
1099
            base = base + urlutils.escape(relpath)
778
1100
        return base
779
1101
 
780
1102
    def get_transport(self):
793
1115
        self.assertTrue(t.is_readonly())
794
1116
        return t
795
1117
 
796
 
    def make_branch(self, relpath):
 
1118
    def make_branch(self, relpath, format=None):
797
1119
        """Create a branch on the transport at relpath."""
798
 
        repo = self.make_repository(relpath)
 
1120
        repo = self.make_repository(relpath, format=format)
799
1121
        return repo.bzrdir.create_branch()
800
1122
 
801
 
    def make_bzrdir(self, relpath):
 
1123
    def make_bzrdir(self, relpath, format=None):
802
1124
        try:
803
1125
            url = self.get_url(relpath)
804
 
            segments = relpath.split('/')
 
1126
            mutter('relpath %r => url %r', relpath, url)
 
1127
            segments = url.split('/')
805
1128
            if segments and segments[-1] not in ('', '.'):
806
 
                parent = self.get_url('/'.join(segments[:-1]))
 
1129
                parent = '/'.join(segments[:-1])
807
1130
                t = get_transport(parent)
808
1131
                try:
809
1132
                    t.mkdir(segments[-1])
810
1133
                except errors.FileExists:
811
1134
                    pass
812
 
            return bzrlib.bzrdir.BzrDir.create(url)
 
1135
            if format is None:
 
1136
                format=bzrlib.bzrdir.BzrDirFormat.get_default_format()
 
1137
            # FIXME: make this use a single transport someday. RBC 20060418
 
1138
            return format.initialize_on_transport(get_transport(relpath))
813
1139
        except errors.UninitializableFormat:
814
 
            raise TestSkipped("Format %s is not initializable.")
 
1140
            raise TestSkipped("Format %s is not initializable." % format)
815
1141
 
816
 
    def make_repository(self, relpath, shared=False):
 
1142
    def make_repository(self, relpath, shared=False, format=None):
817
1143
        """Create a repository on our default transport at relpath."""
818
 
        made_control = self.make_bzrdir(relpath)
 
1144
        made_control = self.make_bzrdir(relpath, format=format)
819
1145
        return made_control.create_repository(shared=shared)
820
1146
 
821
 
    def make_branch_and_tree(self, relpath):
 
1147
    def make_branch_and_tree(self, relpath, format=None):
822
1148
        """Create a branch on the transport and a tree locally.
823
1149
 
824
1150
        Returns the tree.
827
1153
        # this obviously requires a format that supports branch references
828
1154
        # so check for that by checking bzrdir.BzrDirFormat.get_default_format()
829
1155
        # RBC 20060208
830
 
        b = self.make_branch(relpath)
 
1156
        b = self.make_branch(relpath, format=format)
831
1157
        try:
832
1158
            return b.bzrdir.create_workingtree()
833
1159
        except errors.NotLocalUrl:
872
1198
 
873
1199
 
874
1200
def filter_suite_by_re(suite, pattern):
875
 
    result = TestSuite()
 
1201
    result = TestUtil.TestSuite()
876
1202
    filter_re = re.compile(pattern)
877
1203
    for test in iter_suite_tests(suite):
878
1204
        if filter_re.search(test.id()):
882
1208
 
883
1209
def run_suite(suite, name='test', verbose=False, pattern=".*",
884
1210
              stop_on_failure=False, keep_output=False,
885
 
              transport=None):
 
1211
              transport=None, lsprof_timed=None):
886
1212
    TestCaseInTempDir._TEST_NAME = name
 
1213
    TestCase._gather_lsprof_in_benchmarks = lsprof_timed
887
1214
    if verbose:
888
1215
        verbosity = 2
 
1216
        pb = None
889
1217
    else:
890
1218
        verbosity = 1
 
1219
        pb = progress.ProgressBar()
891
1220
    runner = TextTestRunner(stream=sys.stdout,
892
1221
                            descriptions=0,
893
 
                            verbosity=verbosity)
 
1222
                            verbosity=verbosity,
 
1223
                            keep_output=keep_output,
 
1224
                            pb=pb)
894
1225
    runner.stop_on_failure=stop_on_failure
895
1226
    if pattern != '.*':
896
1227
        suite = filter_suite_by_re(suite, pattern)
897
1228
    result = runner.run(suite)
898
 
    # This is still a little bogus, 
899
 
    # but only a little. Folk not using our testrunner will
900
 
    # have to delete their temp directories themselves.
901
 
    test_root = TestCaseInTempDir.TEST_ROOT
902
 
    if result.wasSuccessful() or not keep_output:
903
 
        if test_root is not None:
904
 
            print 'Deleting test root %s...' % test_root
905
 
            try:
906
 
                shutil.rmtree(test_root)
907
 
            finally:
908
 
                print
909
 
    else:
910
 
        print "Failed tests working directories are in '%s'\n" % TestCaseInTempDir.TEST_ROOT
911
1229
    return result.wasSuccessful()
912
1230
 
913
1231
 
914
1232
def selftest(verbose=False, pattern=".*", stop_on_failure=True,
915
1233
             keep_output=False,
916
 
             transport=None):
 
1234
             transport=None,
 
1235
             test_suite_factory=None,
 
1236
             lsprof_timed=None):
917
1237
    """Run the whole test suite under the enhanced runner"""
918
1238
    global default_transport
919
1239
    if transport is None:
920
1240
        transport = default_transport
921
1241
    old_transport = default_transport
922
1242
    default_transport = transport
923
 
    suite = test_suite()
924
1243
    try:
 
1244
        if test_suite_factory is None:
 
1245
            suite = test_suite()
 
1246
        else:
 
1247
            suite = test_suite_factory()
925
1248
        return run_suite(suite, 'testbzr', verbose=verbose, pattern=pattern,
926
1249
                     stop_on_failure=stop_on_failure, keep_output=keep_output,
927
 
                     transport=transport)
 
1250
                     transport=transport,
 
1251
                     lsprof_timed=lsprof_timed)
928
1252
    finally:
929
1253
        default_transport = old_transport
930
1254
 
931
1255
 
932
 
 
933
1256
def test_suite():
934
 
    """Build and return TestSuite for the whole program."""
935
 
    from doctest import DocTestSuite
936
 
 
937
 
    global MODULES_TO_DOCTEST
938
 
 
939
 
    testmod_names = [ \
 
1257
    """Build and return TestSuite for the whole of bzrlib.
 
1258
    
 
1259
    This function can be replaced if you need to change the default test
 
1260
    suite on a global basis, but it is not encouraged.
 
1261
    """
 
1262
    testmod_names = [
940
1263
                   'bzrlib.tests.test_ancestry',
941
 
                   'bzrlib.tests.test_annotate',
942
1264
                   'bzrlib.tests.test_api',
 
1265
                   'bzrlib.tests.test_atomicfile',
943
1266
                   'bzrlib.tests.test_bad_files',
944
 
                   'bzrlib.tests.test_basis_inventory',
945
1267
                   'bzrlib.tests.test_branch',
 
1268
                   'bzrlib.tests.test_bundle',
946
1269
                   'bzrlib.tests.test_bzrdir',
947
1270
                   'bzrlib.tests.test_command',
948
1271
                   'bzrlib.tests.test_commit',
959
1282
                   'bzrlib.tests.test_graph',
960
1283
                   'bzrlib.tests.test_hashcache',
961
1284
                   'bzrlib.tests.test_http',
 
1285
                   'bzrlib.tests.test_http_response',
962
1286
                   'bzrlib.tests.test_identitymap',
 
1287
                   'bzrlib.tests.test_ignores',
963
1288
                   'bzrlib.tests.test_inv',
964
1289
                   'bzrlib.tests.test_knit',
965
1290
                   'bzrlib.tests.test_lockdir',
973
1298
                   'bzrlib.tests.test_nonascii',
974
1299
                   'bzrlib.tests.test_options',
975
1300
                   'bzrlib.tests.test_osutils',
 
1301
                   'bzrlib.tests.test_patch',
 
1302
                   'bzrlib.tests.test_patches',
976
1303
                   'bzrlib.tests.test_permissions',
977
1304
                   'bzrlib.tests.test_plugins',
978
1305
                   'bzrlib.tests.test_progress',
980
1307
                   'bzrlib.tests.test_repository',
981
1308
                   'bzrlib.tests.test_revision',
982
1309
                   'bzrlib.tests.test_revisionnamespaces',
983
 
                   'bzrlib.tests.test_revprops',
 
1310
                   'bzrlib.tests.test_revisiontree',
984
1311
                   'bzrlib.tests.test_rio',
985
1312
                   'bzrlib.tests.test_sampler',
986
1313
                   'bzrlib.tests.test_selftest',
988
1315
                   'bzrlib.tests.test_sftp_transport',
989
1316
                   'bzrlib.tests.test_smart_add',
990
1317
                   'bzrlib.tests.test_source',
 
1318
                   'bzrlib.tests.test_status',
991
1319
                   'bzrlib.tests.test_store',
992
1320
                   'bzrlib.tests.test_symbol_versioning',
993
1321
                   'bzrlib.tests.test_testament',
 
1322
                   'bzrlib.tests.test_textfile',
 
1323
                   'bzrlib.tests.test_textmerge',
994
1324
                   'bzrlib.tests.test_trace',
995
1325
                   'bzrlib.tests.test_transactions',
996
1326
                   'bzrlib.tests.test_transform',
997
1327
                   'bzrlib.tests.test_transport',
 
1328
                   'bzrlib.tests.test_tree',
998
1329
                   'bzrlib.tests.test_tsort',
 
1330
                   'bzrlib.tests.test_tuned_gzip',
999
1331
                   'bzrlib.tests.test_ui',
1000
1332
                   'bzrlib.tests.test_upgrade',
 
1333
                   'bzrlib.tests.test_urlutils',
1001
1334
                   'bzrlib.tests.test_versionedfile',
1002
1335
                   'bzrlib.tests.test_weave',
1003
1336
                   'bzrlib.tests.test_whitebox',
1005
1338
                   'bzrlib.tests.test_xml',
1006
1339
                   ]
1007
1340
    test_transport_implementations = [
1008
 
        'bzrlib.tests.test_transport_implementations']
1009
 
 
1010
 
    TestCase.BZRPATH = osutils.pathjoin(
1011
 
            osutils.realpath(osutils.dirname(bzrlib.__path__[0])), 'bzr')
1012
 
    print '%10s: %s' % ('bzr', osutils.realpath(sys.argv[0]))
1013
 
    print '%10s: %s' % ('bzrlib', bzrlib.__path__[0])
1014
 
    print
1015
 
    suite = TestSuite()
1016
 
    # python2.4's TestLoader.loadTestsFromNames gives very poor 
1017
 
    # errors if it fails to load a named module - no indication of what's
1018
 
    # actually wrong, just "no such module".  We should probably override that
1019
 
    # class, but for the moment just load them ourselves. (mbp 20051202)
1020
 
    loader = TestLoader()
 
1341
        'bzrlib.tests.test_transport_implementations',
 
1342
        'bzrlib.tests.test_read_bundle',
 
1343
        ]
 
1344
    suite = TestUtil.TestSuite()
 
1345
    loader = TestUtil.TestLoader()
 
1346
    suite.addTest(loader.loadTestsFromModuleNames(testmod_names))
1021
1347
    from bzrlib.transport import TransportTestProviderAdapter
1022
1348
    adapter = TransportTestProviderAdapter()
1023
1349
    adapt_modules(test_transport_implementations, adapter, loader, suite)
1024
 
    for mod_name in testmod_names:
1025
 
        mod = _load_module_by_name(mod_name)
1026
 
        suite.addTest(loader.loadTestsFromModule(mod))
1027
1350
    for package in packages_to_test():
1028
1351
        suite.addTest(package.test_suite())
1029
1352
    for m in MODULES_TO_TEST:
1030
1353
        suite.addTest(loader.loadTestsFromModule(m))
1031
 
    for m in (MODULES_TO_DOCTEST):
1032
 
        suite.addTest(DocTestSuite(m))
 
1354
    for m in MODULES_TO_DOCTEST:
 
1355
        suite.addTest(doctest.DocTestSuite(m))
1033
1356
    for name, plugin in bzrlib.plugin.all_plugins().items():
1034
1357
        if getattr(plugin, 'test_suite', None) is not None:
1035
1358
            suite.addTest(plugin.test_suite())
1038
1361
 
1039
1362
def adapt_modules(mods_list, adapter, loader, suite):
1040
1363
    """Adapt the modules in mods_list using adapter and add to suite."""
1041
 
    for mod_name in mods_list:
1042
 
        mod = _load_module_by_name(mod_name)
1043
 
        for test in iter_suite_tests(loader.loadTestsFromModule(mod)):
1044
 
            suite.addTests(adapter.adapt(test))
1045
 
 
1046
 
 
1047
 
def _load_module_by_name(mod_name):
1048
 
    parts = mod_name.split('.')
1049
 
    module = __import__(mod_name)
1050
 
    del parts[0]
1051
 
    # for historical reasons python returns the top-level module even though
1052
 
    # it loads the submodule; we need to walk down to get the one we want.
1053
 
    while parts:
1054
 
        module = getattr(module, parts.pop(0))
1055
 
    return module
 
1364
    for test in iter_suite_tests(loader.loadTestsFromModuleNames(mods_list)):
 
1365
        suite.addTests(adapter.adapt(test))