/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: v.ladeuil+lp at free
  • Date: 2006-10-12 14:29:32 UTC
  • mto: (2145.1.1 keepalive)
  • mto: This revision was merged to the branch mainline in revision 2146.
  • Revision ID: v.ladeuil+lp@free.fr-20061012142932-7221fe16d2b48fa3
Shuffle http related test code. Hopefully it ends up at the right place :)

* bzrlib/tests/HttpServer.py: 
New file. bzrlib.tests.ChrootedTestCase use HttpServer. So the
class can't be defined in bzrlib.tests.HTTPUtils because it
creates a circular dependency (bzrlib.tests.HTTPUtils needs to
import bzrlib.tests).

* bzrlib/transport/http/_urllib.py: 
Transfer test server definition to bzrlib.tests.HttpServer. Clean
up imports.

* bzrlib/transport/http/_pycurl.py: 
Transfer test server definition to bzrlib.tests.HttpServer. Clean
up imports.

* bzrlib/transport/http/__init__.py: 
Transfer all test related code to either bzrlib.tests.HttpServer
and bzrlib.tests.HTTPUtils.
Fix all use of TransportNotPossible and InvalidURL by prefixing it
by 'errors.' (this seems to be the preferred way in the rest of
bzr).
Get rid of unused imports.

* bzrlib/tests/test_transport.py:
(ReadonlyDecoratorTransportTest.test_local_parameters,
FakeNFSDecoratorTests.test_http_parameters): Use HttpServer from
bzrlib.tests.HttpServer instead of bzrlib.transport.http.

* bzrlib/tests/test_sftp_transport.py:
(set_test_transport_to_sftp): Use HttpServer from
bzrlib.tests.HttpServer instead of bzrlib.transport.http.

* bzrlib/tests/test_selftest.py:
(TestTestCaseWithTransport.test_get_readonly_url_http): Use
HttpServer from bzrlib.tests.HttpServer instead of
bzrlib.transport.http.

* bzrlib/tests/test_repository.py: 
Does *not* use HttpServer.

* bzrlib/tests/test_http.py: 
Build on top of bzrlib.tests.HttpServer and bzrlib.tests.HTTPUtils
instead of bzrlib.transport.http.

* bzrlib/tests/test_bzrdir.py:
(ChrootedTests.setUp): Use HttpServer from bzrlib.tests.HttpServer
instead of bzrlib.transport.http.

* bzrlib/tests/branch_implementations/test_http.py:
(HTTPBranchTests.setUp): Use HttpServer from bzrlib.tests.HttpServer
instead of bzrlib.transport.http.

* bzrlib/tests/branch_implementations/test_branch.py:
(ChrootedTests.setUp): Use HttpServer from bzrlib.tests.HttpServer
instead of bzrlib.transport.http.

* bzrlib/tests/__init__.py:
(ChrootedTestCase.setUp): Use HttpServer from
bzrlib.tests.HttpServer instead of bzrlib.transport.http.

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