/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/tests/__init__.py

  • Committer: John Arbash Meinel
  • Date: 2006-10-10 06:48:45 UTC
  • mto: This revision was merged to the branch mainline in revision 2069.
  • Revision ID: john@arbash-meinel.com-20061010064845-173353db11a009a0
review feedback from Martin

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2005, 2006 by Canonical Ltd
 
2
#
 
3
# This program is free software; you can redistribute it and/or modify
 
4
# it under the terms of the GNU General Public License as published by
 
5
# the Free Software Foundation; either version 2 of the License, or
 
6
# (at your option) any later version.
 
7
#
 
8
# This program is distributed in the hope that it will be useful,
 
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
11
# GNU General Public License for more details.
 
12
#
 
13
# You should have received a copy of the GNU General Public License
 
14
# along with this program; if not, write to the Free Software
 
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
16
 
 
17
 
 
18
# TODO: Perhaps there should be an API to find out if bzr running under the
 
19
# test suite -- some plugins might want to avoid making intrusive changes if
 
20
# this is the case.  However, we want behaviour under to test to diverge as
 
21
# little as possible, so this should be used rarely if it's added at all.
 
22
# (Suggestion from j-a-meinel, 2005-11-24)
 
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
import codecs
 
30
from cStringIO import StringIO
 
31
import difflib
 
32
import doctest
 
33
import errno
 
34
import logging
 
35
import os
 
36
import re
 
37
import shlex
 
38
import stat
 
39
from subprocess import Popen, PIPE
 
40
import sys
 
41
import tempfile
 
42
import unittest
 
43
import time
 
44
 
 
45
 
 
46
from bzrlib import memorytree
 
47
import bzrlib.branch
 
48
import bzrlib.bzrdir as bzrdir
 
49
import bzrlib.commands
 
50
import bzrlib.bundle.serializer
 
51
import bzrlib.errors as errors
 
52
import bzrlib.export
 
53
import bzrlib.inventory
 
54
import bzrlib.iterablefile
 
55
import bzrlib.lockdir
 
56
try:
 
57
    import bzrlib.lsprof
 
58
except ImportError:
 
59
    # lsprof not available
 
60
    pass
 
61
from bzrlib.merge import merge_inner
 
62
import bzrlib.merge3
 
63
import bzrlib.osutils
 
64
import bzrlib.osutils as osutils
 
65
import bzrlib.plugin
 
66
import bzrlib.progress as progress
 
67
from bzrlib.revision import common_ancestor
 
68
import bzrlib.store
 
69
from bzrlib import symbol_versioning
 
70
import bzrlib.trace
 
71
from bzrlib.transport import get_transport
 
72
import bzrlib.transport
 
73
from bzrlib.transport.local import LocalRelpathServer
 
74
from bzrlib.transport.memory import MemoryServer
 
75
from bzrlib.transport.readonly import ReadonlyServer
 
76
from bzrlib.trace import mutter
 
77
from bzrlib.tests import TestUtil
 
78
from bzrlib.tests.TestUtil import (
 
79
                          TestSuite,
 
80
                          TestLoader,
 
81
                          )
 
82
from bzrlib.tests.treeshape import build_tree_contents
 
83
import bzrlib.urlutils as urlutils
 
84
from bzrlib.workingtree import WorkingTree, WorkingTreeFormat2
 
85
 
 
86
default_transport = LocalRelpathServer
 
87
 
 
88
MODULES_TO_TEST = []
 
89
MODULES_TO_DOCTEST = [
 
90
                      bzrlib.branch,
 
91
                      bzrlib.bundle.serializer,
 
92
                      bzrlib.commands,
 
93
                      bzrlib.errors,
 
94
                      bzrlib.export,
 
95
                      bzrlib.inventory,
 
96
                      bzrlib.iterablefile,
 
97
                      bzrlib.lockdir,
 
98
                      bzrlib.merge3,
 
99
                      bzrlib.option,
 
100
                      bzrlib.osutils,
 
101
                      bzrlib.store,
 
102
                      bzrlib.transport,
 
103
                      ]
 
104
 
 
105
 
 
106
def packages_to_test():
 
107
    """Return a list of packages to test.
 
108
 
 
109
    The packages are not globally imported so that import failures are
 
110
    triggered when running selftest, not when importing the command.
 
111
    """
 
112
    import bzrlib.doc
 
113
    import bzrlib.tests.blackbox
 
114
    import bzrlib.tests.branch_implementations
 
115
    import bzrlib.tests.bzrdir_implementations
 
116
    import bzrlib.tests.interrepository_implementations
 
117
    import bzrlib.tests.interversionedfile_implementations
 
118
    import bzrlib.tests.intertree_implementations
 
119
    import bzrlib.tests.repository_implementations
 
120
    import bzrlib.tests.revisionstore_implementations
 
121
    import bzrlib.tests.tree_implementations
 
122
    import bzrlib.tests.workingtree_implementations
 
123
    return [
 
124
            bzrlib.doc,
 
125
            bzrlib.tests.blackbox,
 
126
            bzrlib.tests.branch_implementations,
 
127
            bzrlib.tests.bzrdir_implementations,
 
128
            bzrlib.tests.interrepository_implementations,
 
129
            bzrlib.tests.interversionedfile_implementations,
 
130
            bzrlib.tests.intertree_implementations,
 
131
            bzrlib.tests.repository_implementations,
 
132
            bzrlib.tests.revisionstore_implementations,
 
133
            bzrlib.tests.tree_implementations,
 
134
            bzrlib.tests.workingtree_implementations,
 
135
            ]
 
136
 
 
137
 
 
138
class _MyResult(unittest._TextTestResult):
 
139
    """Custom TestResult.
 
140
 
 
141
    Shows output in a different format, including displaying runtime for tests.
 
142
    """
 
143
    stop_early = False
 
144
    
 
145
    def __init__(self, stream, descriptions, verbosity, pb=None,
 
146
                 bench_history=None):
 
147
        """Construct new TestResult.
 
148
 
 
149
        :param bench_history: Optionally, a writable file object to accumulate
 
150
            benchmark results.
 
151
        """
 
152
        unittest._TextTestResult.__init__(self, stream, descriptions, verbosity)
 
153
        self.pb = pb
 
154
        if bench_history is not None:
 
155
            from bzrlib.version import _get_bzr_source_tree
 
156
            src_tree = _get_bzr_source_tree()
 
157
            if src_tree:
 
158
                try:
 
159
                    revision_id = src_tree.get_parent_ids()[0]
 
160
                except IndexError:
 
161
                    # XXX: if this is a brand new tree, do the same as if there
 
162
                    # is no branch.
 
163
                    revision_id = ''
 
164
            else:
 
165
                # XXX: If there's no branch, what should we do?
 
166
                revision_id = ''
 
167
            bench_history.write("--date %s %s\n" % (time.time(), revision_id))
 
168
        self._bench_history = bench_history
 
169
    
 
170
    def extractBenchmarkTime(self, testCase):
 
171
        """Add a benchmark time for the current test case."""
 
172
        self._benchmarkTime = getattr(testCase, "_benchtime", None)
 
173
    
 
174
    def _elapsedTestTimeString(self):
 
175
        """Return a time string for the overall time the current test has taken."""
 
176
        return self._formatTime(time.time() - self._start_time)
 
177
 
 
178
    def _testTimeString(self):
 
179
        if self._benchmarkTime is not None:
 
180
            return "%s/%s" % (
 
181
                self._formatTime(self._benchmarkTime),
 
182
                self._elapsedTestTimeString())
 
183
        else:
 
184
            return "      %s" % self._elapsedTestTimeString()
 
185
 
 
186
    def _formatTime(self, seconds):
 
187
        """Format seconds as milliseconds with leading spaces."""
 
188
        return "%5dms" % (1000 * seconds)
 
189
 
 
190
    def _ellipsise_unimportant_words(self, a_string, final_width,
 
191
                                   keep_start=False):
 
192
        """Add ellipses (sp?) for overly long strings.
 
193
        
 
194
        :param keep_start: If true preserve the start of a_string rather
 
195
                           than the end of it.
 
196
        """
 
197
        if keep_start:
 
198
            if len(a_string) > final_width:
 
199
                result = a_string[:final_width-3] + '...'
 
200
            else:
 
201
                result = a_string
 
202
        else:
 
203
            if len(a_string) > final_width:
 
204
                result = '...' + a_string[3-final_width:]
 
205
            else:
 
206
                result = a_string
 
207
        return result.ljust(final_width)
 
208
 
 
209
    def startTest(self, test):
 
210
        unittest.TestResult.startTest(self, test)
 
211
        # In a short description, the important words are in
 
212
        # the beginning, but in an id, the important words are
 
213
        # at the end
 
214
        SHOW_DESCRIPTIONS = False
 
215
 
 
216
        if not self.showAll and self.dots and self.pb is not None:
 
217
            final_width = 13
 
218
        else:
 
219
            final_width = osutils.terminal_width()
 
220
            final_width = final_width - 15 - 8
 
221
        what = None
 
222
        if SHOW_DESCRIPTIONS:
 
223
            what = test.shortDescription()
 
224
            if what:
 
225
                what = self._ellipsise_unimportant_words(what, final_width, keep_start=True)
 
226
        if what is None:
 
227
            what = test.id()
 
228
            if what.startswith('bzrlib.tests.'):
 
229
                what = what[13:]
 
230
            what = self._ellipsise_unimportant_words(what, final_width)
 
231
        if self.showAll:
 
232
            self.stream.write(what)
 
233
        elif self.dots and self.pb is not None:
 
234
            self.pb.update(what, self.testsRun - 1, None)
 
235
        self.stream.flush()
 
236
        self._recordTestStartTime()
 
237
 
 
238
    def _recordTestStartTime(self):
 
