/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: Aaron Bentley
  • Date: 2007-02-06 14:52:16 UTC
  • mfrom: (2266 +trunk)
  • mto: This revision was merged to the branch mainline in revision 2268.
  • Revision ID: abentley@panoramicfeedback.com-20070206145216-fcpi8o3ufvuzwbp9
Merge bzr.dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006 by Canonical Ltd
 
1
# Copyright (C) 2005, 2006 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
43
43
import time
44
44
 
45
45
 
46
 
from bzrlib import memorytree
 
46
from bzrlib import (
 
47
    bzrdir,
 
48
    debug,
 
49
    errors,
 
50
    memorytree,
 
51
    osutils,
 
52
    progress,
 
53
    urlutils,
 
54
    )
47
55
import bzrlib.branch
48
 
import bzrlib.bzrdir as bzrdir
49
56
import bzrlib.commands
50
57
import bzrlib.bundle.serializer
51
 
import bzrlib.errors as errors
52
58
import bzrlib.export
53
59
import bzrlib.inventory
54
60
import bzrlib.iterablefile
61
67
from bzrlib.merge import merge_inner
62
68
import bzrlib.merge3
63
69
import bzrlib.osutils
64
 
import bzrlib.osutils as osutils
65
70
import bzrlib.plugin
66
 
import bzrlib.progress as progress
67
71
from bzrlib.revision import common_ancestor
68
72
import bzrlib.store
69
73
from bzrlib import symbol_versioning
70
74
import bzrlib.trace
71
75
from bzrlib.transport import get_transport
72
76
import bzrlib.transport
73
 
from bzrlib.transport.local import LocalRelpathServer
 
77
from bzrlib.transport.local import LocalURLServer
 
78
from bzrlib.transport.memory import MemoryServer
74
79
from bzrlib.transport.readonly import ReadonlyServer
75
 
from bzrlib.trace import mutter
 
80
from bzrlib.trace import mutter, note
76
81
from bzrlib.tests import TestUtil
 
82
from bzrlib.tests.HttpServer import HttpServer
77
83
from bzrlib.tests.TestUtil import (
78
84
                          TestSuite,
79
85
                          TestLoader,
80
86
                          )
81
87
from bzrlib.tests.treeshape import build_tree_contents
82
 
import bzrlib.urlutils as urlutils
83
88
from bzrlib.workingtree import WorkingTree, WorkingTreeFormat2
84
89
 
85
 
default_transport = LocalRelpathServer
 
90
default_transport = LocalURLServer
86
91
 
87
92
MODULES_TO_TEST = []
88
93
MODULES_TO_DOCTEST = [
89
 
                      bzrlib.branch,
90
94
                      bzrlib.bundle.serializer,
91
 
                      bzrlib.commands,
92
95
                      bzrlib.errors,
93
96
                      bzrlib.export,
94
97
                      bzrlib.inventory,
96
99
                      bzrlib.lockdir,
97
100
                      bzrlib.merge3,
98
101
                      bzrlib.option,
99
 
                      bzrlib.osutils,
100
102
                      bzrlib.store,
101
 
                      bzrlib.transport,
102
103
                      ]
103
104
 
104
105
 
134
135
            ]
135
136
 
136
137
 
137
 
class _MyResult(unittest._TextTestResult):
138
 
    """Custom TestResult.
 
138
class ExtendedTestResult(unittest._TextTestResult):
 
139
    """Accepts, reports and accumulates the results of running tests.
139
140
 
140
 
    Shows output in a different format, including displaying runtime for tests.
 
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.
141
144
    """
 
145
 
142
146
    stop_early = False
143
147
    
144
 
    def __init__(self, stream, descriptions, verbosity, pb=None,
145
 
                 bench_history=None):
 
148
    def __init__(self, stream, descriptions, verbosity,
 
149
                 bench_history=None,
 
150
                 num_tests=None,
 
151
                 ):
146
152
        """Construct new TestResult.
147
153
 
148
154
        :param bench_history: Optionally, a writable file object to accumulate
149
155
            benchmark results.
150
156
        """
151
157
        unittest._TextTestResult.__init__(self, stream, descriptions, verbosity)
152
 
        self.pb = pb
153
158
        if bench_history is not None:
154
159
            from bzrlib.version import _get_bzr_source_tree
155
160
            src_tree = _get_bzr_source_tree()
165
170
                revision_id = ''
166
171
            bench_history.write("--date %s %s\n" % (time.time(), revision_id))
167
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()
168
180
    
169
181
    def extractBenchmarkTime(self, testCase):
170
182
        """Add a benchmark time for the current test case."""
180
192
                self._formatTime(self._benchmarkTime),
181
193
                self._elapsedTestTimeString())
182
194
        else:
183
 
            return "      %s" % self._elapsedTestTimeString()
 
195
            return "           %s" % self._elapsedTestTimeString()
184
196
 
185
197
    def _formatTime(self, seconds):
186
198
        """Format seconds as milliseconds with leading spaces."""
187
 
        return "%5dms" % (1000 * seconds)
 
199
        # some benchmarks can take thousands of seconds to run, so we need 8
 
200
        # places
 
201
        return "%8dms" % (1000 * seconds)
188
202
 
189
 
    def _ellipsise_unimportant_words(self, a_string, final_width,
190
 
                                   keep_start=False):
191
 
        """Add ellipses (sp?) for overly long strings.
192
 
        
193
 
        :param keep_start: If true preserve the start of a_string rather
194
 
                           than the end of it.
