~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/__init__.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2006-12-07 17:20:51 UTC
  • mfrom: (1551.9.10 Aaron's mergeable stuff)
  • Revision ID: pqm@pqm.ubuntu.com-20061207172051-43fe52677c8dfb85
Fix bugs in execute bit handling by revert

Show diffs side-by-side

added added

removed removed

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