239
        """Record that a test has started."""
 
240
        self._start_time = time.time()
 
241
 
 
242
    def addError(self, test, err):
 
243
        if isinstance(err[1], TestSkipped):
 
244
            return self.addSkipped(test, err)    
 
245
        unittest.TestResult.addError(self, test, err)
 
246
        # We can only do this if we have one of our TestCases, not if
 
247
        # we have a doctest.
 
248
        setKeepLogfile = getattr(test, 'setKeepLogfile', None)
 
249
        if setKeepLogfile is not None:
 
250
            setKeepLogfile()
 
251
        self.extractBenchmarkTime(test)
 
252
        if self.showAll:
 
253
            self.stream.writeln("ERROR %s" % self._testTimeString())
 
254
        elif self.dots and self.pb is None:
 
255
            self.stream.write('E')
 
256
        elif self.dots:
 
257
            self.pb.update(self._ellipsise_unimportant_words('ERROR', 13), self.testsRun, None)
 
258
            self.pb.note(self._ellipsise_unimportant_words(
 
259
                            test.id() + ': ERROR',
 
260
                            osutils.terminal_width()))
 
261
        self.stream.flush()
 
262
        if self.stop_early:
 
263
            self.stop()
 
264
 
 
265
    def addFailure(self, test, err):
 
266
        unittest.TestResult.addFailure(self, test, err)
 
267
        # We can only do this if we have one of our TestCases, not if
 
268
        # we have a doctest.
 
269
        setKeepLogfile = getattr(test, 'setKeepLogfile', None)
 
270
        if setKeepLogfile is not None:
 
271
            setKeepLogfile()
 
272
        self.extractBenchmarkTime(test)
 
273
        if self.showAll:
 
274
            self.stream.writeln(" FAIL %s" % self._testTimeString())
 
275
        elif self.dots and self.pb is None:
 
276
            self.stream.write('F')
 
277
        elif self.dots:
 
278
            self.pb.update(self._ellipsise_unimportant_words('FAIL', 13), self.testsRun, None)
 
279
            self.pb.note(self._ellipsise_unimportant_words(
 
280
                            test.id() + ': FAIL',
 
281
                            osutils.terminal_width()))
 
282
        self.stream.flush()
 
283
        if self.stop_early:
 
284
            self.stop()
 
285
 
 
286
    def addSuccess(self, test):
 
287
        self.extractBenchmarkTime(test)
 
288
        if self._bench_history is not None:
 
289
            if self._benchmarkTime is not None:
 
290
                self._bench_history.write("%s %s\n" % (
 
291
                    self._formatTime(self._benchmarkTime),
 
292
                    test.id()))
 
293
        if self.showAll:
 
294
            self.stream.writeln('   OK %s' % self._testTimeString())
 
295
            for bench_called, stats in getattr(test, '_benchcalls', []):
 
296
                self.stream.writeln('LSProf output for %s(%s, %s)' % bench_called)
 
297
                stats.pprint(file=self.stream)
 
298
        elif self.dots and self.pb is None:
 
299
            self.stream.write('~')
 
300
        elif self.dots:
 
301
            self.pb.update(self._ellipsise_unimportant_words('OK', 13), self.testsRun, None)
 
302
        self.stream.flush()
 
303
        unittest.TestResult.addSuccess(self, test)
 
304
 
 
305
    def addSkipped(self, test, skip_excinfo):
 
306
        self.extractBenchmarkTime(test)
 
307
        if self.showAll:
 
308
            print >>self.stream, ' SKIP %s' % self._testTimeString()
 
309
            print >>self.stream, '     %s' % skip_excinfo[1]
 
310
        elif self.dots and self.pb is None:
 
311
            self.stream.write('S')
 
312
        elif self.dots:
 
313
            self.pb.update(self._ellipsise_unimportant_words('SKIP', 13), self.testsRun, None)
 
314
        self.stream.flush()
 
315
        # seems best to treat this as success from point-of-view of unittest
 
316
        # -- it actually does nothing so it barely matters :)
 
317
        try:
 
318
            test.tearDown()
 
319
        except KeyboardInterrupt:
 
320
            raise
 
321
        except:
 
322
            self.addError(test, test.__exc_info())
 
323
        else:
 
324
            unittest.TestResult.addSuccess(self, test)
 
325
 
 
326
    def printErrorList(self, flavour, errors):
 
327
        for test, err in errors:
 
328
            self.stream.writeln(self.separator1)
 
329
            self.stream.writeln("%s: %s" % (flavour, self.getDescription(test)))
 
330
            if getattr(test, '_get_log', None) is not None:
 
331
                print >>self.stream
 
332
                print >>self.stream, \
 
333
                        ('vvvv[log from %s]' % test.id()).ljust(78,'-')
 
334
                print >>self.stream, test._get_log()
 
335
                print >>self.stream, \
 
336
                        ('^^^^[log from %s]' % test.id()).ljust(78,'-')
 
337
            self.stream.writeln(self.separator2)
 
338
            self.stream.writeln("%s" % err)
 
339
 
 
340
 
 
341
class TextTestRunner(object):
 
342
    stop_on_failure = False
 
343
 
 
344
    def __init__(self,
 
345
                 stream=sys.stderr,
 
346
                 descriptions=0,
 
347
                 verbosity=1,
 
348
                 keep_output=False,
 
349
                 pb=None,
 
350
                 bench_history=None):
 
351
        self.stream = unittest._WritelnDecorator(stream)
 
352
        self.descriptions = descriptions
 
353
        self.verbosity = verbosity
 
354
        self.keep_output = keep_output
 
355
        self.pb = pb
 
356
        self._bench_history = bench_history
 
357
 
 
358
    def _makeResult(self):
 
359
        result = _MyResult(self.stream,
 
360
                           self.descriptions,
 
361
                           self.verbosity,
 
362
                           pb=self.pb,
 
363
                           bench_history=self._bench_history)
 
364
        result.stop_early = self.stop_on_failure
 
365
        return result
 
366
 
 
367
    def run(self, test):
 
368
        "Run the given test case or test suite."
 
369
        result = self._makeResult()
 
370
        startTime = time.time()
 
371
        if self.pb is not None:
 
372
            self.pb.update('Running tests', 0, test.countTestCases())
 
373
        test.run(result)
 
374
        stopTime = time.time()
 
375
        timeTaken = stopTime - startTime
 
376
        result.printErrors()
 
377
        self.stream.writeln(result.separator2)
 
378
        run = result.testsRun
 
379
        self.stream.writeln("Ran %d test%s in %.3fs" %
 
380
                            (run, run != 1 and "s" or "", timeTaken))
 
381
        self.stream.writeln()
 
382
        if not result.wasSuccessful():
 
383
            self.stream.write("FAILED (")
 
384
            failed, errored = map(len, (result.failures, result.errors))
 
385
            if failed:
 
386
                self.stream.write("failures=%d" % failed)
 
387
            if errored:
 
388
                if failed: self.stream.write(", ")
 
389
                self.stream.write("errors=%d" % errored)
 
390
            self.stream.writeln(")")
 
391
        else:
 
392
            self.stream.writeln("OK")
 
393
        if self.pb is not None:
 
394
            self.pb.update('Cleaning up', 0, 1)
 
395
        # This is still a little bogus, 
 
396
        # but only a little. Folk not using our testrunner will
 
397
        # have to delete their temp directories themselves.
 
398
        test_root = TestCaseWithMemoryTransport.TEST_ROOT
 
399
        if result.wasSuccessful() or not self.keep_output:
 
400
            if test_root is not None:
 
401
                # If LANG=C we probably have created some bogus paths
 
402
                # which rmtree(unicode) will fail to delete
 
403
                # so make sure we are using rmtree(str) to delete everything
 
404
                # except on win32, where rmtree(str) will fail
 
405
                # since it doesn't have the property of byte-stream paths
 
406
                # (they are either ascii or mbcs)
 
407
                if sys.platform == 'win32':
 
408
                    # make sure we are using the unicode win32 api
 
409
                    test_root = unicode(test_root)
 
410
                else:
 
411
                    test_root = test_root.encode(
 
412
                        sys.getfilesystemencoding())
 
413
                osutils.rmtree(test_root)
 
414
        else:
 
415
            if self.pb is not None:
 
416
                self.pb.note("Failed tests working directories are in '%s'\n",
 
417
                             test_root)
 
418
            else:
 
419
                self.stream.writeln(
 
420
                    "Failed tests working directories are in '%s'\n" %
 
421
                    test_root)
 
422
        TestCaseWithMemoryTransport.TEST_ROOT = None
 
423
        if self.pb is not None:
 
424
            self.pb.clear()
 
425
        return result
 
426
 
 
427
 
 
428
def iter_suite_tests(suite):
 
429
    """Return all tests in a suite, recursing through nested suites"""
 
430
    for item in suite._tests:
 
431
        if isinstance(item, unittest.TestCase):
 
432
            yield item
 
433
        elif isinstance(item, unittest.TestSuite):
 
434
            for r in iter_suite_tests(item):
 
435
                yield r
 
436
        else:
 
437
            raise Exception('unknown object %r inside test suite %r'
 
438
                            % (item, suite))
 
439
 
 
440
 
 
441
class TestSkipped(Exception):
 
442
    """Indicates that a test was intentionally skipped, rather than failing."""
 
443
 
 
444
 
 
445
class CommandFailed(Exception):
 
446
    pass
 
447
 
 
448
 
 
449
class StringIOWrapper(object):
 
450
    """A wrapper around cStringIO which just adds an encoding attribute.
 
451
    
 
452
    Internally we can check sys.stdout to see what the output encoding
 
453
    should be. However, cStringIO has no encoding attribute that we can
 
454
    set. So we wrap it instead.
 
455
    """
 