195
 
        """
196
 
        if keep_start:
197
 
            if len(a_string) > final_width:
198
 
                result = a_string[:final_width-3] + '...'
199
 
            else:
200
 
                result = a_string
201
 
        else:
202
 
            if len(a_string) > final_width:
203
 
                result = '...' + a_string[3-final_width:]
204
 
            else:
205
 
                result = a_string
206
 
        return result.ljust(final_width)
 
203
    def _shortened_test_description(self, test):
 
204
        what = test.id()
 
205
        what = re.sub(r'^bzrlib\.(tests|benchmarks)\.', '', what)
 
206
        return what
207
207
 
208
208
    def startTest(self, test):
209
209
        unittest.TestResult.startTest(self, test)
210
 
        # In a short description, the important words are in
211
 
        # the beginning, but in an id, the important words are
212
 
        # at the end
213
 
        SHOW_DESCRIPTIONS = False
214
 
 
215
 
        if not self.showAll and self.dots and self.pb is not None:
216
 
            final_width = 13
217
 
        else:
218
 
            final_width = osutils.terminal_width()
219
 
            final_width = final_width - 15 - 8
220
 
        what = None
221
 
        if SHOW_DESCRIPTIONS:
222
 
            what = test.shortDescription()
223
 
            if what:
224
 
                what = self._ellipsise_unimportant_words(what, final_width, keep_start=True)
225
 
        if what is None:
226
 
            what = test.id()
227
 
            if what.startswith('bzrlib.tests.'):
228
 
                what = what[13:]
229
 
            what = self._ellipsise_unimportant_words(what, final_width)
230
 
        if self.showAll:
231
 
            self.stream.write(what)
232
 
        elif self.dots and self.pb is not None:
233
 
            self.pb.update(what, self.testsRun - 1, None)
234
 
        self.stream.flush()
 
210
        self.report_test_start(test)
235
211
        self._recordTestStartTime()
236
212
 
237
213
    def _recordTestStartTime(self):
248
224
        if setKeepLogfile is not None:
249
225
            setKeepLogfile()
250
226
        self.extractBenchmarkTime(test)
251
 
        if self.showAll:
252
 
            self.stream.writeln("ERROR %s" % self._testTimeString())
253
 
        elif self.dots and self.pb is None:
254
 
            self.stream.write('E')
255
 
        elif self.dots:
256
 
            self.pb.update(self._ellipsise_unimportant_words('ERROR', 13), self.testsRun, None)
257
 
            self.pb.note(self._ellipsise_unimportant_words(
258
 
                            test.id() + ': ERROR',
259
 
                            osutils.terminal_width()))
260
 
        self.stream.flush()
 
227
        self.report_error(test, err)
261
228
        if self.stop_early:
262
229
            self.stop()
263
230
 
269
236
        if setKeepLogfile is not None:
270
237
            setKeepLogfile()
271
238
        self.extractBenchmarkTime(test)
272
 
        if self.showAll:
273
 
            self.stream.writeln(" FAIL %s" % self._testTimeString())
274
 
        elif self.dots and self.pb is None:
275
 
            self.stream.write('F')
276
 
        elif self.dots:
277
 
            self.pb.update(self._ellipsise_unimportant_words('FAIL', 13), self.testsRun, None)
278
 
            self.pb.note(self._ellipsise_unimportant_words(
279
 
                            test.id() + ': FAIL',
280
 
                            osutils.terminal_width()))
281
 
        self.stream.flush()
 
239
        self.report_failure(test, err)
282
240
        if self.stop_early:
283
241
            self.stop()
284
242
 
289
247
                self._bench_history.write("%s %s\n" % (
290
248
                    self._formatTime(self._benchmarkTime),
291
249
                    test.id()))
292
 
        if self.showAll:
293
 
            self.stream.writeln('   OK %s' % self._testTimeString())
294
 
            for bench_called, stats in getattr(test, '_benchcalls', []):
295
 
                self.stream.writeln('LSProf output for %s(%s, %s)' % bench_called)
296
 
                stats.pprint(file=self.stream)
297
 
        elif self.dots and self.pb is None:
298
 
            self.stream.write('~')
299
 
        elif self.dots:
300
 
            self.pb.update(self._ellipsise_unimportant_words('OK', 13), self.testsRun, None)
301
 
        self.stream.flush()
 
250
        self.report_success(test)
302
251
        unittest.TestResult.addSuccess(self, test)
303
252
 
304
253
    def addSkipped(self, test, skip_excinfo):
305
254
        self.extractBenchmarkTime(test)
306
 
        if self.showAll:
307
 
            print >>self.stream, ' SKIP %s' % self._testTimeString()
308
 
            print >>self.stream, '     %s' % skip_excinfo[1]
309
 
        elif self.dots and self.pb is None:
310
 
            self.stream.write('S')
311
 
        elif self.dots:
312
 
            self.pb.update(self._ellipsise_unimportant_words('SKIP', 13), self.testsRun, None)
313
 
        self.stream.flush()
 
255
        self.report_skip(test, skip_excinfo)
314
256
        # seems best to treat this as success from point-of-view of unittest
315
257
        # -- it actually does nothing so it barely matters :)
316
258
        try:
336
278
            self.stream.writeln(self.separator2)
337
279
            self.stream.writeln("%s" % err)
338
280
 
 
281
    def finished(self):
 
282
        pass
 
283
 
 
284
    def report_cleaning_up(self):
 
285
        pass
 
286
 
 
287
    def report_success(self, test):
 
288
        pass
 
289
 
 
290
 
 
291
class TextTestResult(ExtendedTestResult):
 
292
    """Displays progress and results of tests in text form"""
 
293
 
 
294
    def __init__(self, *args, **kw):
 
295
        ExtendedTestResult.__init__(self, *args, **kw)
 
296
        self.pb = self.ui.nested_progress_bar()
 
297
        self.pb.show_pct = False
 
298
        self.pb.show_spinner = False
 
299
        self.pb.show_eta = False, 
 
300
        self.pb.show_count = False
 
301
        self.pb.show_bar = False
 
302
 
 
303
    def report_starting(self):
 
304
        self.pb.update('[test 0/%d] starting...' % (self.num_tests))
 
305
 
 
306
    def _progress_prefix_text(self):
 
307
        a = '[%d' % self.count
 
308
        if self.num_tests is not None:
 
309
            a +='/%d' % self.num_tests
 
310
        a += ' in %ds' % (time.time() - self._overall_start_time)
 
311
        if self.error_count:
 
312
            a += ', %d errors' % self.error_count
 
313
        if self.failure_count:
 
314
            a += ', %d failed' % self.failure_count
 
315
        if self.skip_count:
 
316
            a += ', %d skipped' % self.skip_count
 
317
        a += ']'
 
318
        return a
 
319
 
 
320
    def report_test_start(self, test):
 
321
        self.count += 1
 
322
        self.pb.update(
 
323
                self._progress_prefix_text()
 
324
                + ' ' 
 
325
                + self._shortened_test_description(test))
 
326
 
 
327
    def report_error(self, test, err):
 
328
        self.error_count += 1
 
329
        self.pb.note('ERROR: %s\n    %s\n', 
 
330
            self._shortened_test_description(test),
 
331
            err[1],
 
332
            )
 
333
 
 
334
    def report_failure(self, test, err):
 
335
        self.failure_count += 1
 
336
        self.pb.note('FAIL: %s\n    %s\n', 
 
337
            self._shortened_test_description(test),
 
338
            err[1],
 
339
            )
 
340
 
 
341
    def report_skip(self, test, skip_excinfo):
 
342
        self.skip_count += 1
 
343
        if False:
 
344
            # at the moment these are mostly not things we can fix
 
345
            # and so they just produce stipple; use the verbose reporter
 
346
            # to see them.
 
347
            if False:
 
348
                # show test and reason for skip
 
349
                self.pb.note('SKIP: %s\n    %s\n', 
 
350
                    self._shortened_test_description(test),
 
351
                    skip_excinfo[1])
 
352
            else:
 
353
                # since the class name was left behind in the still-visible
 
354
                # progress bar...
 
355
                self.pb.note('SKIP: %s', skip_excinfo[1])
 
356
 
 
357
    def report_cleaning_up(self):
 
358
        self.pb.update('cleaning up...')
 
359
 
 
360
    def finished(self):
 
361
        self.pb.finished()
 
362
 
 
363
 
 
364
class VerboseTestResult(ExtendedTestResult):
 
365
    """Produce long output, with one line per test run plus times"""
 
366
 
 
367
    def _ellipsize_to_right(self, a_string, final_width):
 
368
        """Truncate and pad a string, keeping the right hand side"""
 
369
        if len(a_string) > final_width:
 
370
            result = '...' + a_string[3-final_width:]
 
371
        else:
 
372
            result = a_string
 
373
        return result.ljust(final_width)
 
374
 
 
375
    def report_starting(self):
 
376
        self.stream.write('running %d tests...\n' % self.num_tests)
 
377
 
 
378
    def report_test_start(self, test):
 
379
        self.count += 1
 
380
        name = self._shortened_test_description(test)
 
381
        # width needs space for 6 char status, plus 1 for slash, plus 2 10-char
 
382
        # numbers, plus a trailing blank
 
383
        self.stream.write(self._ellipsize_to_right(name,
 
384
                            osutils.terminal_width()-30))
 
385
        self.stream.flush()
 
386
 
 
387
    def report_error(self, test, err):
 
388
        self.error_count += 1
 
389
        self.stream.writeln('ERROR %s\n    %s' 
 
390
                % (self._testTimeString(), err[1]))
 
391
 
 
392
    def report_failure(self, test, err):
 
393
        self.failure_count += 1
 
394
        self.stream.writeln(' FAIL %s\n    %s'
 
395
                % (self._testTimeString(), err[1]))
 
396
 
 
397
    def report_success(self, test):
 
398
        self.stream.writeln('   OK %s' % self._testTimeString())
 
399
        for bench_called, stats in getattr(test, '_benchcalls', []):
 
400
            self.stream.writeln('LSProf output for %s(%s, %s)' % bench_called)
 
401
            stats.pprint(file=self.stream)
 
402
        self.stream.flush()
 
403
 
 
404
    def report_skip(self, test, skip_excinfo):
 
405
        print >>self.stream, ' SKIP %s' % self._testTimeString()
 
406
        print >>self.stream, '     %s' % skip_excinfo[1]
 
407
 
339
408
 
340
409
class TextTestRunner(object):
341
410
    stop_on_failure = False
345
414
                 descriptions=0,
346
415
                 verbosity=1,
347
416
                 keep_output=False,
348
 
                 pb=None,
349
417
                 bench_history=None):
350
418
        self.stream = unittest._WritelnDecorator(stream)
351
419
        self.descriptions = descriptions
352
420
        self.verbosity = verbosity
353
421
        self.keep_output = keep_output
354
 
        self.pb = pb
355
422
        self._bench_history = bench_history
356
423
 
357
 
    def _makeResult(self):
358
 
        result = _MyResult(self.stream,
359
 
                           self.descriptions,
360
 
                           self.verbosity,
361
 
                           pb=self.pb,
362
 
                           bench_history=self._bench_history)
363
 
        result.stop_early = self.stop_on_failure
364
 
        return result
365
 
 
366
424
    def run(self, test):
367
425
        "Run the given test case or test suite."
368
 
        result = self._makeResult()
369
426
        startTime = time.time()
370
 
        if self.pb is not None:
371
 
            self.pb.update('Running tests', 0, test.countTestCases())
 
427
        if self.verbosity == 1:
 
428
            result_class = TextTestResult
 
429
        elif self.verbosity >= 2:
 
430
            result_class = VerboseTestResult
 
431
        result = result_class(self.stream,
 
432
                              self.descriptions,
 
433
                              self.verbosity,
 
434
                              bench_history=self._bench_history,
 
435
                              num_tests=test.countTestCases(),
 
436
                              )
 
437
        result.stop_early = self.stop_on_failure
 
438
        result.report_starting()
372
439
        test.run(result)
373
440
        stopTime = time.time()
374
441
        timeTaken = stopTime - startTime
389
456
            self.stream.writeln(")")
390
457
        else:
391
458
            self.stream.writeln("OK")
392
 
        if self.pb is not None:
393
 
            self.pb.update('Cleaning up', 0, 1)
 
459
        result.report_cleaning_up()
394
460
        # This is still a little bogus, 
395
461
        # but only a little. Folk not using our testrunner will
396
462
        # have to delete their temp directories themselves.
397
 
        test_root = TestCaseInTempDir.TEST_ROOT
 
463
        test_root = TestCaseWithMemoryTransport.TEST_ROOT
398
464
        if result.wasSuccessful() or not self.keep_output:
399
465
            if test_root is not None:
400
466
                # If LANG=C we probably have created some bogus paths
411
477
                        sys.getfilesystemencoding())
412
478
                osutils.rmtree(test_root)
413
479
        else:
414
 
            if self.pb is not None:
415
 
                self.pb.note("Failed tests working directories are in '%s'\n",
416
 
                             test_root)
417
 
            else:
418
 
                self.stream.writeln(
419
 
                    "Failed tests working directories are in '%s'\n" %
420
 
                    test_root)
421
 
        TestCaseInTempDir.TEST_ROOT = None
422
 
        if self.pb is not None:
423
 
            self.pb.clear()
 
480
            note("Failed tests working directories are in '%s'\n", test_root)
 
481
        TestCaseWithMemoryTransport.TEST_ROOT = None
 
482
        result.finished()
424
483
        return result
425
484
 
426
485
 
506
565
        unittest.TestCase.setUp(self)
507
566
        self._cleanEnvironment()
508
567
        bzrlib.trace.disable_default_logging()
 
568
        self._silenceUI()
509
569
        self._startLogFile()
510
570
        self._benchcalls = []
511
571
        self._benchtime = None
 
572
        # prevent hooks affecting tests
 
573
        self._preserved_hooks = bzrlib.branch.Branch.hooks
 
574
        self.addCleanup(self._restoreHooks)
 
575
        # this list of hooks must be kept in sync with the defaults
 
576
        # in branch.py
 
577
        bzrlib.branch.Branch.hooks = bzrlib.branch.BranchHooks()
 
578
 
 
579
    def _silenceUI(self):
 
580
        """Turn off UI for duration of test"""
 
581
        # by default the UI is off; tests can turn it on if they want it.
 
582
        saved = bzrlib.ui.ui_factory
 
583
        def _restore():
 
584
            bzrlib.ui.ui_factory = saved
 
585
        bzrlib.ui.ui_factory = bzrlib.ui.SilentUIFactory()
 
586
        self.addCleanup(_restore)
512
587
 
513
588
    def _ndiff_strings(self, a, b):
514
589
        """Return ndiff between two strings containing lines.
