/brz/remove-bazaar

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

« back to all changes in this revision

Viewing changes to bzrlib/tests/__init__.py

[merge] bzr.dev 2255, resolve conflicts, update copyrights

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
74
78
from bzrlib.transport.memory import MemoryServer
75
79
from bzrlib.transport.readonly import ReadonlyServer
76
 
from bzrlib.trace import mutter
 
80
from bzrlib.trace import mutter, note
77
81
from bzrlib.tests import TestUtil
 
82
from bzrlib.tests.HttpServer import HttpServer
78
83
from bzrlib.tests.TestUtil import (
79
84
                          TestSuite,
80
85
                          TestLoader,
81
86
                          )
82
87
from bzrlib.tests.treeshape import build_tree_contents
83
 
import bzrlib.urlutils as urlutils
84
88
from bzrlib.workingtree import WorkingTree, WorkingTreeFormat2
85
89
 
86
 
default_transport = LocalRelpathServer
 
90
default_transport = LocalURLServer
87
91
 
88
92
MODULES_TO_TEST = []
89
93
MODULES_TO_DOCTEST = [
90
 
                      bzrlib.branch,
91
94
                      bzrlib.bundle.serializer,
92
 
                      bzrlib.commands,
93
95
                      bzrlib.errors,
94
96
                      bzrlib.export,
95
97
                      bzrlib.inventory,
97
99
                      bzrlib.lockdir,
98
100
                      bzrlib.merge3,
99
101
                      bzrlib.option,
100
 
                      bzrlib.osutils,
101
102
                      bzrlib.store,
102
 
                      bzrlib.transport,
103
103
                      ]
104
104
 
105
105
 
135
135
            ]
136
136
 
137
137
 
138
 
class _MyResult(unittest._TextTestResult):
139
 
    """Custom TestResult.
 
138
class ExtendedTestResult(unittest._TextTestResult):
 
139
    """Accepts, reports and accumulates the results of running tests.
140
140
 
141
 
    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.
142
144
    """
 
145
 
143
146
    stop_early = False
144
147
    
145
 
    def __init__(self, stream, descriptions, verbosity, pb=None,
146
 
                 bench_history=None):
 
148
    def __init__(self, stream, descriptions, verbosity,
 
149
                 bench_history=None,
 
150
                 num_tests=None,
 
151
                 ):
147
152
        """Construct new TestResult.
148
153
 
149
154
        :param bench_history: Optionally, a writable file object to accumulate
150
155
            benchmark results.
151
156
        """
152
157
        unittest._TextTestResult.__init__(self, stream, descriptions, verbosity)
153
 
        self.pb = pb
154
158
        if bench_history is not None:
155
159
            from bzrlib.version import _get_bzr_source_tree
156
160
            src_tree = _get_bzr_source_tree()
166
170
                revision_id = ''
167
171
            bench_history.write("--date %s %s\n" % (time.time(), revision_id))
168
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()
169
180
    
170
181
    def extractBenchmarkTime(self, testCase):
171
182
        """Add a benchmark time for the current test case."""
181
192
                self._formatTime(self._benchmarkTime),
182
193
                self._elapsedTestTimeString())
183
194
        else:
184
 
            return "      %s" % self._elapsedTestTimeString()
 
195
            return "           %s" % self._elapsedTestTimeString()
185
196
 
186
197
    def _formatTime(self, seconds):
187
198
        """Format seconds as milliseconds with leading spaces."""
188
 
        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)
189
202
 
190
 
    def _ellipsise_unimportant_words(self, a_string, final_width,
191
 
                                   keep_start=False):
192
 
        """Add ellipses (sp?) for overly long strings.
193
 
        
194
 
        :param keep_start: If true preserve the start of a_string rather
195
 
                           than the end of it.