456
    encoding='ascii'
 
457
    _cstring = None
 
458
 
 
459
    def __init__(self, s=None):
 
460
        if s is not None:
 
461
            self.__dict__['_cstring'] = StringIO(s)
 
462
        else:
 
463
            self.__dict__['_cstring'] = StringIO()
 
464
 
 
465
    def __getattr__(self, name, getattr=getattr):
 
466
        return getattr(self.__dict__['_cstring'], name)
 
467
 
 
468
    def __setattr__(self, name, val):
 
469
        if name == 'encoding':
 
470
            self.__dict__['encoding'] = val
 
471
        else:
 
472
            return setattr(self._cstring, name, val)
 
473
 
 
474
 
 
475
class TestCase(unittest.TestCase):
 
476
    """Base class for bzr unit tests.
 
477
    
 
478
    Tests that need access to disk resources should subclass 
 
479
    TestCaseInTempDir not TestCase.
 
480
 
 
481
    Error and debug log messages are redirected from their usual
 
482
    location into a temporary file, the contents of which can be
 
483
    retrieved by _get_log().  We use a real OS file, not an in-memory object,
 
484
    so that it can also capture file IO.  When the test completes this file
 
485
    is read into memory and removed from disk.
 
486
       
 
487
    There are also convenience functions to invoke bzr's command-line
 
488
    routine, and to build and check bzr trees.
 
489
   
 
490
    In addition to the usual method of overriding tearDown(), this class also
 
491
    allows subclasses to register functions into the _cleanups list, which is
 
492
    run in order as the object is torn down.  It's less likely this will be
 
493
    accidentally overlooked.
 
494
    """
 
495
 
 
496
    _log_file_name = None
 
497
    _log_contents = ''
 
498
    _keep_log_file = False
 
499
    # record lsprof data when performing benchmark calls.
 
500
    _gather_lsprof_in_benchmarks = False
 
501
 
 
502
    def __init__(self, methodName='testMethod'):
 
503
        super(TestCase, self).__init__(methodName)
 
504
        self._cleanups = []
 
505
 
 
506
    def setUp(self):
 
507
        unittest.TestCase.setUp(self)
 
508
        self._cleanEnvironment()
 
509
        bzrlib.trace.disable_default_logging()
 
510
        self._startLogFile()
 
511
        self._benchcalls = []
 
512
        self._benchtime = None
 
513
 
 
514
    def _ndiff_strings(self, a, b):
 
515
        """Return ndiff between two strings containing lines.
 
516
        
 
517
        A trailing newline is added if missing to make the strings
 
518
        print properly."""
 
519
        if b and b[-1] != '\n':
 
520
            b += '\n'
 
521
        if a and a[-1] != '\n':
 
522
            a += '\n'
 
523
        difflines = difflib.ndiff(a.splitlines(True),
 
524
                                  b.splitlines(True),
 
525
                                  linejunk=lambda x: False,
 
526
                                  charjunk=lambda x: False)
 
527
        return ''.join(difflines)
 
528
 
 
529
    def assertEqualDiff(self, a, b, message=None):
 
530
        """Assert two texts are equal, if not raise an exception.
 
531
        
 
532
        This is intended for use with multi-line strings where it can 
 
533
        be hard to find the differences by eye.
 
534
        """
 
535
        # TODO: perhaps override assertEquals to call this for strings?
 
536
        if a == b:
 
537
            return
 
538
        if message is None:
 
539
            message = "texts not equal:\n"
 
540
        raise AssertionError(message + 
 
541
                             self._ndiff_strings(a, b))      
 
542
        
 
543
    def assertEqualMode(self, mode, mode_test):
 
544
        self.assertEqual(mode, mode_test,
 
545
                         'mode mismatch %o != %o' % (mode, mode_test))
 
546
 
 
547
    def assertStartsWith(self, s, prefix):
 
548
        if not s.startswith(prefix):
 
549
            raise AssertionError('string %r does not start with %r' % (s, prefix))
 
550
 
 
551
    def assertEndsWith(self, s, suffix):
 
552
        """Asserts that s ends with suffix."""
 
553
        if not s.endswith(suffix):
 
554
            raise AssertionError('string %r does not end with %r' % (s, suffix))
 
555
 
 
556
    def assertContainsRe(self, haystack, needle_re):
 
557
        """Assert that a contains something matching a regular expression."""
 
558
        if not re.search(needle_re, haystack):
 
559
            raise AssertionError('pattern "%s" not found in "%s"'
 
560
                    % (needle_re, haystack))
 
561
 
 
562
    def assertNotContainsRe(self, haystack, needle_re):
 
563
        """Assert that a does not match a regular expression"""
 
564
        if re.search(needle_re, haystack):
 
565
            raise AssertionError('pattern "%s" found in "%s"'
 
566
                    % (needle_re, haystack))
 
567
 
 
568
    def assertSubset(self, sublist, superlist):
 
569
        """Assert that every entry in sublist is present in superlist."""
 
570
        missing = []
 
571
        for entry in sublist:
 
572
            if entry not in superlist:
 
573
                missing.append(entry)
 
574
        if len(missing) > 0:
 
575
            raise AssertionError("value(s) %r not present in container %r" % 
 
576
                                 (missing, superlist))
 
577
 
 
578
    def assertIs(self, left, right):
 
579
        if not (left is right):
 
580
            raise AssertionError("%r is not %r." % (left, right))
 
581
 
 
582
    def assertTransportMode(self, transport, path, mode):
 
583
        """Fail if a path does not have mode mode.
 
584
        
 
585
        If modes are not supported on this transport, the assertion is ignored.
 
586
        """
 
587
        if not transport._can_roundtrip_unix_modebits():
 
588
            return
 
589
        path_stat = transport.stat(path)
 
590
        actual_mode = stat.S_IMODE(path_stat.st_mode)
 
591
        self.assertEqual(mode, actual_mode,
 
592
            'mode of %r incorrect (%o != %o)' % (path, mode, actual_mode))
 
593
 
 
594
    def assertIsInstance(self, obj, kls):
 
595
        """Fail if obj is not an instance of kls"""
 
596
        if not isinstance(obj, kls):
 
597
            self.fail("%r is an instance of %s rather than %s" % (
 
598
                obj, obj.__class__, kls))
 
599
 
 
600
    def _capture_warnings(self, a_callable, *args, **kwargs):
 
601
        """A helper for callDeprecated and applyDeprecated.
 
602
 
 
603
        :param a_callable: A callable to call.
 
604
        :param args: The positional arguments for the callable
 
605
        :param kwargs: The keyword arguments for the callable
 
606
        :return: A tuple (warnings, result). result is the result of calling
 
607
            a_callable(*args, **kwargs).
 
608
        """
 
609
        local_warnings = []
 
610
        def capture_warnings(msg, cls, stacklevel=None):
 
611
            # we've hooked into a deprecation specific callpath,
 
612
            # only deprecations should getting sent via it.
 
613
            self.assertEqual(cls, DeprecationWarning)
 
614
            local_warnings.append(msg)
 
615
        original_warning_method = symbol_versioning.warn
 
616
        symbol_versioning.set_warning_method(capture_warnings)
 
617
        try:
 
618
            result = a_callable(*args, **kwargs)
 
619
        finally:
 
620
            symbol_versioning.set_warning_method(original_warning_method)
 
621
        return (local_warnings, result)
 
622
 
 
623
    def applyDeprecated(self, deprecation_format, a_callable, *args, **kwargs):
 
624
        """Call a deprecated callable without warning the user.
 
625
 
 
626
        :param deprecation_format: The deprecation format that the callable
 
627
            should have been deprecated with. This is the same type as the 
 
628
            parameter to deprecated_method/deprecated_function. If the 
 
629
            callable is not deprecated with this format, an assertion error
 
630
            will be raised.
 
631
        :param a_callable: A callable to call. This may be a bound method or
 
632
            a regular function. It will be called with *args and **kwargs.
 
633
        :param args: The positional arguments for the callable
 
634
        :param kwargs: The keyword arguments for the callable
 
635
        :return: The result of a_callable(*args, **kwargs)
 
636
        """
 
637
        call_warnings, result = self._capture_warnings(a_callable,
 
638
            *args, **kwargs)
 
639
        expected_first_warning = symbol_versioning.deprecation_string(
 
640
            a_callable, deprecation_format)
 
641
        if len(call_warnings) == 0:
 
642
            self.fail("No assertion generated by call to %s" %
 
643
                a_callable)
 
644
        self.assertEqual(expected_first_warning, call_warnings[0])
 
645
        return result
 
646
 
 
647
    def callDeprecated(self, expected, callable, *args, **kwargs):
 
648
        """Assert that a callable is deprecated in a particular way.
 
649
 
 
650
        This is a very precise test for unusual requirements. The 
 
651
        applyDeprecated helper function is probably more suited for most tests
 
652
        as it allows you to simply specify the deprecation format being used
 
653
        and will ensure that that is issued for the function being called.
 
654
 
 
655
        :param expected: a list of the deprecation warnings expected, in order
 
656
        :param callable: The callable to call
 
657
        :param args: The positional arguments for the callable
 
658
        :param kwargs: The keyword arguments for the callable
 
659
        """
 
660
        call_warnings, result = self._capture_warnings(callable,
 
661
            *args, **kwargs)
 
662
        self.assertEqual(expected, call_warnings)
 
663
        return result
 
664
 
 
665
    def _startLogFile(self):
 
666
        """Send bzr and test log messages to a temporary file.
 
667
 
 
668
        The file is removed as the test is torn down.
 
669
        """
 
670
        fileno, name = tempfile.mkstemp(suffix='.log', prefix='testbzr')
 
671
        self._log_file = os.fdopen(fileno, 'w+')
 