574
649
            raise AssertionError("value(s) %r not present in container %r" % 
575
650
                                 (missing, superlist))
576
651
 
577
 
    def assertIs(self, left, right):
 
652
    def assertListRaises(self, excClass, func, *args, **kwargs):
 
653
        """Fail unless excClass is raised when the iterator from func is used.
 
654
        
 
655
        Many functions can return generators this makes sure
 
656
        to wrap them in a list() call to make sure the whole generator
 
657
        is run, and that the proper exception is raised.
 
658
        """
 
659
        try:
 
660
            list(func(*args, **kwargs))
 
661
        except excClass:
 
662
            return
 
663
        else:
 
664
            if getattr(excClass,'__name__', None) is not None:
 
665
                excName = excClass.__name__
 
666
            else:
 
667
                excName = str(excClass)
 
668
            raise self.failureException, "%s not raised" % excName
 
669
 
 
670
    def assertIs(self, left, right, message=None):
578
671
        if not (left is right):
579
 
            raise AssertionError("%r is not %r." % (left, right))
 
672
            if message is not None:
 
673
                raise AssertionError(message)
 
674
            else:
 
675
                raise AssertionError("%r is not %r." % (left, right))
 
676
 
 
677
    def assertIsNot(self, left, right, message=None):
 
678
        if (left is right):
 
679
            if message is not None:
 
680
                raise AssertionError(message)
 
681
            else:
 
682
                raise AssertionError("%r is %r." % (left, right))