196
 
        """
197
 
        if keep_start:
198
 
            if len(a_string) > final_width:
199
 
                result = a_string[:final_width-3] + '...'
200
 
            else:
201
 
                result = a_string
202
 
        else:
203
 
            if len(a_string) > final_width:
204
 
                result = '...' + a_string[3-final_width:]
205
 
            else:
206
 
                result = a_string
207
 
        return result.ljust(final_width)
 
203
    def _shortened_test_description(self, test):
 
204
        what = test.id()
 
205
        what = re.sub(r'^bzrlib\.(tests|benchmarks)\.', '', what)
 
206
        return what
208
207
 
209
208
    def startTest(self, test):
210
209
        unittest.TestResult.startTest(self, test)
211
 
        # In a short description, the important words are in
212
 
        # the beginning, but in an id, the important words are
213
 
        # at the end
214
 
        SHOW_DESCRIPTIONS = False
215
 
 
216
 
        if not self.showAll and self.dots and self.pb is not None:
217
 
            final_width = 13
218
 
        else:
219
 
            final_width = osutils.terminal_width()
220
 
            final_width = final_width - 15 - 8
221
 
        what = None
222
 
        if SHOW_DESCRIPTIONS:
223
 
            what = test.shortDescription()
224
 
            if what:
225
 
                what = self._ellipsise_unimportant_words(what, final_width, keep_start=True)
226
 
        if what is None:
227
 
            what = test.id()
228
 
            if what.startswith('bzrlib.tests.'):
229
 
                what = what[13:]
230
 
            what = self._ellipsise_unimportant_words(what, final_width)
231
 
        if self.showAll:
232
 
            self.stream.write(what)
233
 
        elif self.dots and self.pb is not None:
234
 
            self.pb.update(what, self.testsRun - 1, None)
235
 
        self.stream.flush()
 
210
        self.report_test_start(test)
236
211
        self._recordTestStartTime()
237
212
 
238
213
    def _recordTestStartTime(self):
249
224
        if setKeepLogfile is not None:
250
225
            setKeepLogfile()
251
226
        self.extractBenchmarkTime(test)
252
 
        if self.showAll:
253
 
            self.stream.writeln("ERROR %s" % self._testTimeString())
254
 
        elif self.dots and self.pb is None:
255
 
            self.stream.write('E')
256
 
        elif self.dots:
257
 
            self.pb.update(self._ellipsise_unimportant_words('ERROR', 13), self.testsRun, None)
258
 
            self.pb.note(self._ellipsise_unimportant_words(
259
 
                            test.id() + ': ERROR',
260
 
                            osutils.terminal_width()))
261
 
        self.stream.flush()
 
227
        self.report_error(test, err)
262
228
        if self.stop_early:
263
229
            self.stop()
264
230
 
270
236
        if setKeepLogfile is not None:
271
237
            setKeepLogfile()
272
238
        self.extractBenchmarkTime(test)
273
 
        if self.showAll:
274
 
            self.stream.writeln(" FAIL %s" % self._testTimeString())
275
 
        elif self.dots and self.pb is None:
276
 
            self.stream.write('F')
277
 
        elif self.dots:
278
 
            self.pb.update(self._ellipsise_unimportant_words('FAIL', 13), self.testsRun, None)
279
 
            self.pb.note(self._ellipsise_unimportant_words(
280
 
                            test.id() + ': FAIL',
281
 
                            osutils.terminal_width()))
282
 
        self.stream.flush()
 
239
        self.report_failure(test, err)
283
240
        if self.stop_early:
284
241
            self.stop()
285
242
 
290
247
                self._bench_history.write("%s %s\n" % (
291
248
                    self._formatTime(self._benchmarkTime),
292
249
                    test.id()))
293
 
        if self.showAll:
294
 
            self.stream.writeln('   OK %s' % self._testTimeString())
295
 
            for bench_called, stats in getattr(test, '_benchcalls', []):
296
 
                self.stream.writeln('LSProf output for %s(%s, %s)' % bench_called)
297
 
                stats.pprint(file=self.stream)
298
 
        elif self.dots and self.pb is None:
299
 
            self.stream.write('~')
300
 
        elif self.dots:
301
 
            self.pb.update(self._ellipsise_unimportant_words('OK', 13), self.testsRun, None)
302
 
        self.stream.flush()
 
250
        self.report_success(test)
303
251
        unittest.TestResult.addSuccess(self, test)
304
252
 
305
253
    def addSkipped(self, test, skip_excinfo):
306
254
        self.extractBenchmarkTime(test)
307
 
        if self.showAll:
308
 
            print >>self.stream, ' SKIP %s' % self._testTimeString()
309
 
            print >>self.stream, '     %s' % skip_excinfo[1]
310
 
        elif self.dots and self.pb is None:
311
 
            self.stream.write('S')
312
 
        elif self.dots:
313
 
            self.pb.update(self._ellipsise_unimportant_words('SKIP', 13), self.testsRun, None)
314
 
        self.stream.flush()
 
255
        self.report_skip(test, skip_excinfo)
315
256
        # seems best to treat this as success from point-of-view of unittest
316
257
        # -- it actually does nothing so it barely matters :)
317
258
        try:
337
278
            self.stream.writeln(self.separator2)
338
279
            self.stream.writeln("%s" % err)
339
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
 
340
408
 
341
409
class TextTestRunner(object):
342
410
    stop_on_failure = False
346
414
                 descriptions=0,
347
415
                 verbosity=1,
348
416
                 keep_output=False,
349
 
                 pb=None,
350
417
                 bench_history=None):
351
418
        self.stream = unittest._WritelnDecorator(stream)
352
419
        self.descriptions = descriptions
353
420
        self.verbosity = verbosity
354
421
        self.keep_output = keep_output
355
 
        self.pb = pb
356
422
        self._bench_history = bench_history
357
423
 
358
 
    def _makeResult(self):
359
 
        result = _MyResult(self.stream,
360
 
                           self.descriptions,
361
 
                           self.verbosity,
362
 
                           pb=self.pb,
363
 
                           bench_history=self._bench_history)
364
 
        result.stop_early = self.stop_on_failure
365
 
        return result
366
 
 
367
424
    def run(self, test):
368
425
        "Run the given test case or test suite."
369
 
        result = self._makeResult()
370
426
        startTime = time.time()
371
 
        if self.pb is not None:
372
 
            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()
373
439
        test.run(result)
374
440
        stopTime = time.time()
375
441
        timeTaken = stopTime - startTime
390
456
            self.stream.writeln(")")
391
457
        else:
392
458
            self.stream.writeln("OK")
393
 
        if self.pb is not None:
394
 
            self.pb.update('Cleaning up', 0, 1)
 
459
        result.report_cleaning_up()
395
460
        # This is still a little bogus, 
396
461
        # but only a little. Folk not using our testrunner will
397
462
        # have to delete their temp directories themselves.
412
477
                        sys.getfilesystemencoding())
413
478
                osutils.rmtree(test_root)
414
479
        else:
415
 
            if self.pb is not None:
416
 
                self.pb.note("Failed tests working directories are in '%s'\n",
417
 
                             test_root)
418
 
            else:
419
 
                self.stream.writeln(
420
 
                    "Failed tests working directories are in '%s'\n" %
421
 
                    test_root)
 
480
            note("Failed tests working directories are in '%s'\n", test_root)
422
481
        TestCaseWithMemoryTransport.TEST_ROOT = None
423
 
        if self.pb is not None:
424
 
            self.pb.clear()
 
482
        result.finished()
425
483
        return result
426
484
 
427
485
 
507
565
        unittest.TestCase.setUp(self)
508
566
        self._cleanEnvironment()
509
567
        bzrlib.trace.disable_default_logging()
 
568
        self._silenceUI()
510
569
        self._startLogFile()
511
570
        self._benchcalls = []
512
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)
513
587
 
514
588
    def _ndiff_strings(self, a, b):
515
589
        """Return ndiff between two strings containing lines.