672
        self._log_nonce = bzrlib.trace.enable_test_log(self._log_file)
 
673
        self._log_file_name = name
 
674
        self.addCleanup(self._finishLogFile)
 
675
 
 
676
    def _finishLogFile(self):
 
677
        """Finished with the log file.
 
678
 
 
679
        Close the file and delete it, unless setKeepLogfile was called.
 
680
        """
 
681
        if self._log_file is None:
 
682
            return
 
683
        bzrlib.trace.disable_test_log(self._log_nonce)
 
684
        self._log_file.close()
 
685
        self._log_file = None
 
686
        if not self._keep_log_file:
 
687
            os.remove(self._log_file_name)
 
688
            self._log_file_name = None
 
689
 
 
690
    def setKeepLogfile(self):
 
691
        """Make the logfile not be deleted when _finishLogFile is called."""
 
692
        self._keep_log_file = True
 
693
 
 
694
    def addCleanup(self, callable):
 
695
        """Arrange to run a callable when this case is torn down.
 
696
 
 
697
        Callables are run in the reverse of the order they are registered, 
 
698
        ie last-in first-out.
 
699
        """
 
700
        if callable in self._cleanups:
 
701
            raise ValueError("cleanup function %r already registered on %s" 
 
702
                    % (callable, self))
 
703
        self._cleanups.append(callable)
 
704
 
 
705
    def _cleanEnvironment(self):
 
706
        new_env = {
 
707
            'BZR_HOME': None, # Don't inherit BZR_HOME to all the tests.
 
708
            'HOME': os.getcwd(),
 
709
            'APPDATA': os.getcwd(),
 
710
            'BZR_EMAIL': None,
 
711
            'BZREMAIL': None, # may still be present in the environment
 
712
            'EMAIL': None,
 
713
            'BZR_PROGRESS_BAR': None,
 
714
        }
 
715
        self.__old_env = {}
 
716
        self.addCleanup(self._restoreEnvironment)
 
717
        for name, value in new_env.iteritems():
 
718
            self._captureVar(name, value)
 
719
 
 
720
    def _captureVar(self, name, newvalue):
 
721
        """Set an environment variable, and reset it when finished."""
 
722
        self.__old_env[name] = osutils.set_or_unset_env(name, newvalue)
 
723
 
 
724
    def _restoreEnvironment(self):
 
725
        for name, value in self.__old_env.iteritems():
 
726
            osutils.set_or_unset_env(name, value)
 
727
 
 
728
    def tearDown(self):
 
729
        self._runCleanups()
 
730
        unittest.TestCase.tearDown(self)
 
731
 
 
732
    def time(self, callable, *args, **kwargs):
 
733
        """Run callable and accrue the time it takes to the benchmark time.
 
734
        
 
735
        If lsprofiling is enabled (i.e. by --lsprof-time to bzr selftest) then
 
736
        this will cause lsprofile statistics to be gathered and stored in
 
737
        self._benchcalls.
 
738
        """
 
739
        if self._benchtime is None:
 
740
            self._benchtime = 0
 
741
        start = time.time()
 
742
        try:
 
743
            if not self._gather_lsprof_in_benchmarks:
 
744
                return callable(*args, **kwargs)
 
745
            else:
 
746
                # record this benchmark
 
747
                ret, stats = bzrlib.lsprof.profile(callable, *args, **kwargs)
 
748
                stats.sort()
 
749
                self._benchcalls.append(((callable, args, kwargs), stats))
 
750
                return ret
 
751
        finally:
 
752
            self._benchtime += time.time() - start
 
753
 
 
754
    def _runCleanups(self):
 
755
        """Run registered cleanup functions. 
 
756
 
 
757
        This should only be called from TestCase.tearDown.
 
758
        """
 
759
        # TODO: Perhaps this should keep running cleanups even if 
 
760
        # one of them fails?
 
761
        for cleanup_fn in reversed(self._cleanups):
 
762
            cleanup_fn()
 
763
 
 
764
    def log(self, *args):
 
765
        mutter(*args)
 
766
 
 
767
    def _get_log(self, keep_log_file=False):
 
768
        """Return as a string the log for this test. If the file is still
 
769
        on disk and keep_log_file=False, delete the log file and store the
 
770
        content in self._log_contents."""
 
771
        # flush the log file, to get all content
 
772
        import bzrlib.trace
 
773
        bzrlib.trace._trace_file.flush()
 
774
        if self._log_contents:
 
775
            return self._log_contents
 
776
        if self._log_file_name is not None:
 
777
            logfile = open(self._log_file_name)
 
778
            try:
 
779
                log_contents = logfile.read()
 
780
            finally:
 
781
                logfile.close()
 
782
            if not keep_log_file:
 
783
                self._log_contents = log_contents
 
784
                os.remove(self._log_file_name)
 
785
            return log_contents
 
786
        else:
 
787
            return "DELETED log file to reduce memory footprint"
 
788
 
 
789
    def capture(self, cmd, retcode=0):
 
790
        """Shortcut that splits cmd into words, runs, and returns stdout"""
 
791
        return self.run_bzr_captured(cmd.split(), retcode=retcode)[0]
 
792
 
 
793
    def run_bzr_captured(self, argv, retcode=0, encoding=None, stdin=None,
 
794
                         working_dir=None):
 
795
        """Invoke bzr and return (stdout, stderr).
 
796
 
 
797
        Useful for code that wants to check the contents of the
 
798
        output, the way error messages are presented, etc.
 
799
 
 
800
        This should be the main method for tests that want to exercise the
 
801
        overall behavior of the bzr application (rather than a unit test
 
802
        or a functional test of the library.)
 
803
 
 
804
        Much of the old code runs bzr by forking a new copy of Python, but
 
805
        that is slower, harder to debug, and generally not necessary.
 
806
 
 
807
        This runs bzr through the interface that catches and reports
 
808
        errors, and with logging set to something approximating the
 
809
        default, so that error reporting can be checked.
 
810
 
 
811
        :param argv: arguments to invoke bzr
 
812
        :param retcode: expected return code, or None for don't-care.
 
813
        :param encoding: encoding for sys.stdout and sys.stderr
 
814
        :param stdin: A string to be used as stdin for the command.
 
815
        :param working_dir: Change to this directory before running
 
816
        """
 
817
        if encoding is None:
 
818
            encoding = bzrlib.user_encoding
 
819
        if stdin is not None:
 
820
            stdin = StringIO(stdin)
 
821
        stdout = StringIOWrapper()
 
822
        stderr = StringIOWrapper()
 
823
        stdout.encoding = encoding
 
824
        stderr.encoding = encoding
 
825
 
 
826
        self.log('run bzr: %r', argv)
 
827
        # FIXME: don't call into logging here
 
828
        handler = logging.StreamHandler(stderr)
 
829
        handler.setLevel(logging.INFO)
 
830
        logger = logging.getLogger('')
 
831
        logger.addHandler(handler)
 
832
        old_ui_factory = bzrlib.ui.ui_factory
 
833
        bzrlib.ui.ui_factory = bzrlib.tests.blackbox.TestUIFactory(
 
834
            stdout=stdout,
 
835
            stderr=stderr)
 
836
        bzrlib.ui.ui_factory.stdin = stdin
 
837
 
 
838
        cwd = None
 
839
        if working_dir is not None:
 
840
            cwd = osutils.getcwd()
 
841
            os.chdir(working_dir)
 
842
 
 
843
        try:
 
844
            result = self.apply_redirected(stdin, stdout, stderr,
 
845
                                           bzrlib.commands.run_bzr_catch_errors,
 
846
                                           argv)
 
847
        finally:
 
848
            logger.removeHandler(handler)
 
849
            bzrlib.ui.ui_factory = old_ui_factory
 
850
            if cwd is not None:
 
851
                os.chdir(cwd)
 
852
 
 
853
        out = stdout.getvalue()
 
854
        err = stderr.getvalue()
 
855
        if out:
 
856
            self.log('output:\n%r', out)
 
857
        if err:
 
858
            self.log('errors:\n%r', err)
 
859
        if retcode is not None:
 
860
            self.assertEquals(retcode, result)
 
861
        return out, err
 
862
 
 
863
    def run_bzr(self, *args, **kwargs):
 
864
        """Invoke bzr, as if it were run from the command line.
 
865
 
 
866
        This should be the main method for tests that want to exercise the
 
867
        overall behavior of the bzr application (rather than a unit test
 
868
        or a functional test of the library.)
 
869
 
 
870
        This sends the stdout/stderr results into the test's log,
 
871
        where it may be useful for debugging.  See also run_captured.
 
872
 
 
873
        :param stdin: A string to be used as stdin for the command.
 
874
        """
 
875
        retcode = kwargs.pop('retcode', 0)
 
876
        encoding = kwargs.pop('encoding', None)
 
877
        stdin = kwargs.pop('stdin', None)
 
878
        working_dir = kwargs.pop('working_dir', None)
 
879
        return self.run_bzr_captured(args, retcode=retcode, encoding=encoding,
 
880
                                     stdin=stdin, working_dir=working_dir)
 
881
 
 
882
    def run_bzr_decode(self, *args, **kwargs):
 
883
        if 'encoding' in kwargs:
 
884
            encoding = kwargs['encoding']
 
885
        else:
 
886
            encoding = bzrlib.user_encoding
 
887
        return self.run_bzr(*args, **kwargs)[0].decode(encoding)
 
888
 
 
889
    def run_bzr_error(self, error_regexes, *args, **kwargs):
 