580
683
 
581
684
    def assertTransportMode(self, transport, path, mode):
582
685
        """Fail if a path does not have mode mode.
606
709
            a_callable(*args, **kwargs).
607
710
        """
608
711
        local_warnings = []
609
 
        def capture_warnings(msg, cls, stacklevel=None):
 
712
        def capture_warnings(msg, cls=None, stacklevel=None):
610
713
            # we've hooked into a deprecation specific callpath,
611
714
            # only deprecations should getting sent via it.
612
715
            self.assertEqual(cls, DeprecationWarning)
703
806
 
704
807
    def _cleanEnvironment(self):
705
808
        new_env = {
 
809
            'BZR_HOME': None, # Don't inherit BZR_HOME to all the tests.
706
810
            'HOME': os.getcwd(),
707
811
            'APPDATA': os.getcwd(),
708
812
            'BZR_EMAIL': None,
709
813
            'BZREMAIL': None, # may still be present in the environment
710
814
            'EMAIL': None,
711
815
            'BZR_PROGRESS_BAR': None,
 
816
            # Proxies
 
817
            'http_proxy': None,
 
818
            'HTTP_PROXY': None,
 
819
            'https_proxy': None,
 
820
            'HTTPS_PROXY': None,
 
821
            'no_proxy': None,
 
822
            'NO_PROXY': None,
 
823
            'all_proxy': None,
 
824
            'ALL_PROXY': None,
 
825
            # Nobody cares about these ones AFAIK. So far at
 
826
            # least. If you do (care), please update this comment
 
827
            # -- vila 20061212
 
828
            'ftp_proxy': None,
 
829
            'FTP_PROXY': None,
712
830
        }
713
831
        self.__old_env = {}
714
832
        self.addCleanup(self._restoreEnvironment)
723
841
        for name, value in self.__old_env.iteritems():
724
842
            osutils.set_or_unset_env(name, value)
725
843
 
 
844
    def _restoreHooks(self):
 
845
        bzrlib.branch.Branch.hooks = self._preserved_hooks
 
846
 
726
847
    def tearDown(self):
727
848
        self._runCleanups()
728
849
        unittest.TestCase.tearDown(self)
839
960
            os.chdir(working_dir)
840
961
 
841
962
        try:
842
 
            result = self.apply_redirected(stdin, stdout, stderr,
843
 
                                           bzrlib.commands.run_bzr_catch_errors,
844
 
                                           argv)
 
963
            saved_debug_flags = frozenset(debug.debug_flags)
 
964
            debug.debug_flags.clear()
 
965
            try:
 
966
                result = self.apply_redirected(stdin, stdout, stderr,
 
967
                                               bzrlib.commands.run_bzr_catch_errors,
 
968
                                               argv)
 
969
            finally:
 
970
                debug.debug_flags.update(saved_debug_flags)
845
971
        finally:
846
972
            logger.removeHandler(handler)
847
973
            bzrlib.ui.ui_factory = old_ui_factory
929
1055
            The values must be strings. The change will only occur in the
930
1056
            child, so you don't need to fix the environment after running.
931
1057
        :param universal_newlines: Convert CRLF => LF
 
1058
        :param allow_plugins: By default the subprocess is run with
 
1059
            --no-plugins to ensure test reproducibility. Also, it is possible
 
1060
            for system-wide plugins to create unexpected output on stderr,
 
1061
            which can cause unnecessary test failures.
932
1062
        """
933
1063
        env_changes = kwargs.get('env_changes', {})
934
1064
        working_dir = kwargs.get('working_dir', None)
 
1065
        allow_plugins = kwargs.get('allow_plugins', False)
935
1066
        process = self.start_bzr_subprocess(args, env_changes=env_changes,
936
 
                                            working_dir=working_dir)
 
1067
                                            working_dir=working_dir,
 
1068
                                            allow_plugins=allow_plugins)
937
1069
        # We distinguish between retcode=None and retcode not passed.
938
1070
        supplied_retcode = kwargs.get('retcode', 0)
939
1071
        return self.finish_bzr_subprocess(process, retcode=supplied_retcode,
942
1074
 
943
1075
    def start_bzr_subprocess(self, process_args, env_changes=None,
944
1076
                             skip_if_plan_to_signal=False,
945
 
                             working_dir=None):
 
1077
                             working_dir=None,
 
1078
                             allow_plugins=False):
946
1079
        """Start bzr in a subprocess for testing.
947
1080
 
948
1081
        This starts a new Python interpreter and runs bzr in there.
959
1092
            child, so you don't need to fix the environment after running.
960
1093
        :param skip_if_plan_to_signal: raise TestSkipped when true and os.kill
961
1094
            is not available.
 
1095
        :param allow_plugins: If False (default) pass --no-plugins to bzr.
962
1096
 
963
1097
        :returns: Popen object for the started process.
964
1098
        """
990
1124
            # so we will avoid using it on all platforms, just to
991
1125
            # make sure the code path is used, and we don't break on win32
992
1126
            cleanup_environment()
993
 
            process = Popen([sys.executable, bzr_path] + list(process_args),
994
 
                             stdin=PIPE, stdout=PIPE, stderr=PIPE)
 
1127
            command = [sys.executable, bzr_path]
 
1128
            if not allow_plugins:
 
1129
                command.append('--no-plugins')
 
1130
            command.extend(process_args)
 
1131
            process = self._popen(command, stdin=PIPE, stdout=PIPE, stderr=PIPE)
995
1132
        finally:
996
1133
            restore_environment()
997
1134
            if cwd is not None:
999
1136
 
1000
1137
        return process
1001
1138
 
 
1139
    def _popen(self, *args, **kwargs):
 
1140
        """Place a call to Popen.
 
1141
 
 
1142
        Allows tests to override this method to intercept the calls made to
 
1143
        Popen for introspection.
 
1144
        """
 
1145
        return Popen(*args, **kwargs)
 
1146
 
1002
1147
    def get_bzr_path(self):
1003
1148
        """Return the path of the 'bzr' executable for this test suite."""
1004
1149
        bzr_path = os.path.dirname(os.path.dirname(bzrlib.__file__))+'/bzr'
1107
1252
 
1108
1253
BzrTestBase = TestCase
1109
1254
 
 
1255
 
 
1256
class TestCaseWithMemoryTransport(TestCase):
 
1257
    """Common test class for tests that do not need disk resources.
 
1258
 
 
1259
    Tests that need disk resources should derive from TestCaseWithTransport.
 
1260
 
 
1261
    TestCaseWithMemoryTransport sets the TEST_ROOT variable for all bzr tests.
 
1262
 
 
1263
    For TestCaseWithMemoryTransport the test_home_dir is set to the name of
 
1264
    a directory which does not exist. This serves to help ensure test isolation
 
1265
    is preserved. test_dir is set to the TEST_ROOT, as is cwd, because they
 
1266
    must exist. However, TestCaseWithMemoryTransport does not offer local
 
1267
    file defaults for the transport in tests, nor does it obey the command line
 
1268
    override, so tests that accidentally write to the common directory should
 
1269
    be rare.
 