575
649
            raise AssertionError("value(s) %r not present in container %r" % 
576
650
                                 (missing, superlist))
577
651
 
578
 
    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):
579
671
        if not (left is right):
580
 
            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))
581
683
 
582
684
    def assertTransportMode(self, transport, path, mode):
583
685
        """Fail if a path does not have mode mode.
607
709
            a_callable(*args, **kwargs).
608
710
        """
609
711
        local_warnings = []
610
 
        def capture_warnings(msg, cls, stacklevel=None):
 
712
        def capture_warnings(msg, cls=None, stacklevel=None):
611
713
            # we've hooked into a deprecation specific callpath,
612
714
            # only deprecations should getting sent via it.
613
715
            self.assertEqual(cls, DeprecationWarning)
711
813
            'BZREMAIL': None, # may still be present in the environment
712
814
            'EMAIL': None,
713
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,
714
830
        }
715
831
        self.__old_env = {}
716
832
        self.addCleanup(self._restoreEnvironment)
725
841
        for name, value in self.__old_env.iteritems():
726
842
            osutils.set_or_unset_env(name, value)
727
843
 
 
844
    def _restoreHooks(self):
 
845
        bzrlib.branch.Branch.hooks = self._preserved_hooks
 
846
 
728
847
    def tearDown(self):