890
        """Run bzr, and check that stderr contains the supplied regexes
 
891
        
 
892
        :param error_regexes: Sequence of regular expressions which 
 
893
            must each be found in the error output. The relative ordering
 
894
            is not enforced.
 
895
        :param args: command-line arguments for bzr
 
896
        :param kwargs: Keyword arguments which are interpreted by run_bzr
 
897
            This function changes the default value of retcode to be 3,
 
898
            since in most cases this is run when you expect bzr to fail.
 
899
        :return: (out, err) The actual output of running the command (in case you
 
900
                 want to do more inspection)
 
901
 
 
902
        Examples of use:
 
903
            # Make sure that commit is failing because there is nothing to do
 
904
            self.run_bzr_error(['no changes to commit'],
 
905
                               'commit', '-m', 'my commit comment')
 
906
            # Make sure --strict is handling an unknown file, rather than
 
907
            # giving us the 'nothing to do' error
 
908
            self.build_tree(['unknown'])
 
909
            self.run_bzr_error(['Commit refused because there are unknown files'],
 
910
                               'commit', '--strict', '-m', 'my commit comment')
 
911
        """
 
912
        kwargs.setdefault('retcode', 3)
 
913
        out, err = self.run_bzr(*args, **kwargs)
 
914
        for regex in error_regexes:
 
915
            self.assertContainsRe(err, regex)
 
916
        return out, err
 
917
 
 
918
    def run_bzr_subprocess(self, *args, **kwargs):
 
919
        """Run bzr in a subprocess for testing.
 
920
 
 
921
        This starts a new Python interpreter and runs bzr in there. 
 
922
        This should only be used for tests that have a justifiable need for
 
923
        this isolation: e.g. they are testing startup time, or signal
 
924
        handling, or early startup code, etc.  Subprocess code can't be 
 
925
        profiled or debugged so easily.
 
926
 
 
927
        :param retcode: The status code that is expected.  Defaults to 0.  If
 
928
            None is supplied, the status code is not checked.
 
929
        :param env_changes: A dictionary which lists changes to environment
 
930
            variables. A value of None will unset the env variable.
 
931
            The values must be strings. The change will only occur in the
 
932
            child, so you don't need to fix the environment after running.
 
933
        :param universal_newlines: Convert CRLF => LF
 
934
        """
 
935
        env_changes = kwargs.get('env_changes', {})
 
936
        working_dir = kwargs.get('working_dir', None)
 
937
        process = self.start_bzr_subprocess(args, env_changes=env_changes,
 
938
                                            working_dir=working_dir)
 
939
        # We distinguish between retcode=None and retcode not passed.
 
940
        supplied_retcode = kwargs.get('retcode', 0)
 
941
        return self.finish_bzr_subprocess(process, retcode=supplied_retcode,
 
942
            universal_newlines=kwargs.get('universal_newlines', False),
 
943
            process_args=args)
 
944
 
 
945
    def start_bzr_subprocess(self, process_args, env_changes=None,
 
946
                             skip_if_plan_to_signal=False,
 
947
                             working_dir=None):
 
948
        """Start bzr in a subprocess for testing.
 
949
 
 
950
        This starts a new Python interpreter and runs bzr in there.
 
951
        This should only be used for tests that have a justifiable need for
 
952
        this isolation: e.g. they are testing startup time, or signal
 
953
        handling, or early startup code, etc.  Subprocess code can't be
 
954
        profiled or debugged so easily.
 
955
 
 
956
        :param process_args: a list of arguments to pass to the bzr executable,
 
957
            for example `['--version']`.
 
958
        :param env_changes: A dictionary which lists changes to environment
 
959
            variables. A value of None will unset the env variable.
 
960
            The values must be strings. The change will only occur in the
 
961
            child, so you don't need to fix the environment after running.
 
962
        :param skip_if_plan_to_signal: raise TestSkipped when true and os.kill
 
963
            is not available.
 
964
 
 
965
        :returns: Popen object for the started process.
 
966
        """
 
967
        if skip_if_plan_to_signal:
 
968
            if not getattr(os, 'kill', None):
 
969
                raise TestSkipped("os.kill not available.")
 
970
 
 
971
        if env_changes is None:
 
972
            env_changes = {}
 
973
        old_env = {}
 
974
 
 
975
        def cleanup_environment():
 
976
            for env_var, value in env_changes.iteritems():
 
977
                old_env[env_var] = osutils.set_or_unset_env(env_var, value)
 
978
 
 
979
        def restore_environment():
 
980
            for env_var, value in old_env.iteritems():
 
981
                osutils.set_or_unset_env(env_var, value)
 
982
 
 
983
        bzr_path = self.get_bzr_path()
 
984
 
 
985
        cwd = None
 
986
        if working_dir is not None:
 
987
            cwd = osutils.getcwd()
 
988
            os.chdir(working_dir)
 
989
 
 
990
        try:
 
991
            # win32 subprocess doesn't support preexec_fn
 
992
            # so we will avoid using it on all platforms, just to
 
993
            # make sure the code path is used, and we don't break on win32
 
994
            cleanup_environment()
 
995
            process = Popen([sys.executable, bzr_path] + list(process_args),
 
996
                             stdin=PIPE, stdout=PIPE, stderr=PIPE)
 
997
        finally:
 
998
            restore_environment()
 
999
            if cwd is not None:
 
1000
                os.chdir(cwd)
 
1001
 
 
1002
        return process
 
1003
 
 
1004
    def get_bzr_path(self):
 
1005
        """Return the path of the 'bzr' executable for this test suite."""
 
1006
        bzr_path = os.path.dirname(os.path.dirname(bzrlib.__file__))+'/bzr'
 
1007
        if not os.path.isfile(bzr_path):
 
1008
            # We are probably installed. Assume sys.argv is the right file
 
1009
            bzr_path = sys.argv[0]
 
1010
        return bzr_path
 
1011
 
 
1012
    def finish_bzr_subprocess(self, process, retcode=0, send_signal=None,
 
1013
                              universal_newlines=False, process_args=None):
 
1014
        """Finish the execution of process.
 
1015
 
 
1016
        :param process: the Popen object returned from start_bzr_subprocess.
 
1017
        :param retcode: The status code that is expected.  Defaults to 0.  If
 
1018
            None is supplied, the status code is not checked.
 
1019
        :param send_signal: an optional signal to send to the process.
 
1020
        :param universal_newlines: Convert CRLF => LF
 
1021
        :returns: (stdout, stderr)
 
1022
        """
 
1023
        if send_signal is not None:
 
1024
            os.kill(process.pid, send_signal)
 
1025
        out, err = process.communicate()
 
1026
 
 
1027
        if universal_newlines:
 
1028
            out = out.replace('\r\n', '\n')
 
1029
            err = err.replace('\r\n', '\n')
 
1030
 
 
1031
        if retcode is not None and retcode != process.returncode:
 
1032
            if process_args is None:
 
1033
                process_args = "(unknown args)"
 
1034
            mutter('Output of bzr %s:\n%s', process_args, out)
 
1035
            mutter('Error for bzr %s:\n%s', process_args, err)
 
1036
            self.fail('Command bzr %s failed with retcode %s != %s'
 
1037
                      % (process_args, retcode, process.returncode))
 
1038
        return [out, err]
 
1039
 
 
1040
    def check_inventory_shape(self, inv, shape):
 
1041
        """Compare an inventory to a list of expected names.
 
1042
 
 
1043
        Fail if they are not precisely equal.
 
1044
        """
 
1045
        extras = []
 
1046
        shape = list(shape)             # copy
 
1047
        for path, ie in inv.entries():
 
1048
            name = path.replace('\\', '/')
 
1049
            if ie.kind == 'dir':
 
1050
                name = name + '/'
 
1051
            if name in shape:
 
1052
                shape.remove(name)
 
1053
            else:
 
1054
                extras.append(name)
 
1055
        if shape:
 
1056
            self.fail("expected paths not found in inventory: %r" % shape)
 
1057
        if extras:
 
1058
            self.fail("unexpected paths found in inventory: %r" % extras)
 
1059
 
 
1060
    def apply_redirected(self, stdin=None, stdout=None, stderr=None,
 
1061
                         a_callable=None, *args, **kwargs):
 
1062
        """Call callable with redirected std io pipes.
 
1063
 
 
1064
        Returns the return code."""
 
1065
        if not callable(a_callable):
 
1066
            raise ValueError("a_callable must be callable.")
 
1067
        if stdin is None:
 
1068
            stdin = StringIO("")
 
1069
        if stdout is None:
 
1070
            if getattr(self, "_log_file", None) is not None:
 
1071
                stdout = self._log_file
 
1072
            else:
 
1073
                stdout = StringIO()
 
1074
        if stderr is None:
 
1075
            if getattr(self, "_log_file", None is not None):
 
1076
                stderr = self._log_file
 
1077
            else:
 
1078
                stderr = StringIO()
 
1079
        real_stdin = sys.stdin
 
1080
        real_stdout = sys.stdout
 
1081
        real_stderr = sys.stderr
 
1082
        try:
 
1083
            sys.stdout = stdout
 
1084
            sys.stderr = stderr
 
1085
            sys.stdin = stdin
 
1086
            return a_callable(*args, **kwargs)
 
1087
        finally:
 
1088
            sys.stdout = real_stdout
 
1089
            sys.stderr = real_stderr
 
1090
            sys.stdin = real_stdin
 
1091
 
 
1092
    @symbol_versioning.deprecated_method(symbol_versioning.zero_eleven)
 
1093
    def merge(self, branch_from, wt_to):
 
1094
        """A helper for tests to do a ui-less merge.
 
1095
 
 
1096
        This should move to the main library when someone has time to integrate
 
1097
        it in.
 
1098
        """
 
1099
        # minimal ui-less merge.
 
1100
        wt_to.branch.fetch(branch_from)
 
1101
        base_rev = common_ancestor(branch_from.last_revision(),
 
1102
                                   wt_to.branch.last_revision(),
 
1103
                                   wt_to.branch.repository)
 