1270
    """
 
1271
 
 
1272
    TEST_ROOT = None
 
1273
    _TEST_NAME = 'test'
 
1274
 
 
1275
 
 
1276
    def __init__(self, methodName='runTest'):
 
1277
        # allow test parameterisation after test construction and before test
 
1278
        # execution. Variables that the parameteriser sets need to be 
 
1279
        # ones that are not set by setUp, or setUp will trash them.
 
1280
        super(TestCaseWithMemoryTransport, self).__init__(methodName)
 
1281
        self.transport_server = default_transport
 
1282
        self.transport_readonly_server = None
 
1283
 
 
1284
    def get_transport(self):
 
1285
        """Return a writeable transport for the test scratch space"""
 
1286
        t = get_transport(self.get_url())
 
1287
        self.assertFalse(t.is_readonly())
 
1288
        return t
 
1289
 
 
1290
    def get_readonly_transport(self):
 
1291
        """Return a readonly transport for the test scratch space
 
1292
        
 
1293
        This can be used to test that operations which should only need
 
1294
        readonly access in fact do not try to write.
 
1295
        """
 
1296
        t = get_transport(self.get_readonly_url())
 
1297
        self.assertTrue(t.is_readonly())
 
1298
        return t
 
1299
 
 
1300
    def create_transport_readonly_server(self):
 
1301
        """Create a transport server from class defined at init.
 
1302
 
 
1303
        This is mostly a hook for daughter classes.
 
1304
        """
 
1305
        return self.transport_readonly_server()
 
1306
 
 
1307
    def get_readonly_server(self):
 
1308
        """Get the server instance for the readonly transport
 
1309
 
 
1310
        This is useful for some tests with specific servers to do diagnostics.
 
1311
        """
 
1312
        if self.__readonly_server is None:
 
1313
            if self.transport_readonly_server is None:
 
1314
                # readonly decorator requested
 
1315
                # bring up the server
 
1316
                self.get_url()
 
1317
                self.__readonly_server = ReadonlyServer()
 
1318
                self.__readonly_server.setUp(self.__server)
 
1319
            else:
 
1320
                self.__readonly_server = self.create_transport_readonly_server()
 
1321
                self.__readonly_server.setUp()
 
1322
            self.addCleanup(self.__readonly_server.tearDown)
 
1323
        return self.__readonly_server
 
1324
 
 
1325
    def get_readonly_url(self, relpath=None):
 
1326
        """Get a URL for the readonly transport.
 
1327
 
 
1328
        This will either be backed by '.' or a decorator to the transport 
 
1329
        used by self.get_url()
 
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_readonly_server().get_url()
 
1334
        if relpath is not None:
 
1335
            if not base.endswith('/'):
 
1336
                base = base + '/'
 
1337
            base = base + relpath
 
1338
        return base
 
1339
 
 
1340
    def get_server(self):
 
1341
        """Get the read/write server instance.
 
1342
 
 
1343
        This is useful for some tests with specific servers that need
 
1344
        diagnostics.
 
1345
 
 
1346
        For TestCaseWithMemoryTransport this is always a MemoryServer, and there
 
1347
        is no means to override it.
 
1348
        """
 
1349
        if self.__server is None:
 
1350
            self.__server = MemoryServer()
 
1351
            self.__server.setUp()
 
1352
            self.addCleanup(self.__server.tearDown)
 
1353
        return self.__server
 
1354
 
 
1355
    def get_url(self, relpath=None):
 
1356
        """Get a URL (or maybe a path) for the readwrite transport.
 
1357
 
 
1358
        This will either be backed by '.' or to an equivalent non-file based
 
1359
        facility.
 
1360
        relpath provides for clients to get a path relative to the base url.
 
1361
        These should only be downwards relative, not upwards.
 
1362
        """
 
1363
        base = self.get_server().get_url()
 
1364
        if relpath is not None and relpath != '.':
 
1365
            if not base.endswith('/'):
 
1366
                base = base + '/'
 
1367
            # XXX: Really base should be a url; we did after all call
 
1368
            # get_url()!  But sometimes it's just a path (from
 
1369
            # LocalAbspathServer), and it'd be wrong to append urlescaped data
 
1370
            # to a non-escaped local path.
 
1371
            if base.startswith('./') or base.startswith('/'):
 
1372
                base += relpath
 
1373
            else:
 
1374
                base += urlutils.escape(relpath)
 
1375
        return base
 
1376
 
 
1377
    def _make_test_root(self):
 
1378
        if TestCaseWithMemoryTransport.TEST_ROOT is not None:
 
1379
            return
 
1380
        i = 0
 
1381
        while True:
 
1382
            root = u'test%04d.tmp' % i
 
1383
            try:
 
1384
                os.mkdir(root)
 
1385
            except OSError, e:
 
1386
                if e.errno == errno.EEXIST:
 
1387
                    i += 1
 
1388
                    continue
 
1389
                else:
 
1390
                    raise
 
1391
            # successfully created
 
1392
            TestCaseWithMemoryTransport.TEST_ROOT = osutils.abspath(root)
 
1393
            break
 
1394
        # make a fake bzr directory there to prevent any tests propagating
 
1395
        # up onto the source directory's real branch
 
1396
        bzrdir.BzrDir.create_standalone_workingtree(
 
1397
            TestCaseWithMemoryTransport.TEST_ROOT)
 
1398
 
 
1399
    def makeAndChdirToTestDir(self):
 
1400
        """Create a temporary directories for this one test.
 
1401
        
 
1402
        This must set self.test_home_dir and self.test_dir and chdir to
 
1403
        self.test_dir.
 
1404
        
 
1405
        For TestCaseWithMemoryTransport we chdir to the TEST_ROOT for this test.
 
1406
        """
 
1407
        os.chdir(TestCaseWithMemoryTransport.TEST_ROOT)
 
1408
        self.test_dir = TestCaseWithMemoryTransport.TEST_ROOT
 
1409
        self.test_home_dir = self.test_dir + "/MemoryTransportMissingHomeDir"
 
1410
        
 
1411
    def make_branch(self, relpath, format=None):
 
1412
        """Create a branch on the transport at relpath."""
 
1413
        repo = self.make_repository(relpath, format=format)
 
1414
        return repo.bzrdir.create_branch()
 
1415
 
 
1416
    def make_bzrdir(self, relpath, format=None):
 
1417
        try:
 
1418
            # might be a relative or absolute path
 
1419
            maybe_a_url = self.get_url(relpath)
 
1420
            segments = maybe_a_url.rsplit('/', 1)
 
1421
            t = get_transport(maybe_a_url)
 
1422
            if len(segments) > 1 and segments[-1] not in ('', '.'):
 
1423
                try:
 
1424
                    t.mkdir('.')
 
1425
                except errors.FileExists:
 
1426
                    pass
 
1427
            if isinstance(format, basestring):
 
1428
                format = bzrdir.format_registry.make_bzrdir(format)
 
1429
            elif format is None:
 
1430
                format = bzrlib.bzrdir.BzrDirFormat.get_default_format()
 
1431
            return format.initialize_on_transport(t)
 
1432
        except errors.UninitializableFormat:
 
1433
            raise TestSkipped("Format %s is not initializable." % format)
 
1434
 
 
1435
    def make_repository(self, relpath, shared=False, format=None):
 
1436
        """Create a repository on our default transport at relpath."""
 
1437
        made_control = self.make_bzrdir(relpath, format=format)
 
1438
        return made_control.create_repository(shared=shared)
 