729
848
        self._runCleanups()
730
849
        unittest.TestCase.tearDown(self)
841
960
            os.chdir(working_dir)
842
961
 
843
962
        try:
844
 
            result = self.apply_redirected(stdin, stdout, stderr,
845
 
                                           bzrlib.commands.run_bzr_catch_errors,
846
 
                                           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)
847
971
        finally:
848
972
            logger.removeHandler(handler)
849
973
            bzrlib.ui.ui_factory = old_ui_factory
931
1055
            The values must be strings. The change will only occur in the
932
1056
            child, so you don't need to fix the environment after running.
933
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.
934
1062
        """
935
1063
        env_changes = kwargs.get('env_changes', {})
936
1064
        working_dir = kwargs.get('working_dir', None)
 
1065
        allow_plugins = kwargs.get('allow_plugins', False)
937
1066
        process = self.start_bzr_subprocess(args, env_changes=env_changes,
938
 
                                            working_dir=working_dir)
 
1067
                                            working_dir=working_dir,
 
1068
                                            allow_plugins=allow_plugins)
939
1069
        # We distinguish between retcode=None and retcode not passed.
940
1070
        supplied_retcode = kwargs.get('retcode', 0)
941
1071
        return self.finish_bzr_subprocess(process, retcode=supplied_retcode,
944
1074
 
945
1075
    def start_bzr_subprocess(self, process_args, env_changes=None,
946
1076
                             skip_if_plan_to_signal=False,
947
 
                             working_dir=None):
 
1077
                             working_dir=None,
 
1078
                             allow_plugins=False):
948
1079
        """Start bzr in a subprocess for testing.
949
1080
 
950
1081
        This starts a new Python interpreter and runs bzr in there.
961
1092
            child, so you don't need to fix the environment after running.
962
1093
        :param skip_if_plan_to_signal: raise TestSkipped when true and os.kill
963
1094
            is not available.
 
1095
        :param allow_plugins: If False (default) pass --no-plugins to bzr.
964
1096
 
965
1097
        :returns: Popen object for the started process.