1104
        merge_inner(wt_to.branch, branch_from.basis_tree(),
 
1105
                    wt_to.branch.repository.revision_tree(base_rev),
 
1106
                    this_tree=wt_to)
 
1107
        wt_to.add_parent_tree_id(branch_from.last_revision())
 
1108
 
 
1109
 
 
1110
BzrTestBase = TestCase
 
1111
 
 
1112
 
 
1113
class TestCaseWithMemoryTransport(TestCase):
 
1114
    """Common test class for tests that do not need disk resources.
 
1115
 
 
1116
    Tests that need disk resources should derive from TestCaseWithTransport.
 
1117
 
 
1118
    TestCaseWithMemoryTransport sets the TEST_ROOT variable for all bzr tests.
 
1119
 
 
1120
    For TestCaseWithMemoryTransport the test_home_dir is set to the name of
 
1121
    a directory which does not exist. This serves to help ensure test isolation
 
1122
    is preserved. test_dir is set to the TEST_ROOT, as is cwd, because they
 
1123
    must exist. However, TestCaseWithMemoryTransport does not offer local
 
1124
    file defaults for the transport in tests, nor does it obey the command line
 
1125
    override, so tests that accidentally write to the common directory should
 
1126
    be rare.
 
1127
    """
 
1128
 
 
1129
    TEST_ROOT = None
 
1130
    _TEST_NAME = 'test'
 
1131
 
 
1132
 
 
1133
    def __init__(self, methodName='runTest'):
 
1134
        # allow test parameterisation after test construction and before test
 
1135
        # execution. Variables that the parameteriser sets need to be 
 
1136
        # ones that are not set by setUp, or setUp will trash them.
 
1137
        super(TestCaseWithMemoryTransport, self).__init__(methodName)
 
1138
        self.transport_server = default_transport
 
1139
        self.transport_readonly_server = None
 
1140
 
 
1141
    def failUnlessExists(self, path):
 
1142
        """Fail unless path, which may be abs or relative, exists."""
 
1143
        self.failUnless(osutils.lexists(path))
 
1144
 
 
1145
    def failIfExists(self, path):
 
1146
        """Fail if path, which may be abs or relative, exists."""
 
1147
        self.failIf(osutils.lexists(path))
 
1148
        
 
1149
    def get_transport(self):
 
1150
        """Return a writeable transport for the test scratch space"""
 
1151
        t = get_transport(self.get_url())
 
1152
        self.assertFalse(t.is_readonly())
 
1153
        return t
 
1154
 
 
1155
    def get_readonly_transport(self):
 
1156
        """Return a readonly transport for the test scratch space
 
1157
        
 
1158
        This can be used to test that operations which should only need
 
1159
        readonly access in fact do not try to write.
 
1160
        """
 
1161
        t = get_transport(self.get_readonly_url())
 
1162
        self.assertTrue(t.is_readonly())
 
1163
        return t
 
1164
 
 
1165
    def get_readonly_server(self):
 
1166
        """Get the server instance for the readonly transport
 
1167
 
 
1168
        This is useful for some tests with specific servers to do diagnostics.
 
1169
        """
 
1170
        if self.__readonly_server is None:
 
1171
            if self.transport_readonly_server is None:
 
1172
                # readonly decorator requested
 
1173
                # bring up the server
 
1174
                self.get_url()
 
1175
                self.__readonly_server = ReadonlyServer()
 
1176
                self.__readonly_server.setUp(self.__server)
 
1177
            else:
 
1178
                self.__readonly_server = self.transport_readonly_server()
 
1179
                self.__readonly_server.setUp()
 
1180
            self.addCleanup(self.__readonly_server.tearDown)
 
1181
        return self.__readonly_server
 
1182
 
 
1183
    def get_readonly_url(self, relpath=None):
 
1184
        """Get a URL for the readonly transport.
 
1185
 
 
1186
        This will either be backed by '.' or a decorator to the transport 
 
1187
        used by self.get_url()
 
1188
        relpath provides for clients to get a path relative to the base url.
 
1189
        These should only be downwards relative, not upwards.
 
1190
        """
 
1191
        base = self.get_readonly_server().get_url()
 
1192
        if relpath is not None:
 
1193
            if not base.endswith('/'):
 
1194
                base = base + '/'
 
1195
            base = base + relpath
 
1196
        return base
 
1197
 
 
1198
    def get_server(self):
 
1199
        """Get the read/write server instance.
 
1200
 
 
1201
        This is useful for some tests with specific servers that need
 
1202
        diagnostics.
 
1203
 
 
1204
        For TestCaseWithMemoryTransport this is always a MemoryServer, and there
 
1205
        is no means to override it.
 
1206
        """
 
1207
        if self.__server is None:
 
1208
            self.__server = MemoryServer()
 
1209
            self.__server.setUp()
 
1210
            self.addCleanup(self.__server.tearDown)
 
1211
        return self.__server
 
1212
 
 
1213
    def get_url(self, relpath=None):
 
1214
        """Get a URL (or maybe a path) for the readwrite transport.
 
1215
 
 
1216
        This will either be backed by '.' or to an equivalent non-file based
 
1217
        facility.
 
1218
        relpath provides for clients to get a path relative to the base url.
 
1219
        These should only be downwards relative, not upwards.
 
1220
        """
 
1221
        base = self.get_server().get_url()
 
1222
        if relpath is not None and relpath != '.':
 
1223
            if not base.endswith('/'):
 
1224
                base = base + '/'
 
1225
            # XXX: Really base should be a url; we did after all call
 
1226
            # get_url()!  But sometimes it's just a path (from
 
1227
            # LocalAbspathServer), and it'd be wrong to append urlescaped data
 
1228
            # to a non-escaped local path.
 
1229
            if base.startswith('./') or base.startswith('/'):
 
1230
                base += relpath
 
1231
            else:
 
1232
                base += urlutils.escape(relpath)
 
1233
        return base
 
1234
 
 
1235
    def _make_test_root(self):
 
1236
        if TestCaseWithMemoryTransport.TEST_ROOT is not None:
 
1237
            return
 
1238
        i = 0
 
1239
        while True:
 
1240
            root = u'test%04d.tmp' % i
 
1241
            try:
 
1242
                os.mkdir(root)
 
1243
            except OSError, e:
 
1244
                if e.errno == errno.EEXIST:
 
1245
                    i += 1
 
1246
                    continue
 
1247
                else:
 
1248
                    raise
 
1249
            # successfully created
 
1250
            TestCaseWithMemoryTransport.TEST_ROOT = osutils.abspath(root)
 
1251
            break
 
1252
        # make a fake bzr directory there to prevent any tests propagating
 
1253
        # up onto the source directory's real branch
 
1254
        bzrdir.BzrDir.create_standalone_workingtree(
 
1255
            TestCaseWithMemoryTransport.TEST_ROOT)
 
1256
 
 
1257
    def makeAndChdirToTestDir(self):
 
1258
        """Create a temporary directories for this one test.
 
1259
        
 
1260
        This must set self.test_home_dir and self.test_dir and chdir to
 
1261
        self.test_dir.
 
1262
        
 
1263
        For TestCaseWithMemoryTransport we chdir to the TEST_ROOT for this test.
 
1264
        """
 
1265
        os.chdir(TestCaseWithMemoryTransport.TEST_ROOT)
 
1266
        self.test_dir = TestCaseWithMemoryTransport.TEST_ROOT
 
1267
        self.test_home_dir = self.test_dir + "/MemoryTransportMissingHomeDir"
 
1268
        
 
1269
    def make_branch(self, relpath, format=None):
 
1270
        """Create a branch on the transport at relpath."""
 
1271
        repo = self.make_repository(relpath, format=format)
 
1272
        return repo.bzrdir.create_branch()
 
1273
 
 
1274
    def make_bzrdir(self, relpath, format=None):
 
1275
        try:
 
1276
            # might be a relative or absolute path
 
1277
            maybe_a_url = self.get_url(relpath)
 
1278
            segments = maybe_a_url.rsplit('/', 1)
 
1279
            t = get_transport(maybe_a_url)
 
1280
            if len(segments) > 1 and segments[-1] not in ('', '.'):
 
1281
                try:
 
1282
                    t.mkdir('.')
 
1283
                except errors.FileExists:
 
1284
                    pass
 
1285
            if format is None:
 
1286
                format = bzrlib.bzrdir.BzrDirFormat.get_default_format()
 
1287
            return format.initialize_on_transport(t)
 
1288
        except errors.UninitializableFormat:
 
1289
            raise TestSkipped("Format %s is not initializable." % format)
 
1290
 
 
1291
    def make_repository(self, relpath, shared=False, format=None):
 
1292
        """Create a repository on our default transport at relpath."""
 
1293
        made_control = self.make_bzrdir(relpath, format=format)
 
1294
        return made_control.create_repository(shared=shared)
 
1295
 
 
1296
    def make_branch_and_memory_tree(self, relpath):
 
1297
        """Create a branch on the default transport and a MemoryTree for it."""
 
1298
        b = self.make_branch(relpath)
 
1299
        return memorytree.MemoryTree.create_on_branch(b)
 
1300
 
 
1301
    def overrideEnvironmentForTesting(self):
 
1302
        os.environ['HOME'] = self.test_home_dir
 
1303
        os.environ['APPDATA'] = self.test_home_dir
 
1304
        
 
1305
    def setUp(self):
 
1306
        super(TestCaseWithMemoryTransport, self).setUp()
 
1307
        self._make_test_root()
 
1308
        _currentdir = os.getcwdu()
 
1309
        def _leaveDirectory():
 
1310
            os.chdir(_currentdir)
 
1311
        self.addCleanup(_leaveDirectory)
 