1439
 
 
1440
    def make_branch_and_memory_tree(self, relpath, format=None):
 
1441
        """Create a branch on the default transport and a MemoryTree for it."""
 
1442
        b = self.make_branch(relpath, format=format)
 
1443
        return memorytree.MemoryTree.create_on_branch(b)
 
1444
 
 
1445
    def overrideEnvironmentForTesting(self):
 
1446
        os.environ['HOME'] = self.test_home_dir
 
1447
        os.environ['APPDATA'] = self.test_home_dir
 
1448
        
 
1449
    def setUp(self):
 
1450
        super(TestCaseWithMemoryTransport, self).setUp()
 
1451
        self._make_test_root()
 
1452
        _currentdir = os.getcwdu()
 
1453
        def _leaveDirectory():
 
1454
            os.chdir(_currentdir)
 
1455
        self.addCleanup(_leaveDirectory)
 
1456
        self.makeAndChdirToTestDir()
 
1457
        self.overrideEnvironmentForTesting()
 
1458
        self.__readonly_server = None
 
1459
        self.__server = None
 
1460
 
1110
1461
     
1111
 
class TestCaseInTempDir(TestCase):
 
1462
class TestCaseInTempDir(TestCaseWithMemoryTransport):
1112
1463
    """Derived class that runs a test within a temporary directory.
1113
1464
 
1114
1465
    This is useful for tests that need to create a branch, etc.
1121
1472
    InTempDir is an old alias for FunctionalTestCase.
1122
1473
    """
1123
1474
 
1124
 
    TEST_ROOT = None
1125
 
    _TEST_NAME = 'test'
1126
1475
    OVERRIDE_PYTHON = 'python'
1127
1476
 
1128
1477
    def check_file_contents(self, filename, expect):
1133
1482
            self.log("actually: %r" % contents)
1134
1483
            self.fail("contents of %s not as expected" % filename)
1135
1484
 
1136
 
    def _make_test_root(self):
1137
 
        if TestCaseInTempDir.TEST_ROOT is not None:
1138
 
            return
1139
 
        i = 0
1140
 
        while True:
1141
 
            root = u'test%04d.tmp' % i
1142
 
            try:
1143
 
                os.mkdir(root)
1144
 
            except OSError, e:
1145
 
                if e.errno == errno.EEXIST:
1146
 
                    i += 1
1147
 
                    continue
1148
 
                else:
1149
 
                    raise
1150
 
            # successfully created
1151
 
            TestCaseInTempDir.TEST_ROOT = osutils.abspath(root)
1152
 
            break
1153
 
        # make a fake bzr directory there to prevent any tests propagating
1154
 
        # up onto the source directory's real branch
1155
 
        bzrdir.BzrDir.create_standalone_workingtree(TestCaseInTempDir.TEST_ROOT)
1156
 
 
1157
 
    def setUp(self):
1158
 
        super(TestCaseInTempDir, self).setUp()
1159
 
        self._make_test_root()
1160
 
        _currentdir = os.getcwdu()
 
1485
    def makeAndChdirToTestDir(self):
 
1486
        """See TestCaseWithMemoryTransport.makeAndChdirToTestDir().
 
1487
        
 
1488
        For TestCaseInTempDir we create a temporary directory based on the test
 
1489
        name and then create two subdirs - test and home under it.
 
1490
        """
1161
1491
        # shorten the name, to avoid test failures due to path length
1162
1492
        short_id = self.id().replace('bzrlib.tests.', '') \
1163
1493
                   .replace('__main__.', '')[-100:]
1180
1510
                os.mkdir(self.test_dir)
1181
1511
                os.chdir(self.test_dir)
1182
1512
                break
1183
 
        os.environ['HOME'] = self.test_home_dir
1184
 
        os.environ['APPDATA'] = self.test_home_dir
1185
 
        def _leaveDirectory():
1186
 
            os.chdir(_currentdir)
1187
 
        self.addCleanup(_leaveDirectory)
1188
 
        
1189
 
    def build_tree(self, shape, line_endings='native', transport=None):
 
1513
 
 
1514
    def build_tree(self, shape, line_endings='binary', transport=None):
1190
1515
        """Build a test tree according to a pattern.
1191
1516
 
1192
1517
        shape is a sequence of file specifications.  If the final
1217
1542
                elif line_endings == 'native':
1218
1543
                    end = os.linesep
1219
1544
                else:
1220
 
                    raise errors.BzrError('Invalid line ending request %r' % (line_endings,))
 
1545
                    raise errors.BzrError(
 
1546
                        'Invalid line ending request %r' % line_endings)
1221
1547
                content = "contents of %s%s" % (name.encode('utf-8'), end)
1222
 
                # Technically 'put()' is the right command. However, put
1223
 
                # uses an AtomicFile, which requires an extra rename into place
1224
 
                # As long as the files didn't exist in the past, append() will
1225
 
                # do the same thing as put()
1226
 
                # On jam's machine, make_kernel_like_tree is:
1227
 
                #   put:    4.5-7.5s (averaging 6s)
1228
 
                #   append: 2.9-4.5s
1229
 
                #   put_non_atomic: 2.9-4.5s
1230
1548
                transport.put_bytes_non_atomic(urlutils.escape(name), content)
1231
1549
 
1232
1550
    def build_tree_contents(self, shape):
1233
1551
        build_tree_contents(shape)
1234
1552
 
 
1553
    def assertFileEqual(self, content, path):
 
1554
        """Fail if path does not contain 'content'."""
 
1555
        self.failUnlessExists(path)
 
1556
        # TODO: jam 20060427 Shouldn't this be 'rb'?
 
1557
        self.assertEqualDiff(content, open(path, 'r').read())
 
1558
 
1235
1559
    def failUnlessExists(self, path):
1236
1560
        """Fail unless path, which may be abs or relative, exists."""
1237
 
        self.failUnless(osutils.lexists(path))
 
1561
        self.failUnless(osutils.lexists(path),path+" does not exist")
1238
1562
 
1239
1563
    def failIfExists(self, path):
1240
1564
        """Fail if path, which may be abs or relative, exists."""
1241
 
        self.failIf(osutils.lexists(path))
1242
 
        
1243
 
    def assertFileEqual(self, content, path):
1244
 
        """Fail if path does not contain 'content'."""
1245
 
        self.failUnless(osutils.lexists(path))
1246
 
        # TODO: jam 20060427 Shouldn't this be 'rb'?
1247
 
        self.assertEqualDiff(content, open(path, 'r').read())
 
1565
        self.failIf(osutils.lexists(path),path+" exists")
1248
1566
 
1249
1567
 
1250
1568
class TestCaseWithTransport(TestCaseInTempDir):
1261
1579
    readwrite one must both define get_url() as resolving to os.getcwd().
1262
1580
    """
1263
1581
 
1264
 
    def __init__(self, methodName='testMethod'):
1265
 
        super(TestCaseWithTransport, self).__init__(methodName)
1266
 
        self.__readonly_server = None
1267
 
        self.__server = None
1268
 
        self.transport_server = default_transport
1269
 
        self.transport_readonly_server = None
1270
 
 
1271
 
    def get_readonly_url(self, relpath=None):