966
1098
        """
992
1124
            # so we will avoid using it on all platforms, just to
993
1125
            # make sure the code path is used, and we don't break on win32
994
1126
            cleanup_environment()
995
 
            process = Popen([sys.executable, bzr_path] + list(process_args),
996
 
                             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)
997
1132
        finally:
998
1133
            restore_environment()
999
1134
            if cwd is not None:
1001
1136
 
1002
1137
        return process
1003
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
 
1004
1147
    def get_bzr_path(self):
1005
1148
        """Return the path of the 'bzr' executable for this test suite."""
1006
1149
        bzr_path = os.path.dirname(os.path.dirname(bzrlib.__file__))+'/bzr'
1138
1281
        self.transport_server = default_transport
1139
1282
        self.transport_readonly_server = None
1140
1283
 
1141
 
    def failUnlessExists(self, path):
1142
 
        """Fail unless path, which may be abs or relative, exists."""
1143
 
        self.failUnless(osutils.lexists(path))
1144
 
 
1145
 
    def failIfExists(self, path):
1146
 
        """Fail if path, which may be abs or relative, exists."""
1147
 
        self.failIf(osutils.lexists(path))
1148
 
        
1149
1284
    def get_transport(self):
1150
1285
        """Return a writeable transport for the test scratch space"""
1151
1286
        t = get_transport(self.get_url())
1162
1297
        self.assertTrue(t.is_readonly())
1163
1298
        return t
1164
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
 
1165
1307
    def get_readonly_server(self):
1166
1308
        """Get the server instance for the readonly transport
1167
1309
 
1175
1317
                self.__readonly_server = ReadonlyServer()
1176
1318
                self.__readonly_server.setUp(self.__server)
1177
1319
            else:
1178
 
                self.__readonly_server = self.transport_readonly_server()
 
1320
                self.__readonly_server = self.create_transport_readonly_server()
1179
1321
                self.__readonly_server.setUp()
1180
1322
            self.addCleanup(self.__readonly_server.tearDown)
1181
1323
        return self.__readonly_server
1282
1424
                    t.mkdir('.')
1283
1425
                except errors.FileExists:
1284
1426
                    pass
1285
 
            if format is None:
 
1427
            if isinstance(format, basestring):
 
1428
                format = bzrdir.format_registry.make_bzrdir(format)
 
1429
            elif format is None:
1286
1430
                format = bzrlib.bzrdir.BzrDirFormat.get_default_format()
1287
1431
            return format.initialize_on_transport(t)
1288
1432
        except errors.UninitializableFormat:
1367
1511
                os.chdir(self.test_dir)
1368
1512
                break
1369
1513
 
1370
 
    def build_tree(self, shape, line_endings='native', transport=None):
 
1514
    def build_tree(self, shape, line_endings='binary', transport=None):
1371
1515
        """Build a test tree according to a pattern.
1372
1516
 
1373
1517
        shape is a sequence of file specifications.  If the final
1398
1542
                elif line_endings == 'native':
1399
1543
                    end = os.linesep
1400
1544
                else:
1401
 
                    raise errors.BzrError('Invalid line ending request %r' % (line_endings,))
 
1545
                    raise errors.BzrError(
 
1546
                        'Invalid line ending request %r' % line_endings)
1402
1547
                content = "contents of %s%s" % (name.encode('utf-8'), end)
1403
 
                # Technically 'put()' is the right command. However, put
1404
 
                # uses an AtomicFile, which requires an extra rename into place
1405
 
                # As long as the files didn't exist in the past, append() will
1406
 
                # do the same thing as put()
1407
 
                # On jam's machine, make_kernel_like_tree is:
1408
 
                #   put:    4.5-7.5s (averaging 6s)
1409
 
                #   append: 2.9-4.5s
1410
 
                #   put_non_atomic: 2.9-4.5s
1411
1548
                transport.put_bytes_non_atomic(urlutils.escape(name), content)
1412
1549
 
1413
1550
    def build_tree_contents(self, shape):
1415
1552
 
1416
1553
    def assertFileEqual(self, content, path):
1417
1554
        """Fail if path does not contain 'content'."""
1418
 
        self.failUnless(osutils.lexists(path))
 
1555
        self.failUnlessExists(path)
1419
1556
        # TODO: jam 20060427 Shouldn't this be 'rb'?
1420
1557
        self.assertEqualDiff(content, open(path, 'r').read())
1421
1558
 
 
1559
    def failUnlessExists(self, path):
 
1560
        """Fail unless path, which may be abs or relative, exists."""
 
1561
        self.failUnless(osutils.lexists(path),path+" does not exist")
 
1562
 
 
1563
    def failIfExists(self, path):
 
1564
        """Fail if path, which may be abs or relative, exists."""
 
1565
        self.failIf(osutils.lexists(path),path+" exists")
 
1566
 
1422
1567
 
1423
1568
class TestCaseWithTransport(TestCaseInTempDir):
1424
1569
    """A test case that provides get_url and get_readonly_url facilities.