1312
        self.makeAndChdirToTestDir()
 
1313
        self.overrideEnvironmentForTesting()
 
1314
        self.__readonly_server = None
 
1315
        self.__server = None
 
1316
 
 
1317
     
 
1318
class TestCaseInTempDir(TestCaseWithMemoryTransport):
 
1319
    """Derived class that runs a test within a temporary directory.
 
1320
 
 
1321
    This is useful for tests that need to create a branch, etc.
 
1322
 
 
1323
    The directory is created in a slightly complex way: for each
 
1324
    Python invocation, a new temporary top-level directory is created.
 
1325
    All test cases create their own directory within that.  If the
 
1326
    tests complete successfully, the directory is removed.
 
1327
 
 
1328
    InTempDir is an old alias for FunctionalTestCase.
 
1329
    """
 
1330
 
 
1331
    OVERRIDE_PYTHON = 'python'
 
1332
 
 
1333
    def check_file_contents(self, filename, expect):
 
1334
        self.log("check contents of file %s" % filename)
 
1335
        contents = file(filename, 'r').read()
 
1336
        if contents != expect:
 
1337
            self.log("expected: %r" % expect)
 
1338
            self.log("actually: %r" % contents)
 
1339
            self.fail("contents of %s not as expected" % filename)
 
1340
 
 
1341
    def makeAndChdirToTestDir(self):
 
1342
        """See TestCaseWithMemoryTransport.makeAndChdirToTestDir().
 
1343
        
 
1344
        For TestCaseInTempDir we create a temporary directory based on the test
 
1345
        name and then create two subdirs - test and home under it.
 
1346
        """
 
1347
        # shorten the name, to avoid test failures due to path length
 
1348
        short_id = self.id().replace('bzrlib.tests.', '') \
 
1349
                   .replace('__main__.', '')[-100:]
 
1350
        # it's possible the same test class is run several times for
 
1351
        # parameterized tests, so make sure the names don't collide.  
 
1352
        i = 0
 
1353
        while True:
 
1354
            if i > 0:
 
1355
                candidate_dir = '%s/%s.%d' % (self.TEST_ROOT, short_id, i)
 
1356
            else:
 
1357
                candidate_dir = '%s/%s' % (self.TEST_ROOT, short_id)
 
1358
            if os.path.exists(candidate_dir):
 
1359
                i = i + 1
 
1360
                continue
 
1361
            else:
 
1362
                os.mkdir(candidate_dir)
 
1363
                self.test_home_dir = candidate_dir + '/home'
 
1364
                os.mkdir(self.test_home_dir)
 
1365
                self.test_dir = candidate_dir + '/work'
 
1366
                os.mkdir(self.test_dir)
 
1367
                os.chdir(self.test_dir)
 
1368
                break
 
1369
 
 
1370
    def build_tree(self, shape, line_endings='native', transport=None):
 
1371
        """Build a test tree according to a pattern.
 
1372
 
 
1373
        shape is a sequence of file specifications.  If the final
 
1374
        character is '/', a directory is created.
 
1375
 
 
1376
        This assumes that all the elements in the tree being built are new.
 
1377
 
 
1378
        This doesn't add anything to a branch.
 
1379
        :param line_endings: Either 'binary' or 'native'
 
1380
                             in binary mode, exact contents are written
 
1381
                             in native mode, the line endings match the
 
1382
                             default platform endings.
 
1383
 
 
1384
        :param transport: A transport to write to, for building trees on 
 
1385
                          VFS's. If the transport is readonly or None,
 
1386
                          "." is opened automatically.
 
1387
        """
 
1388
        # It's OK to just create them using forward slashes on windows.
 
1389
        if transport is None or transport.is_readonly():
 
1390
            transport = get_transport(".")
 
1391
        for name in shape:
 
1392
            self.assert_(isinstance(name, basestring))
 
1393
            if name[-1] == '/':
 
1394
                transport.mkdir(urlutils.escape(name[:-1]))
 
1395
            else:
 
1396
                if line_endings == 'binary':
 
1397
                    end = '\n'
 
1398
                elif line_endings == 'native':
 
1399
                    end = os.linesep
 
1400
                else:
 
1401
                    raise errors.BzrError('Invalid line ending request %r' % (line_endings,))
 
1402
                content = "contents of %s%s" % (name.encode('utf-8'), end)
 
1403
                # Technically 'put()' is the right command. However, put
 
1404
                # uses an AtomicFile, which requires an extra rename into place
 
1405
                # As long as the files didn't exist in the past, append() will
 
1406
                # do the same thing as put()
 
1407
                # On jam's machine, make_kernel_like_tree is:
 
1408
                #   put:    4.5-7.5s (averaging 6s)
 
1409
                #   append: 2.9-4.5s
 
1410
                #   put_non_atomic: 2.9-4.5s
 
1411
                transport.put_bytes_non_atomic(urlutils.escape(name), content)
 
1412
 
 
1413
    def build_tree_contents(self, shape):
 
1414
        build_tree_contents(shape)
 
1415
 
 
1416
    def assertFileEqual(self, content, path):
 
1417
        """Fail if path does not contain 'content'."""
 
1418
        self.failUnless(osutils.lexists(path))
 
1419
        # TODO: jam 20060427 Shouldn't this be 'rb'?
 
1420
        self.assertEqualDiff(content, open(path, 'r').read())
 
1421
 
 
1422
 
 
1423
class TestCaseWithTransport(TestCaseInTempDir):
 
1424
    """A test case that provides get_url and get_readonly_url facilities.
 
1425
 
 
1426
    These back onto two transport servers, one for readonly access and one for
 
1427
    read write access.
 
1428
 
 
1429
    If no explicit class is provided for readonly access, a
 
1430
    ReadonlyTransportDecorator is used instead which allows the use of non disk
 
1431
    based read write transports.
 
1432
 
 
1433
    If an explicit class is provided for readonly access, that server and the 
 
1434
    readwrite one must both define get_url() as resolving to os.getcwd().
 
1435
    """
 
1436
 
 
1437
    def get_server(self):
 
1438
        """See TestCaseWithMemoryTransport.
 
1439
 
 
1440
        This is useful for some tests with specific servers that need
 
1441
        diagnostics.
 
1442
        """
 
1443
        if self.__server is None:
 
1444
            self.__server = self.transport_server()
 
1445
            self.__server.setUp()
 
1446
            self.addCleanup(self.__server.tearDown)
 
1447
        return self.__server
 
1448
 
 
1449
    def make_branch_and_tree(self, relpath, format=None):
 
1450
        """Create a branch on the transport and a tree locally.
 
1451
 
 
1452
        If the transport is not a LocalTransport, the Tree can't be created on
 
1453
        the transport.  In that case the working tree is created in the local
 
1454
        directory, and the returned tree's branch and repository will also be
 
1455
        accessed locally.
 
1456
 
 
1457
        This will fail if the original default transport for this test
 
1458
        case wasn't backed by the working directory, as the branch won't
 
1459
        be on disk for us to open it.  
 
1460
 
 
1461
        :param format: The BzrDirFormat.
 
1462
        :returns: the WorkingTree.
 
1463
        """
 
1464
        # TODO: always use the local disk path for the working tree,
 
1465
        # this obviously requires a format that supports branch references
 
1466
        # so check for that by checking bzrdir.BzrDirFormat.get_default_format()
 
1467
        # RBC 20060208
 
1468
        b = self.make_branch(relpath, format=format)
 
1469
        try:
 
1470
            return b.bzrdir.create_workingtree()
 
1471
        except errors.NotLocalUrl:
 
1472
            # We can only make working trees locally at the moment.  If the
 
1473
            # transport can't support them, then reopen the branch on a local
 
1474
            # transport, and create the working tree there.  
 
1475
            #
 
1476
            # Possibly we should instead keep
 
1477
            # the non-disk-backed branch and create a local checkout?
 
1478
            bd = bzrdir.BzrDir.open(relpath)
 
1479
            return bd.create_workingtree()
 
1480
 
 
1481
    def assertIsDirectory(self, relpath, transport):
 
1482
        """Assert that relpath within transport is a directory.
 
1483
 
 
1484
        This may not be possible on all transports; in that case it propagates
 
1485
        a TransportNotPossible.
 
1486
        """
 
1487
        try:
 
1488
            mode = transport.stat(relpath).st_mode
 
1489
        except errors.NoSuchFile:
 
1490
            self.fail("path %s is not a directory; no such file"
 
1491
                      % (relpath))
 
1492
        if not stat.S_ISDIR(mode):
 
1493
            self.fail("path %s is not a directory; has mode %#o"
 
1494
                      % (relpath, mode))
 
1495
 
 
1496
    def setUp(self):
 
1497
        super(TestCaseWithTransport, self).setUp()
 
1498
        self.__server = None
 
1499
        self.transport_server = default_transport
 
1500
 
 
1501
 
 
1502
class ChrootedTestCase(TestCaseWithTransport):
 
1503
    """A support class that provides readonly urls outside the local namespace.
 
1504
 
 
1505
    This is done by checking if self.transport_server is a MemoryServer. if it
 
1506
    is then we are chrooted already, if it is not then an HttpServer is used
 
1507
    for readonly urls.
 
1508
 
 
1509
    TODO RBC 20060127: make this an option to TestCaseWithTransport so it can
 
1510
                       be used without needed to redo it when a different 
 
1511
                       subclass is in use ?
 
1512
    """
 
1513
 
 
1514
    def setUp(self):
 
1515
        super(ChrootedTestCase, self).setUp()
 
1516
        if not self.transport_server == bzrlib.transport.memory.MemoryServer:
 
1517
            self.transport_readonly_server = bzrlib.transport.http.HttpServer
 
1518
 
 
1519
 
 
1520
def filter_suite_by_re(suite, pattern):
 