1272
 
        """Get a URL for the readonly transport.
1273
 
 
1274
 
        This will either be backed by '.' or a decorator to the transport 
1275
 
        used by self.get_url()
1276
 
        relpath provides for clients to get a path relative to the base url.
1277
 
        These should only be downwards relative, not upwards.
1278
 
        """
1279
 
        base = self.get_readonly_server().get_url()
1280
 
        if relpath is not None:
1281
 
            if not base.endswith('/'):
1282
 
                base = base + '/'
1283
 
            base = base + relpath
1284
 
        return base
1285
 
 
1286
 
    def get_readonly_server(self):
1287
 
        """Get the server instance for the readonly transport
1288
 
 
1289
 
        This is useful for some tests with specific servers to do diagnostics.
1290
 
        """
1291
 
        if self.__readonly_server is None:
1292
 
            if self.transport_readonly_server is None:
1293
 
                # readonly decorator requested
1294
 
                # bring up the server
1295
 
                self.get_url()
1296
 
                self.__readonly_server = ReadonlyServer()
1297
 
                self.__readonly_server.setUp(self.__server)
1298
 
            else:
1299
 
                self.__readonly_server = self.transport_readonly_server()
1300
 
                self.__readonly_server.setUp()
1301
 
            self.addCleanup(self.__readonly_server.tearDown)
1302
 
        return self.__readonly_server
 
1582
    def create_transport_server(self):
 
1583
        """Create a transport server from class defined at init.
 
1584
 
 
1585
        This is mostly a hook for daughter classes.
 
1586
        """
 
1587
        return self.transport_server()
1303
1588
 
1304
1589
    def get_server(self):
1305
 
        """Get the read/write server instance.
 
1590
        """See TestCaseWithMemoryTransport.
1306
1591
 
1307
1592
        This is useful for some tests with specific servers that need
1308
1593
        diagnostics.
1309
1594
        """
1310
1595
        if self.__server is None:
1311
 
            self.__server = self.transport_server()
 
1596
            self.__server = self.create_transport_server()
1312
1597
            self.__server.setUp()
1313
1598
            self.addCleanup(self.__server.tearDown)
1314
1599
        return self.__server
1315
1600
 
1316
 
    def get_url(self, relpath=None):
1317
 
        """Get a URL (or maybe a path) for the readwrite transport.
1318
 
 
1319
 
        This will either be backed by '.' or to an equivalent non-file based
1320
 
        facility.
1321
 
        relpath provides for clients to get a path relative to the base url.
1322
 
        These should only be downwards relative, not upwards.
1323
 
        """
1324
 
        base = self.get_server().get_url()
1325
 
        if relpath is not None and relpath != '.':
1326
 
            if not base.endswith('/'):
1327
 
                base = base + '/'
1328
 
            # XXX: Really base should be a url; we did after all call
1329
 
            # get_url()!  But sometimes it's just a path (from
1330
 
            # LocalAbspathServer), and it'd be wrong to append urlescaped data
1331
 
            # to a non-escaped local path.
1332
 
            if base.startswith('./') or base.startswith('/'):
1333
 
                base += relpath
1334
 
            else:
1335
 
                base += urlutils.escape(relpath)
1336
 
        return base
1337
 
 
1338
 
    def get_transport(self):
1339
 
        """Return a writeable transport for the test scratch space"""
1340
 
        t = get_transport(self.get_url())
1341
 
        self.assertFalse(t.is_readonly())
1342
 
        return t
1343
 
 
1344
 
    def get_readonly_transport(self):
1345
 
        """Return a readonly transport for the test scratch space
1346
 
        
1347
 
        This can be used to test that operations which should only need
1348
 
        readonly access in fact do not try to write.
1349
 
        """
1350
 
        t = get_transport(self.get_readonly_url())
1351
 
        self.assertTrue(t.is_readonly())
1352
 
        return t
1353
 
 
1354
 
    def make_branch(self, relpath, format=None):
1355
 
        """Create a branch on the transport at relpath."""
1356
 
        repo = self.make_repository(relpath, format=format)
1357
 
        return repo.bzrdir.create_branch()
1358
 
 
1359
 
    def make_bzrdir(self, relpath, format=None):
1360
 
        try:
1361
 
            # might be a relative or absolute path
1362
 
            maybe_a_url = self.get_url(relpath)
1363
 
            segments = maybe_a_url.rsplit('/', 1)
1364
 
            t = get_transport(maybe_a_url)
1365
 
            if len(segments) > 1 and segments[-1] not in ('', '.'):
1366
 
                try:
1367
 
                    t.mkdir('.')
1368
 
                except errors.FileExists:
1369
 
                    pass
1370
 
            if format is None:
1371
 
                format = bzrlib.bzrdir.BzrDirFormat.get_default_format()
1372
 
            return format.initialize_on_transport(t)
1373
 
        except errors.UninitializableFormat:
1374
 
            raise TestSkipped("Format %s is not initializable." % format)
1375
 
 
1376
 
    def make_repository(self, relpath, shared=False, format=None):
1377
 
        """Create a repository on our default transport at relpath."""
1378
 
        made_control = self.make_bzrdir(relpath, format=format)
1379
 
        return made_control.create_repository(shared=shared)
1380
 
 
1381
 
    def make_branch_and_memory_tree(self, relpath):
1382
 
        """Create a branch on the default transport and a MemoryTree for it."""
1383
 
        b = self.make_branch(relpath)
1384
 
        return memorytree.MemoryTree.create_on_branch(b)
1385
 
 
1386
1601
    def make_branch_and_tree(self, relpath, format=None):
1387
1602
        """Create a branch on the transport and a tree locally.
1388
1603
 
1430
1645
            self.fail("path %s is not a directory; has mode %#o"
1431
1646
                      % (relpath, mode))
1432
1647
 
 
1648
    def setUp(self):
 
1649
        super(TestCaseWithTransport, self).setUp()
 
1650
        self.__server = None
 
1651
 
1433
1652
 