1434
1579
    readwrite one must both define get_url() as resolving to os.getcwd().
1435
1580
    """
1436
1581
 
 
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()
 
1588
 
1437
1589
    def get_server(self):
1438
1590
        """See TestCaseWithMemoryTransport.
1439
1591
 
1441
1593
        diagnostics.
1442
1594
        """
1443
1595
        if self.__server is None:
1444
 
            self.__server = self.transport_server()
 
1596
            self.__server = self.create_transport_server()
1445
1597
            self.__server.setUp()
1446
1598
            self.addCleanup(self.__server.tearDown)
1447
1599
        return self.__server
1496
1648
    def setUp(self):
1497
1649
        super(TestCaseWithTransport, self).setUp()
1498
1650
        self.__server = None
1499
 
        self.transport_server = default_transport
1500
1651
 
1501
1652
 
1502
1653
class ChrootedTestCase(TestCaseWithTransport):
1513
1664
 
1514
1665
    def setUp(self):
1515
1666
        super(ChrootedTestCase, self).setUp()
1516
 
        if not self.transport_server == bzrlib.transport.memory.MemoryServer:
1517
 
            self.transport_readonly_server = bzrlib.transport.http.HttpServer
 
1667
        if not self.transport_server == MemoryServer:
 
1668
            self.transport_readonly_server = HttpServer
1518
1669
 
1519
1670
 
1520
1671
def filter_suite_by_re(suite, pattern):
1526
1677
    return result
1527
1678
 
1528
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
 
1529
1692
def run_suite(suite, name='test', verbose=False, pattern=".*",
1530
1693
              stop_on_failure=False, keep_output=False,
1531
 
              transport=None, lsprof_timed=None, bench_history=None):
 
1694
              transport=None, lsprof_timed=None, bench_history=None,
 
1695
              matching_tests_first=None):
1532
1696
    TestCase._gather_lsprof_in_benchmarks = lsprof_timed
1533
1697
    if verbose:
1534
1698
        verbosity = 2
1535
 
        pb = None
1536
1699
    else:
1537
1700
        verbosity = 1
1538
 
        pb = progress.ProgressBar()
1539
1701
    runner = TextTestRunner(stream=sys.stdout,
1540
1702
                            descriptions=0,
1541
1703
                            verbosity=verbosity,
1542
1704
                            keep_output=keep_output,
1543
 
                            pb=pb,
1544
1705
                            bench_history=bench_history)
1545
1706
    runner.stop_on_failure=stop_on_failure
1546
1707
    if pattern != '.*':
1547
 
        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)
1548
1712
    result = runner.run(suite)
1549
1713
    return result.wasSuccessful()
1550
1714
 
1554
1718
             transport=None,
1555
1719
             test_suite_factory=None,
1556
1720
             lsprof_timed=None,
1557
 
             bench_history=None):
 
1721
             bench_history=None,
 
1722
             matching_tests_first=None):
1558
1723
    """Run the whole test suite under the enhanced runner"""
1559
1724
    # XXX: Very ugly way to do this...
1560
1725
    # Disable warning about old formats because we don't want it to disturb
1576
1741
                     stop_on_failure=stop_on_failure, keep_output=keep_output,
1577
1742
                     transport=transport,
1578
1743
                     lsprof_timed=lsprof_timed,
1579
 
                     bench_history=bench_history)
 
1744
                     bench_history=bench_history,
 
1745
                     matching_tests_first=matching_tests_first)
1580
1746
    finally:
1581
1747
        default_transport = old_transport
1582
1748
 
1589
1755
    """