1521
    result = TestUtil.TestSuite()
 
1522
    filter_re = re.compile(pattern)
 
1523
    for test in iter_suite_tests(suite):
 
1524
        if filter_re.search(test.id()):
 
1525
            result.addTest(test)
 
1526
    return result
 
1527
 
 
1528
 
 
1529
def run_suite(suite, name='test', verbose=False, pattern=".*",
 
1530
              stop_on_failure=False, keep_output=False,
 
1531
              transport=None, lsprof_timed=None, bench_history=None):
 
1532
    TestCase._gather_lsprof_in_benchmarks = lsprof_timed
 
1533
    if verbose:
 
1534
        verbosity = 2
 
1535
        pb = None
 
1536
    else:
 
1537
        verbosity = 1
 
1538
        pb = progress.ProgressBar()
 
1539
    runner = TextTestRunner(stream=sys.stdout,
 
1540
                            descriptions=0,
 
1541
                            verbosity=verbosity,
 
1542
                            keep_output=keep_output,
 
1543
                            pb=pb,
 
1544
                            bench_history=bench_history)
 
1545
    runner.stop_on_failure=stop_on_failure
 
1546
    if pattern != '.*':
 
1547
        suite = filter_suite_by_re(suite, pattern)
 
1548
    result = runner.run(suite)
 
1549
    return result.wasSuccessful()
 
1550
 
 
1551
 
 
1552
def selftest(verbose=False, pattern=".*", stop_on_failure=True,
 
1553
             keep_output=False,
 
1554
             transport=None,
 
1555
             test_suite_factory=None,
 
1556
             lsprof_timed=None,
 
1557
             bench_history=None):
 
1558
    """Run the whole test suite under the enhanced runner"""
 
1559
    # XXX: Very ugly way to do this...
 
1560
    # Disable warning about old formats because we don't want it to disturb
 
1561
    # any blackbox tests.
 
1562
    from bzrlib import repository
 
1563
    repository._deprecation_warning_done = True
 
1564
 
 
1565
    global default_transport
 
1566
    if transport is None:
 
1567
        transport = default_transport
 
1568
    old_transport = default_transport
 
1569
    default_transport = transport
 
1570
    try:
 
1571
        if test_suite_factory is None:
 
1572
            suite = test_suite()
 
1573
        else:
 
1574
            suite = test_suite_factory()
 
1575
        return run_suite(suite, 'testbzr', verbose=verbose, pattern=pattern,
 
1576
                     stop_on_failure=stop_on_failure, keep_output=keep_output,
 
1577
                     transport=transport,
 
1578
                     lsprof_timed=lsprof_timed,
 
1579
                     bench_history=bench_history)
 
1580
    finally:
 
1581
        default_transport = old_transport
 
1582
 
 
1583
 
 
1584
def test_suite():
 
1585
    """Build and return TestSuite for the whole of bzrlib.
 
1586
    
 
1587
    This function can be replaced if you need to change the default test
 
1588
    suite on a global basis, but it is not encouraged.
 
1589
    """
 
1590
    testmod_names = [
 
1591
                   'bzrlib.tests.test_ancestry',
 
1592
                   'bzrlib.tests.test_api',
 
1593
                   'bzrlib.tests.test_atomicfile',
 
1594
                   'bzrlib.tests.test_bad_files',
 
1595
                   'bzrlib.tests.test_branch',
 
1596
                   'bzrlib.tests.test_bundle',
 
1597
                   'bzrlib.tests.test_bzrdir',
 
1598
                   'bzrlib.tests.test_cache_utf8',
 
1599
                   'bzrlib.tests.test_command',
 
1600
                   'bzrlib.tests.test_commit',
 
1601
                   'bzrlib.tests.test_commit_merge',
 
1602
                   'bzrlib.tests.test_config',
 
1603
                   'bzrlib.tests.test_conflicts',
 
1604
                   'bzrlib.tests.test_decorators',
 
1605
                   'bzrlib.tests.test_diff',
 
1606
                   'bzrlib.tests.test_doc_generate',
 
1607
                   'bzrlib.tests.test_errors',
 
1608
                   'bzrlib.tests.test_escaped_store',
 
1609
                   'bzrlib.tests.test_fetch',
 
1610
                   'bzrlib.tests.test_ftp_transport',
 
1611
                   'bzrlib.tests.test_gpg',
 
1612
                   'bzrlib.tests.test_graph',
 
1613
                   'bzrlib.tests.test_hashcache',
 
1614
                   'bzrlib.tests.test_http',
 
1615
                   'bzrlib.tests.test_http_response',
 
1616
                   'bzrlib.tests.test_identitymap',
 
1617
                   'bzrlib.tests.test_ignores',
 
1618
                   'bzrlib.tests.test_inv',
 
1619
                   'bzrlib.tests.test_knit',
 
1620
                   'bzrlib.tests.test_lazy_import',
 
1621
                   'bzrlib.tests.test_lazy_regex',
 
1622
                   'bzrlib.tests.test_lockdir',
 
1623
                   'bzrlib.tests.test_lockable_files',
 
1624
                   'bzrlib.tests.test_log',
 
1625
                   'bzrlib.tests.test_memorytree',
 
1626
                   'bzrlib.tests.test_merge',
 
1627
                   'bzrlib.tests.test_merge3',
 
1628
                   'bzrlib.tests.test_merge_core',
 
1629
                   'bzrlib.tests.test_missing',
 
1630
                   'bzrlib.tests.test_msgeditor',
 
1631
                   'bzrlib.tests.test_nonascii',
 
1632
                   'bzrlib.tests.test_options',
 
1633
                   'bzrlib.tests.test_osutils',
 
1634
                   'bzrlib.tests.test_patch',
 
1635
                   'bzrlib.tests.test_patches',
 
1636
                   'bzrlib.tests.test_permissions',
 
1637
                   'bzrlib.tests.test_plugins',
 
1638
                   'bzrlib.tests.test_progress',
 
1639
                   'bzrlib.tests.test_reconcile',
 
1640
                   'bzrlib.tests.test_repository',
 
1641
                   'bzrlib.tests.test_revert',
 
1642
                   'bzrlib.tests.test_revision',
 
1643
                   'bzrlib.tests.test_revisionnamespaces',
 
1644
                   'bzrlib.tests.test_revisiontree',
 
1645
                   'bzrlib.tests.test_rio',
 
1646
                   'bzrlib.tests.test_sampler',
 
1647
                   'bzrlib.tests.test_selftest',
 
1648
                   'bzrlib.tests.test_setup',
 
1649
                   'bzrlib.tests.test_sftp_transport',
 
1650
                   'bzrlib.tests.test_smart_add',
 
1651
                   'bzrlib.tests.test_smart_transport',
 
1652
                   'bzrlib.tests.test_source',
 
1653
                   'bzrlib.tests.test_status',
 
1654
                   'bzrlib.tests.test_store',
 
1655
                   'bzrlib.tests.test_symbol_versioning',
 
1656
                   'bzrlib.tests.test_testament',
 
1657
                   'bzrlib.tests.test_textfile',
 
1658
                   'bzrlib.tests.test_textmerge',
 
1659
                   'bzrlib.tests.test_trace',
 
1660
                   'bzrlib.tests.test_transactions',
 
1661
                   'bzrlib.tests.test_transform',
 
1662
                   'bzrlib.tests.test_transport',
 
1663
                   'bzrlib.tests.test_tree',
 
1664
                   'bzrlib.tests.test_treebuilder',
 
1665
                   'bzrlib.tests.test_tsort',
 
1666
                   'bzrlib.tests.test_tuned_gzip',
 
1667
                   'bzrlib.tests.test_ui',
 
1668
                   'bzrlib.tests.test_upgrade',
 
1669
                   'bzrlib.tests.test_urlutils',
 
1670
                   'bzrlib.tests.test_versionedfile',
 
1671
                   'bzrlib.tests.test_version',
 
1672
                   'bzrlib.tests.test_version_info',
 
1673
                   'bzrlib.tests.test_weave',
 
1674
                   'bzrlib.tests.test_whitebox',
 
1675
                   'bzrlib.tests.test_workingtree',
 
1676
                   'bzrlib.tests.test_xml',
 
1677
                   ]
 
1678
    test_transport_implementations = [
 
1679
        'bzrlib.tests.test_transport_implementations',
 
1680
        'bzrlib.tests.test_read_bundle',
 
1681
        ]
 
1682
    suite = TestUtil.TestSuite()
 
1683
    loader = TestUtil.TestLoader()
 
1684
    suite.addTest(loader.loadTestsFromModuleNames(testmod_names))
 
1685
    from bzrlib.transport import TransportTestProviderAdapter
 
1686
    adapter = TransportTestProviderAdapter()
 
1687
    adapt_modules(test_transport_implementations, adapter, loader, suite)
 
1688
    for package in packages_to_test():
 
1689
        suite.addTest(package.test_suite())
 
1690
    for m in MODULES_TO_TEST:
 
1691
        suite.addTest(loader.loadTestsFromModule(m))
 
1692
    for m in MODULES_TO_DOCTEST:
 
1693
        suite.addTest(doctest.DocTestSuite(m))
 
1694
    for name, plugin in bzrlib.plugin.all_plugins().items():
 
1695
        if getattr(plugin, 'test_suite', None) is not None:
 
1696
            suite.addTest(plugin.test_suite())
 
1697
    return suite
 
1698
 
 
1699
 
 
1700
def adapt_modules(mods_list, adapter, loader, suite):
 
1701
    """Adapt the modules in mods_list using adapter and add to suite."""
 
1702
    for test in iter_suite_tests(loader.loadTestsFromModuleNames(mods_list)):
 
1703
        suite.addTests(adapter.adapt(test))