1434
1653
class ChrootedTestCase(TestCaseWithTransport):
1435
1654
    """A support class that provides readonly urls outside the local namespace.
1445
1664
 
1446
1665
    def setUp(self):
1447
1666
        super(ChrootedTestCase, self).setUp()
1448
 
        if not self.transport_server == bzrlib.transport.memory.MemoryServer:
1449
 
            self.transport_readonly_server = bzrlib.transport.http.HttpServer
 
1667
        if not self.transport_server == MemoryServer:
 
1668
            self.transport_readonly_server = HttpServer
1450
1669
 
1451
1670
 
1452
1671
def filter_suite_by_re(suite, pattern):
1458
1677
    return result
1459
1678
 
1460
1679
 
 
1680
def sort_suite_by_re(suite, pattern):
 
1681
    first = []
 
1682
    second = []
 
1683
    filter_re = re.compile(pattern)
 
1684
    for test in iter_suite_tests(suite):
 
1685
        if filter_re.search(test.id()):
 
1686
            first.append(test)
 
1687
        else:
 
1688
            second.append(test)
 
1689
    return TestUtil.TestSuite(first + second)
 
1690
 
 
1691
 
1461
1692
def run_suite(suite, name='test', verbose=False, pattern=".*",
1462
1693
              stop_on_failure=False, keep_output=False,
1463
 
              transport=None, lsprof_timed=None, bench_history=None):
1464
 
    TestCaseInTempDir._TEST_NAME = name
 
1694
              transport=None, lsprof_timed=None, bench_history=None,
 
1695
              matching_tests_first=None):
1465
1696
    TestCase._gather_lsprof_in_benchmarks = lsprof_timed
1466
1697
    if verbose:
1467
1698
        verbosity = 2
1468
 
        pb = None
1469
1699
    else:
1470
1700
        verbosity = 1
1471
 
        pb = progress.ProgressBar()
1472
1701
    runner = TextTestRunner(stream=sys.stdout,
1473
1702
                            descriptions=0,
1474
1703
                            verbosity=verbosity,
1475
1704
                            keep_output=keep_output,
1476
 
                            pb=pb,
1477
1705
                            bench_history=bench_history)
1478
1706
    runner.stop_on_failure=stop_on_failure
1479
1707
    if pattern != '.*':
1480
 
        suite = filter_suite_by_re(suite, pattern)
 
1708
        if matching_tests_first:
 
1709
            suite = sort_suite_by_re(suite, pattern)
 
1710
        else:
 
1711
            suite = filter_suite_by_re(suite, pattern)
1481
1712
    result = runner.run(suite)
1482
1713
    return result.wasSuccessful()
1483
1714
 
1487
1718
             transport=None,
1488
1719
             test_suite_factory=None,
1489
1720
             lsprof_timed=None,
1490
 
             bench_history=None):
 
1721
             bench_history=None,
 
1722
             matching_tests_first=None):
1491
1723
    """Run the whole test suite under the enhanced runner"""
1492
1724
    # XXX: Very ugly way to do this...
1493
1725
    # Disable warning about old formats because we don't want it to disturb
1509
1741
                     stop_on_failure=stop_on_failure, keep_output=keep_output,
1510
1742
                     transport=transport,
1511
1743
                     lsprof_timed=lsprof_timed,
1512
 
                     bench_history=bench_history)
 
1744
                     bench_history=bench_history,
 
1745
                     matching_tests_first=matching_tests_first)
1513
1746
    finally:
1514
1747
        default_transport = old_transport
1515
1748
 
1522
1755
    """
1523
1756
    testmod_names = [
1524
1757
                   'bzrlib.tests.test_ancestry',
 
1758
                   'bzrlib.tests.test_annotate',
1525
1759
                   'bzrlib.tests.test_api',
1526
1760
                   'bzrlib.tests.test_atomicfile',
1527
1761
                   'bzrlib.tests.test_bad_files',
1529
1763
                   'bzrlib.tests.test_bundle',
1530
1764
                   'bzrlib.tests.test_bzrdir',
1531
1765
                   'bzrlib.tests.test_cache_utf8',
1532
 
                   'bzrlib.tests.test_command',
 
1766
                   'bzrlib.tests.test_commands',
1533
1767
                   'bzrlib.tests.test_commit',
1534
1768
                   'bzrlib.tests.test_commit_merge',
1535
1769
                   'bzrlib.tests.test_config',
1536
1770
                   'bzrlib.tests.test_conflicts',
1537
1771
                   'bzrlib.tests.test_decorators',
 
1772
                   'bzrlib.tests.test_delta',
1538
1773
                   'bzrlib.tests.test_diff',
1539
1774
                   'bzrlib.tests.test_doc_generate',
1540
1775
                   'bzrlib.tests.test_errors',
1541
1776
                   'bzrlib.tests.test_escaped_store',
1542
1777
                   'bzrlib.tests.test_fetch',
1543
1778
                   'bzrlib.tests.test_ftp_transport',
 
1779
                   'bzrlib.tests.test_generate_docs',
 
1780
                   'bzrlib.tests.test_generate_ids',
 
1781
                   'bzrlib.tests.test_globbing',
1544
1782
                   'bzrlib.tests.test_gpg',
1545
1783
                   'bzrlib.tests.test_graph',
1546
1784
                   'bzrlib.tests.test_hashcache',
1551
1789
                   'bzrlib.tests.test_inv',
1552
1790
                   'bzrlib.tests.test_knit',
1553
1791
                   'bzrlib.tests.test_lazy_import',
 
1792
                   'bzrlib.tests.test_lazy_regex',
1554
1793
                   'bzrlib.tests.test_lockdir',
1555
1794
                   'bzrlib.tests.test_lockable_files',
1556
1795
                   'bzrlib.tests.test_log',
1563
1802
                   'bzrlib.tests.test_nonascii',
1564
1803
                   'bzrlib.tests.test_options',
1565
1804
                   'bzrlib.tests.test_osutils',
 
1805
                   'bzrlib.tests.test_osutils_encodings',
1566
1806
                   'bzrlib.tests.test_patch',
1567
1807
                   'bzrlib.tests.test_patches',
1568
1808
                   'bzrlib.tests.test_permissions',
1569
1809
                   'bzrlib.tests.test_plugins',
1570
1810
                   'bzrlib.tests.test_progress',
1571
1811
                   'bzrlib.tests.test_reconcile',
 
1812
                   'bzrlib.tests.test_registry',
1572
1813
                   'bzrlib.tests.test_repository',
1573
1814
                   'bzrlib.tests.test_revert',
1574
1815
                   'bzrlib.tests.test_revision',
1605
1846
                   'bzrlib.tests.test_weave',
1606
1847
                   'bzrlib.tests.test_whitebox',
1607
1848
                   'bzrlib.tests.test_workingtree',
 
1849
                   'bzrlib.tests.test_wsgi',
1608
1850
                   'bzrlib.tests.test_xml',
1609
1851
                   ]
1610
1852
    test_transport_implementations = [
1622
1864
    for m in MODULES_TO_TEST:
1623
1865
        suite.addTest(loader.loadTestsFromModule(m))
1624
1866
    for m in MODULES_TO_DOCTEST:
1625
 
        suite.addTest(doctest.DocTestSuite(m))
 
1867
        try:
 
1868
            suite.addTest(doctest.DocTestSuite(m))
 
1869
        except ValueError, e:
 
1870
            print '**failed to get doctest for: %s\n%s' %(m,e)
 
1871
            raise
1626
1872
    for name, plugin in bzrlib.plugin.all_plugins().items():
1627
1873
        if getattr(plugin, 'test_suite', None) is not None:
1628
1874
            suite.addTest(plugin.test_suite())
1633
1879
    """Adapt the modules in mods_list using adapter and add to suite."""
1634
1880
    for test in iter_suite_tests(loader.loadTestsFromModuleNames(mods_list)):
1635
1881
        suite.addTests(adapter.adapt(test))
 
1882
 
 
1883
 
 
1884
def clean_selftest_output(root=None, quiet=False):
 
1885
    """Remove all selftest output directories from root directory.
 
1886
 
 
1887
    :param  root:   root directory for clean
 
1888
                    (if ommitted or None then clean current directory).
 
1889
    :param  quiet:  suppress report about deleting directories
 
1890
    """
 
1891
    import re
 
1892
    import shutil
 
1893
 
 
1894
    re_dir = re.compile(r'''test\d\d\d\d\.tmp''')
 
1895
    if root is None:
 
1896
        root = u'.'
 
1897
    for i in os.listdir(root):
 
1898
        if os.path.isdir(i) and re_dir.match(i):
 
1899
            if not quiet:
 
1900
                print 'delete directory:', i
 
1901
            shutil.rmtree(i)