1590
1756
    testmod_names = [
1591
1757
                   'bzrlib.tests.test_ancestry',
 
1758
                   'bzrlib.tests.test_annotate',
1592
1759
                   'bzrlib.tests.test_api',
1593
1760
                   'bzrlib.tests.test_atomicfile',
1594
1761
                   'bzrlib.tests.test_bad_files',
1596
1763
                   'bzrlib.tests.test_bundle',
1597
1764
                   'bzrlib.tests.test_bzrdir',
1598
1765
                   'bzrlib.tests.test_cache_utf8',
1599
 
                   'bzrlib.tests.test_command',
 
1766
                   'bzrlib.tests.test_commands',
1600
1767
                   'bzrlib.tests.test_commit',
1601
1768
                   'bzrlib.tests.test_commit_merge',
1602
1769
                   'bzrlib.tests.test_config',
1603
1770
                   'bzrlib.tests.test_conflicts',
1604
1771
                   'bzrlib.tests.test_decorators',
 
1772
                   'bzrlib.tests.test_delta',
1605
1773
                   'bzrlib.tests.test_diff',
1606
1774
                   'bzrlib.tests.test_doc_generate',
1607
1775
                   'bzrlib.tests.test_errors',
1608
1776
                   'bzrlib.tests.test_escaped_store',
1609
1777
                   'bzrlib.tests.test_fetch',
1610
1778
                   'bzrlib.tests.test_ftp_transport',
 
1779
                   'bzrlib.tests.test_generate_docs',
 
1780
                   'bzrlib.tests.test_generate_ids',
 
1781
                   'bzrlib.tests.test_globbing',
1611
1782
                   'bzrlib.tests.test_gpg',
1612
1783
                   'bzrlib.tests.test_graph',
1613
1784
                   'bzrlib.tests.test_hashcache',
1618
1789
                   'bzrlib.tests.test_inv',
1619
1790
                   'bzrlib.tests.test_knit',
1620
1791
                   'bzrlib.tests.test_lazy_import',
 
1792
                   'bzrlib.tests.test_lazy_regex',
1621
1793
                   'bzrlib.tests.test_lockdir',
1622
1794
                   'bzrlib.tests.test_lockable_files',
1623
1795
                   'bzrlib.tests.test_log',
1630
1802
                   'bzrlib.tests.test_nonascii',
1631
1803
                   'bzrlib.tests.test_options',
1632
1804
                   'bzrlib.tests.test_osutils',
 
1805
                   'bzrlib.tests.test_osutils_encodings',
1633
1806
                   'bzrlib.tests.test_patch',
1634
1807
                   'bzrlib.tests.test_patches',
1635
1808
                   'bzrlib.tests.test_permissions',
1636
1809
                   'bzrlib.tests.test_plugins',
1637
1810
                   'bzrlib.tests.test_progress',
1638
1811
                   'bzrlib.tests.test_reconcile',
 
1812
                   'bzrlib.tests.test_registry',
1639
1813
                   'bzrlib.tests.test_repository',
1640
1814
                   'bzrlib.tests.test_revert',
1641
1815
                   'bzrlib.tests.test_revision',
1672
1846
                   'bzrlib.tests.test_weave',
1673
1847
                   'bzrlib.tests.test_whitebox',
1674
1848
                   'bzrlib.tests.test_workingtree',
 
1849
                   'bzrlib.tests.test_wsgi',
1675
1850
                   'bzrlib.tests.test_xml',
1676
1851
                   ]
1677
1852
    test_transport_implementations = [
1689
1864
    for m in MODULES_TO_TEST:
1690
1865
        suite.addTest(loader.loadTestsFromModule(m))
1691
1866
    for m in MODULES_TO_DOCTEST:
1692
 
        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
1693
1872
    for name, plugin in bzrlib.plugin.all_plugins().items():
1694
1873
        if getattr(plugin, 'test_suite', None) is not None:
1695
1874
            suite.addTest(plugin.test_suite())
1700
1879
    """Adapt the modules in mods_list using adapter and add to suite."""
1701
1880
    for test in iter_suite_tests(loader.loadTestsFromModuleNames(mods_list)):
1702
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)