~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/__init__.py

  • Committer: Naoki INADA
  • Date: 2009-10-29 10:01:19 UTC
  • mto: (4634.97.3 2.0)
  • mto: This revision was merged to the branch mainline in revision 4798.
  • Revision ID: inada-n@klab.jp-20091029100119-uckv9t7ej2qrghw3
import doc-ja rev90

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006, 2007 Canonical Ltd
 
1
# Copyright (C) 2005, 2006, 2007, 2008, 2009 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
12
12
#
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
 
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
17
 
18
18
# TODO: Perhaps there should be an API to find out if bzr running under the
33
33
import doctest
34
34
import errno
35
35
import logging
 
36
import math
36
37
import os
37
38
from pprint import pformat
38
39
import random
39
40
import re
40
41
import shlex
41
42
import stat
42
 
from subprocess import Popen, PIPE
 
43
from subprocess import Popen, PIPE, STDOUT
43
44
import sys
44
45
import tempfile
 
46
import threading
 
47
import time
45
48
import unittest
46
 
import time
47
49
import warnings
48
50
 
49
51
 
50
52
from bzrlib import (
 
53
    branchbuilder,
51
54
    bzrdir,
 
55
    chk_map,
52
56
    debug,
53
57
    errors,
 
58
    hooks,
 
59
    lock as _mod_lock,
54
60
    memorytree,
55
61
    osutils,
56
62
    progress,
57
63
    ui,
58
64
    urlutils,
 
65
    registry,
59
66
    workingtree,
60
67
    )
61
68
import bzrlib.branch
73
80
from bzrlib.merge import merge_inner
74
81
import bzrlib.merge3
75
82
import bzrlib.plugin
76
 
from bzrlib.revision import common_ancestor
 
83
from bzrlib.smart import client, request, server
77
84
import bzrlib.store
78
85
from bzrlib import symbol_versioning
79
86
from bzrlib.symbol_versioning import (
 
87
    DEPRECATED_PARAMETER,
 
88
    deprecated_function,
80
89
    deprecated_method,
81
 
    zero_ninetyone,
82
 
    zero_ninetytwo,
 
90
    deprecated_passed,
83
91
    )
84
92
import bzrlib.trace
85
93
from bzrlib.transport import get_transport
89
97
from bzrlib.transport.readonly import ReadonlyServer
90
98
from bzrlib.trace import mutter, note
91
99
from bzrlib.tests import TestUtil
92
 
from bzrlib.tests.HttpServer import HttpServer
 
100
from bzrlib.tests.http_server import HttpServer
93
101
from bzrlib.tests.TestUtil import (
94
102
                          TestSuite,
95
103
                          TestLoader,
96
104
                          )
97
105
from bzrlib.tests.treeshape import build_tree_contents
 
106
from bzrlib.ui import NullProgressView
 
107
from bzrlib.ui.text import TextUIFactory
 
108
import bzrlib.version_info_formats.format_custom
98
109
from bzrlib.workingtree import WorkingTree, WorkingTreeFormat2
99
110
 
100
111
# Mark this python module as being part of the implementation
104
115
 
105
116
default_transport = LocalURLServer
106
117
 
107
 
MODULES_TO_TEST = []
108
 
MODULES_TO_DOCTEST = [
109
 
        bzrlib.timestamp,
110
 
        bzrlib.errors,
111
 
        bzrlib.export,
112
 
        bzrlib.inventory,
113
 
        bzrlib.iterablefile,
114
 
        bzrlib.lockdir,
115
 
        bzrlib.merge3,
116
 
        bzrlib.option,
117
 
        bzrlib.store,
118
 
        # quoted to avoid module-loading circularity
119
 
        'bzrlib.tests',
120
 
        ]
121
 
 
122
 
 
123
 
def packages_to_test():
124
 
    """Return a list of packages to test.
125
 
 
126
 
    The packages are not globally imported so that import failures are
127
 
    triggered when running selftest, not when importing the command.
128
 
    """
129
 
    import bzrlib.doc
130
 
    import bzrlib.tests.blackbox
131
 
    import bzrlib.tests.branch_implementations
132
 
    import bzrlib.tests.bzrdir_implementations
133
 
    import bzrlib.tests.commands
134
 
    import bzrlib.tests.interrepository_implementations
135
 
    import bzrlib.tests.interversionedfile_implementations
136
 
    import bzrlib.tests.intertree_implementations
137
 
    import bzrlib.tests.inventory_implementations
138
 
    import bzrlib.tests.per_lock
139
 
    import bzrlib.tests.repository_implementations
140
 
    import bzrlib.tests.revisionstore_implementations
141
 
    import bzrlib.tests.tree_implementations
142
 
    import bzrlib.tests.workingtree_implementations
143
 
    return [
144
 
            bzrlib.doc,
145
 
            bzrlib.tests.blackbox,
146
 
            bzrlib.tests.branch_implementations,
147
 
            bzrlib.tests.bzrdir_implementations,
148
 
            bzrlib.tests.commands,
149
 
            bzrlib.tests.interrepository_implementations,
150
 
            bzrlib.tests.interversionedfile_implementations,
151
 
            bzrlib.tests.intertree_implementations,
152
 
            bzrlib.tests.inventory_implementations,
153
 
            bzrlib.tests.per_lock,
154
 
            bzrlib.tests.repository_implementations,
155
 
            bzrlib.tests.revisionstore_implementations,
156
 
            bzrlib.tests.tree_implementations,
157
 
            bzrlib.tests.workingtree_implementations,
158
 
            ]
 
118
# Subunit result codes, defined here to prevent a hard dependency on subunit.
 
119
SUBUNIT_SEEK_SET = 0
 
120
SUBUNIT_SEEK_CUR = 1
159
121
 
160
122
 
161
123
class ExtendedTestResult(unittest._TextTestResult):
175
137
    """
176
138
 
177
139
    stop_early = False
178
 
    
 
140
 
179
141
    def __init__(self, stream, descriptions, verbosity,
180
142
                 bench_history=None,
181
 
                 num_tests=None,
 
143
                 strict=False,
182
144
                 ):
183
145
        """Construct new TestResult.
184
146
 
202
164
            bench_history.write("--date %s %s\n" % (time.time(), revision_id))
203
165
        self._bench_history = bench_history
204
166
        self.ui = ui.ui_factory
205
 
        self.num_tests = num_tests
 
167
        self.num_tests = 0
206
168
        self.error_count = 0
207
169
        self.failure_count = 0
208
170
        self.known_failure_count = 0
211
173
        self.unsupported = {}
212
174
        self.count = 0
213
175
        self._overall_start_time = time.time()
214
 
    
 
176
        self._strict = strict
 
177
 
 
178
    def done(self):
 
179
        # nb: called stopTestRun in the version of this that Python merged
 
180
        # upstream, according to lifeless 20090803
 
181
        if self._strict:
 
182
            ok = self.wasStrictlySuccessful()
 
183
        else:
 
184
            ok = self.wasSuccessful()
 
185
        if ok:
 
186
            self.stream.write('tests passed\n')
 
187
        else:
 
188
            self.stream.write('tests failed\n')
 
189
        if TestCase._first_thread_leaker_id:
 
190
            self.stream.write(
 
191
                '%s is leaking threads among %d leaking tests.\n' % (
 
192
                TestCase._first_thread_leaker_id,
 
193
                TestCase._leaking_threads_tests))
 
194
 
215
195
    def _extractBenchmarkTime(self, testCase):
216
196
        """Add a benchmark time for the current test case."""
217
197
        return getattr(testCase, "_benchtime", None)
218
 
    
 
198
 
219
199
    def _elapsedTestTimeString(self):
220
200
        """Return a time string for the overall time the current test has taken."""
221
201
        return self._formatTime(time.time() - self._start_time)
223
203
    def _testTimeString(self, testCase):
224
204
        benchmark_time = self._extractBenchmarkTime(testCase)
225
205
        if benchmark_time is not None:
226
 
            return "%s/%s" % (
227
 
                self._formatTime(benchmark_time),
228
 
                self._elapsedTestTimeString())
 
206
            return self._formatTime(benchmark_time) + "*"
229
207
        else:
230
 
            return "           %s" % self._elapsedTestTimeString()
 
208
            return self._elapsedTestTimeString()
231
209
 
232
210
    def _formatTime(self, seconds):
233
211
        """Format seconds as milliseconds with leading spaces."""
242
220
 
243
221
    def startTest(self, test):
244
222
        unittest.TestResult.startTest(self, test)
 
223
        if self.count == 0:
 
224
            self.startTests()
245
225
        self.report_test_start(test)
246
226
        test.number = self.count
247
227
        self._recordTestStartTime()
248
228
 
 
229
    def startTests(self):
 
230
        import platform
 
231
        if getattr(sys, 'frozen', None) is None:
 
232
            bzr_path = osutils.realpath(sys.argv[0])
 
233
        else:
 
234
            bzr_path = sys.executable
 
235
        self.stream.write(
 
236
            'testing: %s\n' % (bzr_path,))
 
237
        self.stream.write(
 
238
            '   %s\n' % (
 
239
                    bzrlib.__path__[0],))
 
240
        self.stream.write(
 
241
            '   bzr-%s python-%s %s\n' % (
 
242
                    bzrlib.version_string,
 
243
                    bzrlib._format_version_tuple(sys.version_info),
 
244
                    platform.platform(aliased=1),
 
245
                    ))
 
246
        self.stream.write('\n')
 
247
 
249
248
    def _recordTestStartTime(self):
250
249
        """Record that a test has started."""
251
250
        self._start_time = time.time()
264
263
        fails with an unexpected error.
265
264
        """
266
265
        self._testConcluded(test)
267
 
        if isinstance(err[1], TestSkipped):
268
 
            return self._addSkipped(test, err)
 
266
        if isinstance(err[1], TestNotApplicable):
 
267
            return self._addNotApplicable(test, err)
269
268
        elif isinstance(err[1], UnavailableFeature):
270
269
            return self.addNotSupported(test, err[1].args[0])
271
270
        else:
274
273
            self.report_error(test, err)
275
274
            if self.stop_early:
276
275
                self.stop()
 
276
            self._cleanupLogFile(test)
277
277
 
278
278
    def addFailure(self, test, err):
279
279
        """Tell result that test failed.
290
290
            self.report_failure(test, err)
291
291
            if self.stop_early:
292
292
                self.stop()
 
293
            self._cleanupLogFile(test)
293
294
 
294
295
    def addSuccess(self, test):
295
296
        """Tell result that test completed successfully.
304
305
                    self._formatTime(benchmark_time),
305
306
                    test.id()))
306
307
        self.report_success(test)
 
308
        self._cleanupLogFile(test)
307
309
        unittest.TestResult.addSuccess(self, test)
 
310
        test._log_contents = ''
308
311
 
309
312
    def _testConcluded(self, test):
310
313
        """Common code when a test has finished.
311
314
 
312
315
        Called regardless of whether it succeded, failed, etc.
313
316
        """
314
 
        self._cleanupLogFile(test)
 
317
        pass
315
318
 
316
319
    def _addKnownFailure(self, test, err):
317
320
        self.known_failure_count += 1
321
324
        """The test will not be run because of a missing feature.
322
325
        """
323
326
        # this can be called in two different ways: it may be that the
324
 
        # test started running, and then raised (through addError) 
 
327
        # test started running, and then raised (through addError)
325
328
        # UnavailableFeature.  Alternatively this method can be called
326
329
        # while probing for features before running the tests; in that
327
330
        # case we will see startTest and stopTest, but the test will never
330
333
        self.unsupported[str(feature)] += 1
331
334
        self.report_unsupported(test, feature)
332
335
 
333
 
    def _addSkipped(self, test, skip_excinfo):
 
336
    def addSkip(self, test, reason):
 
337
        """A test has not run for 'reason'."""
 
338
        self.skip_count += 1
 
339
        self.report_skip(test, reason)
 
340
 
 
341
    def _addNotApplicable(self, test, skip_excinfo):
334
342
        if isinstance(skip_excinfo[1], TestNotApplicable):
335
343
            self.not_applicable_count += 1
336
344
            self.report_not_applicable(test, skip_excinfo)
337
 
        else:
338
 
            self.skip_count += 1
339
 
            self.report_skip(test, skip_excinfo)
340
345
        try:
341
346
            test.tearDown()
342
347
        except KeyboardInterrupt:
343
348
            raise
344
349
        except:
345
 
            self.addError(test, test._exc_info())
 
350
            self.addError(test, test.exc_info())
346
351
        else:
347
352
            # seems best to treat this as success from point-of-view of unittest
348
353
            # -- it actually does nothing so it barely matters :)
349
354
            unittest.TestResult.addSuccess(self, test)
 
355
            test._log_contents = ''
350
356
 
351
357
    def printErrorList(self, flavour, errors):
352
358
        for test, err in errors:
354
360
            self.stream.write("%s: " % flavour)
355
361
            self.stream.writeln(self.getDescription(test))
356
362
            if getattr(test, '_get_log', None) is not None:
357
 
                self.stream.write('\n')
358
 
                self.stream.write(
359
 
                        ('vvvv[log from %s]' % test.id()).ljust(78,'-'))
360
 
                self.stream.write('\n')
361
 
                self.stream.write(test._get_log())
362
 
                self.stream.write('\n')
363
 
                self.stream.write(
364
 
                        ('^^^^[log from %s]' % test.id()).ljust(78,'-'))
365
 
                self.stream.write('\n')
 
363
                log_contents = test._get_log()
 
364
                if log_contents:
 
365
                    self.stream.write('\n')
 
366
                    self.stream.write(
 
367
                            ('vvvv[log from %s]' % test.id()).ljust(78,'-'))
 
368
                    self.stream.write('\n')
 
369
                    self.stream.write(log_contents)
 
370
                    self.stream.write('\n')
 
371
                    self.stream.write(
 
372
                            ('^^^^[log from %s]' % test.id()).ljust(78,'-'))
 
373
                    self.stream.write('\n')
366
374
            self.stream.writeln(self.separator2)
367
375
            self.stream.writeln("%s" % err)
368
376
 
 
377
    def progress(self, offset, whence):
 
378
        """The test is adjusting the count of tests to run."""
 
379
        if whence == SUBUNIT_SEEK_SET:
 
380
            self.num_tests = offset
 
381
        elif whence == SUBUNIT_SEEK_CUR:
 
382
            self.num_tests += offset
 
383
        else:
 
384
            raise errors.BzrError("Unknown whence %r" % whence)
 
385
 
369
386
    def finished(self):
370
387
        pass
371
388
 
386
403
 
387
404
    def __init__(self, stream, descriptions, verbosity,
388
405
                 bench_history=None,
389
 
                 num_tests=None,
390
406
                 pb=None,
 
407
                 strict=None,
391
408
                 ):
392
409
        ExtendedTestResult.__init__(self, stream, descriptions, verbosity,
393
 
            bench_history, num_tests)
394
 
        if pb is None:
395
 
            self.pb = self.ui.nested_progress_bar()
396
 
            self._supplied_pb = False
397
 
        else:
398
 
            self.pb = pb
399
 
            self._supplied_pb = True
 
410
            bench_history, strict)
 
411
        # We no longer pass them around, but just rely on the UIFactory stack
 
412
        # for state
 
413
        if pb is not None:
 
414
            warnings.warn("Passing pb to TextTestResult is deprecated")
 
415
        self.pb = self.ui.nested_progress_bar()
400
416
        self.pb.show_pct = False
401
417
        self.pb.show_spinner = False
402
418
        self.pb.show_eta = False,
403
419
        self.pb.show_count = False
404
420
        self.pb.show_bar = False
 
421
        self.pb.update_latency = 0
 
422
        self.pb.show_transport_activity = False
 
423
 
 
424
    def done(self):
 
425
        # called when the tests that are going to run have run
 
426
        self.pb.clear()
 
427
        super(TextTestResult, self).done()
 
428
 
 
429
    def finished(self):
 
430
        self.pb.finished()
405
431
 
406
432
    def report_starting(self):
407
 
        self.pb.update('[test 0/%d] starting...' % (self.num_tests))
 
433
        self.pb.update('[test 0/%d] Starting' % (self.num_tests))
 
434
 
 
435
    def printErrors(self):
 
436
        # clear the pb to make room for the error listing
 
437
        self.pb.clear()
 
438
        super(TextTestResult, self).printErrors()
408
439
 
409
440
    def _progress_prefix_text(self):
410
 
        a = '[%d' % self.count
411
 
        if self.num_tests is not None:
 
441
        # the longer this text, the less space we have to show the test
 
442
        # name...
 
443
        a = '[%d' % self.count              # total that have been run
 
444
        # tests skipped as known not to be relevant are not important enough
 
445
        # to show here
 
446
        ## if self.skip_count:
 
447
        ##     a += ', %d skip' % self.skip_count
 
448
        ## if self.known_failure_count:
 
449
        ##     a += '+%dX' % self.known_failure_count
 
450
        if self.num_tests:
412
451
            a +='/%d' % self.num_tests
413
 
        a += ' in %ds' % (time.time() - self._overall_start_time)
 
452
        a += ' in '
 
453
        runtime = time.time() - self._overall_start_time
 
454
        if runtime >= 60:
 
455
            a += '%dm%ds' % (runtime / 60, runtime % 60)
 
456
        else:
 
457
            a += '%ds' % runtime
414
458
        if self.error_count:
415
 
            a += ', %d errors' % self.error_count
 
459
            a += ', %d err' % self.error_count
416
460
        if self.failure_count:
417
 
            a += ', %d failed' % self.failure_count
418
 
        if self.known_failure_count:
419
 
            a += ', %d known failures' % self.known_failure_count
420
 
        if self.skip_count:
421
 
            a += ', %d skipped' % self.skip_count
 
461
            a += ', %d fail' % self.failure_count
422
462
        if self.unsupported:
423
 
            a += ', %d missing features' % len(self.unsupported)
 
463
            a += ', %d missing' % len(self.unsupported)
424
464
        a += ']'
425
465
        return a
426
466
 
428
468
        self.count += 1
429
469
        self.pb.update(
430
470
                self._progress_prefix_text()
431
 
                + ' ' 
 
471
                + ' '
432
472
                + self._shortened_test_description(test))
433
473
 
434
474
    def _test_description(self, test):
435
475
        return self._shortened_test_description(test)
436
476
 
437
477
    def report_error(self, test, err):
438
 
        self.pb.note('ERROR: %s\n    %s\n', 
 
478
        self.pb.note('ERROR: %s\n    %s\n',
439
479
            self._test_description(test),
440
480
            err[1],
441
481
            )
442
482
 
443
483
    def report_failure(self, test, err):
444
 
        self.pb.note('FAIL: %s\n    %s\n', 
 
484
        self.pb.note('FAIL: %s\n    %s\n',
445
485
            self._test_description(test),
446
486
            err[1],
447
487
            )
450
490
        self.pb.note('XFAIL: %s\n%s\n',
451
491
            self._test_description(test), err[1])
452
492
 
453
 
    def report_skip(self, test, skip_excinfo):
 
493
    def report_skip(self, test, reason):
454
494
        pass
455
495
 
456
496
    def report_not_applicable(self, test, skip_excinfo):
458
498
 
459
499
    def report_unsupported(self, test, feature):
460
500
        """test cannot be run because feature is missing."""
461
 
                  
 
501
 
462
502
    def report_cleaning_up(self):
463
 
        self.pb.update('cleaning up...')
464
 
 
465
 
    def finished(self):
466
 
        if not self._supplied_pb:
467
 
            self.pb.finished()
 
503
        self.pb.update('Cleaning up')
468
504
 
469
505
 
470
506
class VerboseTestResult(ExtendedTestResult):
484
520
    def report_test_start(self, test):
485
521
        self.count += 1
486
522
        name = self._shortened_test_description(test)
487
 
        # width needs space for 6 char status, plus 1 for slash, plus 2 10-char
488
 
        # numbers, plus a trailing blank
 
523
        # width needs space for 6 char status, plus 1 for slash, plus an
 
524
        # 11-char time string, plus a trailing blank
489
525
        # when NUMBERED_DIRS: plus 5 chars on test number, plus 1 char on space
490
526
        self.stream.write(self._ellipsize_to_right(name,
491
 
                          osutils.terminal_width()-30))
 
527
                          osutils.terminal_width()-18))
492
528
        self.stream.flush()
493
529
 
494
530
    def _error_summary(self, err):
519
555
        # used to show the output in PQM.
520
556
        self.stream.flush()
521
557
 
522
 
    def report_skip(self, test, skip_excinfo):
 
558
    def report_skip(self, test, reason):
523
559
        self.stream.writeln(' SKIP %s\n%s'
524
 
                % (self._testTimeString(test),
525
 
                   self._error_summary(skip_excinfo)))
 
560
                % (self._testTimeString(test), reason))
526
561
 
527
562
    def report_not_applicable(self, test, skip_excinfo):
528
563
        self.stream.writeln('  N/A %s\n%s'
543
578
                 descriptions=0,
544
579
                 verbosity=1,
545
580
                 bench_history=None,
546
 
                 list_only=False
 
581
                 list_only=False,
 
582
                 strict=False,
547
583
                 ):
548
584
        self.stream = unittest._WritelnDecorator(stream)
549
585
        self.descriptions = descriptions
550
586
        self.verbosity = verbosity
551
587
        self._bench_history = bench_history
552
588
        self.list_only = list_only
 
589
        self._strict = strict
553
590
 
554
591
    def run(self, test):
555
592
        "Run the given test case or test suite."
562
599
                              self.descriptions,
563
600
                              self.verbosity,
564
601
                              bench_history=self._bench_history,
565
 
                              num_tests=test.countTestCases(),
 
602
                              strict=self._strict,
566
603
                              )
567
604
        result.stop_early = self.stop_on_failure
568
605
        result.report_starting()
573
610
            for t in iter_suite_tests(test):
574
611
                self.stream.writeln("%s" % (t.id()))
575
612
                run += 1
576
 
            actionTaken = "Listed"
577
 
        else: 
578
 
            test.run(result)
 
613
            return None
 
614
        else:
 
615
            try:
 
616
                import testtools
 
617
            except ImportError:
 
618
                test.run(result)
 
619
            else:
 
620
                if isinstance(test, testtools.ConcurrentTestSuite):
 
621
                    # We need to catch bzr specific behaviors
 
622
                    test.run(BZRTransformingResult(result))
 
623
                else:
 
624
                    test.run(result)
579
625
            run = result.testsRun
580
626
            actionTaken = "Ran"
581
627
        stopTime = time.time()
618
664
 
619
665
def iter_suite_tests(suite):
620
666
    """Return all tests in a suite, recursing through nested suites"""
621
 
    for item in suite._tests:
622
 
        if isinstance(item, unittest.TestCase):
623
 
            yield item
624
 
        elif isinstance(item, unittest.TestSuite):
 
667
    if isinstance(suite, unittest.TestCase):
 
668
        yield suite
 
669
    elif isinstance(suite, unittest.TestSuite):
 
670
        for item in suite:
625
671
            for r in iter_suite_tests(item):
626
672
                yield r
627
 
        else:
628
 
            raise Exception('unknown object %r inside test suite %r'
629
 
                            % (item, suite))
 
673
    else:
 
674
        raise Exception('unknown type %r for object %r'
 
675
                        % (type(suite), suite))
630
676
 
631
677
 
632
678
class TestSkipped(Exception):
636
682
class TestNotApplicable(TestSkipped):
637
683
    """A test is not applicable to the situation where it was run.
638
684
 
639
 
    This is only normally raised by parameterized tests, if they find that 
640
 
    the instance they're constructed upon does not support one aspect 
 
685
    This is only normally raised by parameterized tests, if they find that
 
686
    the instance they're constructed upon does not support one aspect
641
687
    of its interface.
642
688
    """
643
689
 
665
711
 
666
712
class StringIOWrapper(object):
667
713
    """A wrapper around cStringIO which just adds an encoding attribute.
668
 
    
 
714
 
669
715
    Internally we can check sys.stdout to see what the output encoding
670
716
    should be. However, cStringIO has no encoding attribute that we can
671
717
    set. So we wrap it instead.
689
735
            return setattr(self._cstring, name, val)
690
736
 
691
737
 
692
 
class TestUIFactory(ui.CLIUIFactory):
 
738
class TestUIFactory(TextUIFactory):
693
739
    """A UI Factory for testing.
694
740
 
695
741
    Hide the progress bar but emit note()s.
696
742
    Redirect stdin.
697
743
    Allows get_password to be tested without real tty attached.
 
744
 
 
745
    See also CannedInputUIFactory which lets you provide programmatic input in
 
746
    a structured way.
698
747
    """
 
748
    # TODO: Capture progress events at the model level and allow them to be
 
749
    # observed by tests that care.
 
750
    #
 
751
    # XXX: Should probably unify more with CannedInputUIFactory or a
 
752
    # particular configuration of TextUIFactory, or otherwise have a clearer
 
753
    # idea of how they're supposed to be different.
 
754
    # See https://bugs.edge.launchpad.net/bzr/+bug/408213
699
755
 
700
 
    def __init__(self,
701
 
                 stdout=None,
702
 
                 stderr=None,
703
 
                 stdin=None):
704
 
        super(TestUIFactory, self).__init__()
 
756
    def __init__(self, stdout=None, stderr=None, stdin=None):
705
757
        if stdin is not None:
706
758
            # We use a StringIOWrapper to be able to test various
707
759
            # encodings, but the user is still responsible to
708
760
            # encode the string and to set the encoding attribute
709
761
            # of StringIOWrapper.
710
 
            self.stdin = StringIOWrapper(stdin)
711
 
        if stdout is None:
712
 
            self.stdout = sys.stdout
713
 
        else:
714
 
            self.stdout = stdout
715
 
        if stderr is None:
716
 
            self.stderr = sys.stderr
717
 
        else:
718
 
            self.stderr = stderr
719
 
 
720
 
    def clear(self):
721
 
        """See progress.ProgressBar.clear()."""
722
 
 
723
 
    def clear_term(self):
724
 
        """See progress.ProgressBar.clear_term()."""
725
 
 
726
 
    def clear_term(self):
727
 
        """See progress.ProgressBar.clear_term()."""
728
 
 
729
 
    def finished(self):
730
 
        """See progress.ProgressBar.finished()."""
731
 
 
732
 
    def note(self, fmt_string, *args, **kwargs):
733
 
        """See progress.ProgressBar.note()."""
734
 
        self.stdout.write((fmt_string + "\n") % args)
735
 
 
736
 
    def progress_bar(self):
737
 
        return self
738
 
 
739
 
    def nested_progress_bar(self):
740
 
        return self
741
 
 
742
 
    def update(self, message, count=None, total=None):
743
 
        """See progress.ProgressBar.update()."""
744
 
 
745
 
    def get_non_echoed_password(self, prompt):
 
762
            stdin = StringIOWrapper(stdin)
 
763
        super(TestUIFactory, self).__init__(stdin, stdout, stderr)
 
764
 
 
765
    def get_non_echoed_password(self):
746
766
        """Get password from stdin without trying to handle the echo mode"""
747
 
        if prompt:
748
 
            self.stdout.write(prompt.encode(self.stdout.encoding, 'replace'))
749
767
        password = self.stdin.readline()
750
768
        if not password:
751
769
            raise EOFError
753
771
            password = password[:-1]
754
772
        return password
755
773
 
 
774
    def make_progress_view(self):
 
775
        return NullProgressView()
 
776
 
756
777
 
757
778
class TestCase(unittest.TestCase):
758
779
    """Base class for bzr unit tests.
759
 
    
760
 
    Tests that need access to disk resources should subclass 
 
780
 
 
781
    Tests that need access to disk resources should subclass
761
782
    TestCaseInTempDir not TestCase.
762
783
 
763
784
    Error and debug log messages are redirected from their usual
765
786
    retrieved by _get_log().  We use a real OS file, not an in-memory object,
766
787
    so that it can also capture file IO.  When the test completes this file
767
788
    is read into memory and removed from disk.
768
 
       
 
789
 
769
790
    There are also convenience functions to invoke bzr's command-line
770
791
    routine, and to build and check bzr trees.
771
 
   
 
792
 
772
793
    In addition to the usual method of overriding tearDown(), this class also
773
794
    allows subclasses to register functions into the _cleanups list, which is
774
795
    run in order as the object is torn down.  It's less likely this will be
775
796
    accidentally overlooked.
776
797
    """
777
798
 
 
799
    _active_threads = None
 
800
    _leaking_threads_tests = 0
 
801
    _first_thread_leaker_id = None
778
802
    _log_file_name = None
779
803
    _log_contents = ''
780
804
    _keep_log_file = False
781
805
    # record lsprof data when performing benchmark calls.
782
806
    _gather_lsprof_in_benchmarks = False
 
807
    attrs_to_keep = ('id', '_testMethodName', '_testMethodDoc',
 
808
                     '_log_contents', '_log_file_name', '_benchtime',
 
809
                     '_TestCase__testMethodName', '_TestCase__testMethodDoc',)
783
810
 
784
811
    def __init__(self, methodName='testMethod'):
785
812
        super(TestCase, self).__init__(methodName)
786
813
        self._cleanups = []
 
814
        self._bzr_test_setUp_run = False
 
815
        self._bzr_test_tearDown_run = False
787
816
 
788
817
    def setUp(self):
789
818
        unittest.TestCase.setUp(self)
 
819
        self._bzr_test_setUp_run = True
790
820
        self._cleanEnvironment()
791
 
        bzrlib.trace.disable_default_logging()
792
821
        self._silenceUI()
793
822
        self._startLogFile()
794
823
        self._benchcalls = []
795
824
        self._benchtime = None
796
825
        self._clear_hooks()
 
826
        self._track_locks()
797
827
        self._clear_debug_flags()
 
828
        TestCase._active_threads = threading.activeCount()
 
829
        self.addCleanup(self._check_leaked_threads)
 
830
 
 
831
    def debug(self):
 
832
        # debug a frame up.
 
833
        import pdb
 
834
        pdb.Pdb().set_trace(sys._getframe().f_back)
 
835
 
 
836
    def _check_leaked_threads(self):
 
837
        active = threading.activeCount()
 
838
        leaked_threads = active - TestCase._active_threads
 
839
        TestCase._active_threads = active
 
840
        if leaked_threads:
 
841
            TestCase._leaking_threads_tests += 1
 
842
            if TestCase._first_thread_leaker_id is None:
 
843
                TestCase._first_thread_leaker_id = self.id()
798
844
 
799
845
    def _clear_debug_flags(self):
800
846
        """Prevent externally set debug flags affecting tests.
801
 
        
 
847
 
802
848
        Tests that want to use debug flags can just set them in the
803
849
        debug_flags set during setup/teardown.
804
850
        """
805
851
        self._preserved_debug_flags = set(debug.debug_flags)
806
 
        debug.debug_flags.clear()
 
852
        if 'allow_debug' not in selftest_debug_flags:
 
853
            debug.debug_flags.clear()
 
854
        if 'disable_lock_checks' not in selftest_debug_flags:
 
855
            debug.debug_flags.add('strict_locks')
807
856
        self.addCleanup(self._restore_debug_flags)
808
857
 
809
858
    def _clear_hooks(self):
810
859
        # prevent hooks affecting tests
811
 
        import bzrlib.branch
812
 
        import bzrlib.smart.server
813
 
        self._preserved_hooks = {
814
 
            bzrlib.branch.Branch: bzrlib.branch.Branch.hooks,
815
 
            bzrlib.smart.server.SmartTCPServer: bzrlib.smart.server.SmartTCPServer.hooks,
816
 
            }
 
860
        self._preserved_hooks = {}
 
861
        for key, factory in hooks.known_hooks.items():
 
862
            parent, name = hooks.known_hooks_key_to_parent_and_attribute(key)
 
863
            current_hooks = hooks.known_hooks_key_to_object(key)
 
864
            self._preserved_hooks[parent] = (name, current_hooks)
817
865
        self.addCleanup(self._restoreHooks)
818
 
        # reset all hooks to an empty instance of the appropriate type
819
 
        bzrlib.branch.Branch.hooks = bzrlib.branch.BranchHooks()
820
 
        bzrlib.smart.server.SmartTCPServer.hooks = bzrlib.smart.server.SmartServerHooks()
 
866
        for key, factory in hooks.known_hooks.items():
 
867
            parent, name = hooks.known_hooks_key_to_parent_and_attribute(key)
 
868
            setattr(parent, name, factory())
 
869
        # this hook should always be installed
 
870
        request._install_hook()
821
871
 
822
872
    def _silenceUI(self):
823
873
        """Turn off UI for duration of test"""
828
878
        ui.ui_factory = ui.SilentUIFactory()
829
879
        self.addCleanup(_restore)
830
880
 
 
881
    def _check_locks(self):
 
882
        """Check that all lock take/release actions have been paired."""
 
883
        # We always check for mismatched locks. If a mismatch is found, we
 
884
        # fail unless -Edisable_lock_checks is supplied to selftest, in which
 
885
        # case we just print a warning.
 
886
        # unhook:
 
887
        acquired_locks = [lock for action, lock in self._lock_actions
 
888
                          if action == 'acquired']
 
889
        released_locks = [lock for action, lock in self._lock_actions
 
890
                          if action == 'released']
 
891
        broken_locks = [lock for action, lock in self._lock_actions
 
892
                        if action == 'broken']
 
893
        # trivially, given the tests for lock acquistion and release, if we
 
894
        # have as many in each list, it should be ok. Some lock tests also
 
895
        # break some locks on purpose and should be taken into account by
 
896
        # considering that breaking a lock is just a dirty way of releasing it.
 
897
        if len(acquired_locks) != (len(released_locks) + len(broken_locks)):
 
898
            message = ('Different number of acquired and '
 
899
                       'released or broken locks. (%s, %s + %s)' %
 
900
                       (acquired_locks, released_locks, broken_locks))
 
901
            if not self._lock_check_thorough:
 
902
                # Rather than fail, just warn
 
903
                print "Broken test %s: %s" % (self, message)
 
904
                return
 
905
            self.fail(message)
 
906
 
 
907
    def _track_locks(self):
 
908
        """Track lock activity during tests."""
 
909
        self._lock_actions = []
 
910
        if 'disable_lock_checks' in selftest_debug_flags:
 
911
            self._lock_check_thorough = False
 
912
        else:
 
913
            self._lock_check_thorough = True
 
914
            
 
915
        self.addCleanup(self._check_locks)
 
916
        _mod_lock.Lock.hooks.install_named_hook('lock_acquired',
 
917
                                                self._lock_acquired, None)
 
918
        _mod_lock.Lock.hooks.install_named_hook('lock_released',
 
919
                                                self._lock_released, None)
 
920
        _mod_lock.Lock.hooks.install_named_hook('lock_broken',
 
921
                                                self._lock_broken, None)
 
922
 
 
923
    def _lock_acquired(self, result):
 
924
        self._lock_actions.append(('acquired', result))
 
925
 
 
926
    def _lock_released(self, result):
 
927
        self._lock_actions.append(('released', result))
 
928
 
 
929
    def _lock_broken(self, result):
 
930
        self._lock_actions.append(('broken', result))
 
931
 
831
932
    def _ndiff_strings(self, a, b):
832
933
        """Return ndiff between two strings containing lines.
833
 
        
 
934
 
834
935
        A trailing newline is added if missing to make the strings
835
936
        print properly."""
836
937
        if b and b[-1] != '\n':
861
962
 
862
963
    def assertEqualDiff(self, a, b, message=None):
863
964
        """Assert two texts are equal, if not raise an exception.
864
 
        
865
 
        This is intended for use with multi-line strings where it can 
 
965
 
 
966
        This is intended for use with multi-line strings where it can
866
967
        be hard to find the differences by eye.
867
968
        """
868
969
        # TODO: perhaps override assertEquals to call this for strings?
870
971
            return
871
972
        if message is None:
872
973
            message = "texts not equal:\n"
 
974
        if a == b + '\n':
 
975
            message = 'first string is missing a final newline.\n'
 
976
        if a + '\n' == b:
 
977
            message = 'second string is missing a final newline.\n'
873
978
        raise AssertionError(message +
874
979
                             self._ndiff_strings(a, b))
875
 
        
 
980
 
876
981
    def assertEqualMode(self, mode, mode_test):
877
982
        self.assertEqual(mode, mode_test,
878
983
                         'mode mismatch %o != %o' % (mode, mode_test))
879
984
 
 
985
    def assertEqualStat(self, expected, actual):
 
986
        """assert that expected and actual are the same stat result.
 
987
 
 
988
        :param expected: A stat result.
 
989
        :param actual: A stat result.
 
990
        :raises AssertionError: If the expected and actual stat values differ
 
991
            other than by atime.
 
992
        """
 
993
        self.assertEqual(expected.st_size, actual.st_size)
 
994
        self.assertEqual(expected.st_mtime, actual.st_mtime)
 
995
        self.assertEqual(expected.st_ctime, actual.st_ctime)
 
996
        self.assertEqual(expected.st_dev, actual.st_dev)
 
997
        self.assertEqual(expected.st_ino, actual.st_ino)
 
998
        self.assertEqual(expected.st_mode, actual.st_mode)
 
999
 
 
1000
    def assertLength(self, length, obj_with_len):
 
1001
        """Assert that obj_with_len is of length length."""
 
1002
        if len(obj_with_len) != length:
 
1003
            self.fail("Incorrect length: wanted %d, got %d for %r" % (
 
1004
                length, len(obj_with_len), obj_with_len))
 
1005
 
880
1006
    def assertPositive(self, val):
881
1007
        """Assert that val is greater than 0."""
882
1008
        self.assertTrue(val > 0, 'expected a positive value, but got %s' % val)
894
1020
        if not s.endswith(suffix):
895
1021
            raise AssertionError('string %r does not end with %r' % (s, suffix))
896
1022
 
897
 
    def assertContainsRe(self, haystack, needle_re):
 
1023
    def assertContainsRe(self, haystack, needle_re, flags=0):
898
1024
        """Assert that a contains something matching a regular expression."""
899
 
        if not re.search(needle_re, haystack):
 
1025
        if not re.search(needle_re, haystack, flags):
900
1026
            if '\n' in haystack or len(haystack) > 60:
901
1027
                # a long string, format it in a more readable way
902
1028
                raise AssertionError(
906
1032
                raise AssertionError('pattern "%s" not found in "%s"'
907
1033
                        % (needle_re, haystack))
908
1034
 
909
 
    def assertNotContainsRe(self, haystack, needle_re):
 
1035
    def assertNotContainsRe(self, haystack, needle_re, flags=0):
910
1036
        """Assert that a does not match a regular expression"""
911
 
        if re.search(needle_re, haystack):
 
1037
        if re.search(needle_re, haystack, flags):
912
1038
            raise AssertionError('pattern "%s" found in "%s"'
913
1039
                    % (needle_re, haystack))
914
1040
 
921
1047
 
922
1048
    def assertListRaises(self, excClass, func, *args, **kwargs):
923
1049
        """Fail unless excClass is raised when the iterator from func is used.
924
 
        
 
1050
 
925
1051
        Many functions can return generators this makes sure
926
1052
        to wrap them in a list() call to make sure the whole generator
927
1053
        is run, and that the proper exception is raised.
928
1054
        """
929
1055
        try:
930
1056
            list(func(*args, **kwargs))
931
 
        except excClass:
932
 
            return
 
1057
        except excClass, e:
 
1058
            return e
933
1059
        else:
934
1060
            if getattr(excClass,'__name__', None) is not None:
935
1061
                excName = excClass.__name__
974
1100
                raise AssertionError("%r is %r." % (left, right))
975
1101
 
976
1102
    def assertTransportMode(self, transport, path, mode):
977
 
        """Fail if a path does not have mode mode.
978
 
        
 
1103
        """Fail if a path does not have mode "mode".
 
1104
 
979
1105
        If modes are not supported on this transport, the assertion is ignored.
980
1106
        """
981
1107
        if not transport._can_roundtrip_unix_modebits():
983
1109
        path_stat = transport.stat(path)
984
1110
        actual_mode = stat.S_IMODE(path_stat.st_mode)
985
1111
        self.assertEqual(mode, actual_mode,
986
 
            'mode of %r incorrect (%o != %o)' % (path, mode, actual_mode))
 
1112
                         'mode of %r incorrect (%s != %s)'
 
1113
                         % (path, oct(mode), oct(actual_mode)))
987
1114
 
988
1115
    def assertIsSameRealPath(self, path1, path2):
989
1116
        """Fail if path1 and path2 points to different files"""
991
1118
                         osutils.realpath(path2),
992
1119
                         "apparent paths:\na = %s\nb = %s\n," % (path1, path2))
993
1120
 
994
 
    def assertIsInstance(self, obj, kls):
995
 
        """Fail if obj is not an instance of kls"""
 
1121
    def assertIsInstance(self, obj, kls, msg=None):
 
1122
        """Fail if obj is not an instance of kls
 
1123
        
 
1124
        :param msg: Supplementary message to show if the assertion fails.
 
1125
        """
996
1126
        if not isinstance(obj, kls):
997
 
            self.fail("%r is an instance of %s rather than %s" % (
998
 
                obj, obj.__class__, kls))
 
1127
            m = "%r is an instance of %s rather than %s" % (
 
1128
                obj, obj.__class__, kls)
 
1129
            if msg:
 
1130
                m += ": " + msg
 
1131
            self.fail(m)
999
1132
 
1000
1133
    def expectFailure(self, reason, assertion, *args, **kwargs):
1001
1134
        """Invoke a test, expecting it to fail for the given reason.
1032
1165
        else:
1033
1166
            self.fail('Unexpected success.  Should have failed: %s' % reason)
1034
1167
 
 
1168
    def assertFileEqual(self, content, path):
 
1169
        """Fail if path does not contain 'content'."""
 
1170
        self.failUnlessExists(path)
 
1171
        f = file(path, 'rb')
 
1172
        try:
 
1173
            s = f.read()
 
1174
        finally:
 
1175
            f.close()
 
1176
        self.assertEqualDiff(content, s)
 
1177
 
 
1178
    def failUnlessExists(self, path):
 
1179
        """Fail unless path or paths, which may be abs or relative, exist."""
 
1180
        if not isinstance(path, basestring):
 
1181
            for p in path:
 
1182
                self.failUnlessExists(p)
 
1183
        else:
 
1184
            self.failUnless(osutils.lexists(path),path+" does not exist")
 
1185
 
 
1186
    def failIfExists(self, path):
 
1187
        """Fail if path or paths, which may be abs or relative, exist."""
 
1188
        if not isinstance(path, basestring):
 
1189
            for p in path:
 
1190
                self.failIfExists(p)
 
1191
        else:
 
1192
            self.failIf(osutils.lexists(path),path+" exists")
 
1193
 
1035
1194
    def _capture_deprecation_warnings(self, a_callable, *args, **kwargs):
1036
1195
        """A helper for callDeprecated and applyDeprecated.
1037
1196
 
1064
1223
        To test that a deprecated method raises an error, do something like
1065
1224
        this::
1066
1225
 
1067
 
        self.assertRaises(errors.ReservedId,
1068
 
            self.applyDeprecated, zero_ninetyone,
1069
 
                br.append_revision, 'current:')
 
1226
            self.assertRaises(errors.ReservedId,
 
1227
                self.applyDeprecated,
 
1228
                deprecated_in((1, 5, 0)),
 
1229
                br.append_revision,
 
1230
                'current:')
1070
1231
 
1071
1232
        :param deprecation_format: The deprecation format that the callable
1072
1233
            should have been deprecated with. This is the same type as the
1106
1267
        # warnings.  It's the easiest way to insulate ourselves from -Werror,
1107
1268
        # though.  -- Andrew, 20071062
1108
1269
        wlist = []
1109
 
        def _catcher(message, category, filename, lineno, file=None):
 
1270
        def _catcher(message, category, filename, lineno, file=None, line=None):
1110
1271
            # despite the name, 'message' is normally(?) a Warning subclass
1111
1272
            # instance
1112
1273
            wlist.append(message)
1124
1285
    def callDeprecated(self, expected, callable, *args, **kwargs):
1125
1286
        """Assert that a callable is deprecated in a particular way.
1126
1287
 
1127
 
        This is a very precise test for unusual requirements. The 
 
1288
        This is a very precise test for unusual requirements. The
1128
1289
        applyDeprecated helper function is probably more suited for most tests
1129
1290
        as it allows you to simply specify the deprecation format being used
1130
1291
        and will ensure that that is issued for the function being called.
1150
1311
        """
1151
1312
        fileno, name = tempfile.mkstemp(suffix='.log', prefix='testbzr')
1152
1313
        self._log_file = os.fdopen(fileno, 'w+')
1153
 
        self._log_nonce = bzrlib.trace.enable_test_log(self._log_file)
 
1314
        self._log_memento = bzrlib.trace.push_log_file(self._log_file)
1154
1315
        self._log_file_name = name
1155
1316
        self.addCleanup(self._finishLogFile)
1156
1317
 
1161
1322
        """
1162
1323
        if self._log_file is None:
1163
1324
            return
1164
 
        bzrlib.trace.disable_test_log(self._log_nonce)
 
1325
        bzrlib.trace.pop_log_file(self._log_memento)
1165
1326
        self._log_file.close()
1166
1327
        self._log_file = None
1167
1328
        if not self._keep_log_file:
1172
1333
        """Make the logfile not be deleted when _finishLogFile is called."""
1173
1334
        self._keep_log_file = True
1174
1335
 
1175
 
    def addCleanup(self, callable):
 
1336
    def thisFailsStrictLockCheck(self):
 
1337
        """It is known that this test would fail with -Dstrict_locks.
 
1338
 
 
1339
        By default, all tests are run with strict lock checking unless
 
1340
        -Edisable_lock_checks is supplied. However there are some tests which
 
1341
        we know fail strict locks at this point that have not been fixed.
 
1342
        They should call this function to disable the strict checking.
 
1343
 
 
1344
        This should be used sparingly, it is much better to fix the locking
 
1345
        issues rather than papering over the problem by calling this function.
 
1346
        """
 
1347
        debug.debug_flags.discard('strict_locks')
 
1348
 
 
1349
    def addCleanup(self, callable, *args, **kwargs):
1176
1350
        """Arrange to run a callable when this case is torn down.
1177
1351
 
1178
 
        Callables are run in the reverse of the order they are registered, 
 
1352
        Callables are run in the reverse of the order they are registered,
1179
1353
        ie last-in first-out.
1180
1354
        """
1181
 
        if callable in self._cleanups:
1182
 
            raise ValueError("cleanup function %r already registered on %s" 
1183
 
                    % (callable, self))
1184
 
        self._cleanups.append(callable)
 
1355
        self._cleanups.append((callable, args, kwargs))
1185
1356
 
1186
1357
    def _cleanEnvironment(self):
1187
1358
        new_env = {
1188
1359
            'BZR_HOME': None, # Don't inherit BZR_HOME to all the tests.
1189
1360
            'HOME': os.getcwd(),
1190
 
            'APPDATA': None,  # bzr now use Win32 API and don't rely on APPDATA
 
1361
            # bzr now uses the Win32 API and doesn't rely on APPDATA, but the
 
1362
            # tests do check our impls match APPDATA
1191
1363
            'BZR_EDITOR': None, # test_msgeditor manipulates this variable
 
1364
            'VISUAL': None,
 
1365
            'EDITOR': None,
1192
1366
            'BZR_EMAIL': None,
1193
1367
            'BZREMAIL': None, # may still be present in the environment
1194
1368
            'EMAIL': None,
1195
1369
            'BZR_PROGRESS_BAR': None,
 
1370
            'BZR_LOG': None,
 
1371
            'BZR_PLUGIN_PATH': None,
 
1372
            # Make sure that any text ui tests are consistent regardless of
 
1373
            # the environment the test case is run in; you may want tests that
 
1374
            # test other combinations.  'dumb' is a reasonable guess for tests
 
1375
            # going to a pipe or a StringIO.
 
1376
            'TERM': 'dumb',
 
1377
            'LINES': '25',
 
1378
            'COLUMNS': '80',
1196
1379
            # SSH Agent
1197
1380
            'SSH_AUTH_SOCK': None,
1198
1381
            # Proxies
1204
1387
            'NO_PROXY': None,
1205
1388
            'all_proxy': None,
1206
1389
            'ALL_PROXY': None,
1207
 
            # Nobody cares about these ones AFAIK. So far at
 
1390
            # Nobody cares about ftp_proxy, FTP_PROXY AFAIK. So far at
1208
1391
            # least. If you do (care), please update this comment
1209
 
            # -- vila 20061212
 
1392
            # -- vila 20080401
1210
1393
            'ftp_proxy': None,
1211
1394
            'FTP_PROXY': None,
1212
1395
            'BZR_REMOTE_PATH': None,
1229
1412
            osutils.set_or_unset_env(name, value)
1230
1413
 
1231
1414
    def _restoreHooks(self):
1232
 
        for klass, hooks in self._preserved_hooks.items():
1233
 
            setattr(klass, 'hooks', hooks)
 
1415
        for klass, (name, hooks) in self._preserved_hooks.items():
 
1416
            setattr(klass, name, hooks)
1234
1417
 
1235
1418
    def knownFailure(self, reason):
1236
1419
        """This test has failed for some known reason."""
1237
1420
        raise KnownFailure(reason)
1238
1421
 
 
1422
    def _do_skip(self, result, reason):
 
1423
        addSkip = getattr(result, 'addSkip', None)
 
1424
        if not callable(addSkip):
 
1425
            result.addError(self, sys.exc_info())
 
1426
        else:
 
1427
            addSkip(self, reason)
 
1428
 
1239
1429
    def run(self, result=None):
1240
1430
        if result is None: result = self.defaultTestResult()
1241
1431
        for feature in getattr(self, '_test_needs_features', []):
1246
1436
                else:
1247
1437
                    result.addSuccess(self)
1248
1438
                result.stopTest(self)
1249
 
                return
1250
 
        return unittest.TestCase.run(self, result)
 
1439
                return result
 
1440
        try:
 
1441
            try:
 
1442
                result.startTest(self)
 
1443
                absent_attr = object()
 
1444
                # Python 2.5
 
1445
                method_name = getattr(self, '_testMethodName', absent_attr)
 
1446
                if method_name is absent_attr:
 
1447
                    # Python 2.4
 
1448
                    method_name = getattr(self, '_TestCase__testMethodName')
 
1449
                testMethod = getattr(self, method_name)
 
1450
                try:
 
1451
                    try:
 
1452
                        self.setUp()
 
1453
                        if not self._bzr_test_setUp_run:
 
1454
                            self.fail(
 
1455
                                "test setUp did not invoke "
 
1456
                                "bzrlib.tests.TestCase's setUp")
 
1457
                    except KeyboardInterrupt:
 
1458
                        self._runCleanups()
 
1459
                        raise
 
1460
                    except TestSkipped, e:
 
1461
                        self._do_skip(result, e.args[0])
 
1462
                        self.tearDown()
 
1463
                        return result
 
1464
                    except:
 
1465
                        result.addError(self, sys.exc_info())
 
1466
                        self._runCleanups()
 
1467
                        return result
 
1468
 
 
1469
                    ok = False
 
1470
                    try:
 
1471
                        testMethod()
 
1472
                        ok = True
 
1473
                    except self.failureException:
 
1474
                        result.addFailure(self, sys.exc_info())
 
1475
                    except TestSkipped, e:
 
1476
                        if not e.args:
 
1477
                            reason = "No reason given."
 
1478
                        else:
 
1479
                            reason = e.args[0]
 
1480
                        self._do_skip(result, reason)
 
1481
                    except KeyboardInterrupt:
 
1482
                        self._runCleanups()
 
1483
                        raise
 
1484
                    except:
 
1485
                        result.addError(self, sys.exc_info())
 
1486
 
 
1487
                    try:
 
1488
                        self.tearDown()
 
1489
                        if not self._bzr_test_tearDown_run:
 
1490
                            self.fail(
 
1491
                                "test tearDown did not invoke "
 
1492
                                "bzrlib.tests.TestCase's tearDown")
 
1493
                    except KeyboardInterrupt:
 
1494
                        self._runCleanups()
 
1495
                        raise
 
1496
                    except:
 
1497
                        result.addError(self, sys.exc_info())
 
1498
                        self._runCleanups()
 
1499
                        ok = False
 
1500
                    if ok: result.addSuccess(self)
 
1501
                finally:
 
1502
                    result.stopTest(self)
 
1503
                return result
 
1504
            except TestNotApplicable:
 
1505
                # Not moved from the result [yet].
 
1506
                self._runCleanups()
 
1507
                raise
 
1508
            except KeyboardInterrupt:
 
1509
                self._runCleanups()
 
1510
                raise
 
1511
        finally:
 
1512
            saved_attrs = {}
 
1513
            for attr_name in self.attrs_to_keep:
 
1514
                if attr_name in self.__dict__:
 
1515
                    saved_attrs[attr_name] = self.__dict__[attr_name]
 
1516
            self.__dict__ = saved_attrs
1251
1517
 
1252
1518
    def tearDown(self):
1253
1519
        self._runCleanups()
 
1520
        self._log_contents = ''
 
1521
        self._bzr_test_tearDown_run = True
1254
1522
        unittest.TestCase.tearDown(self)
1255
1523
 
1256
1524
    def time(self, callable, *args, **kwargs):
1257
1525
        """Run callable and accrue the time it takes to the benchmark time.
1258
 
        
 
1526
 
1259
1527
        If lsprofiling is enabled (i.e. by --lsprof-time to bzr selftest) then
1260
1528
        this will cause lsprofile statistics to be gathered and stored in
1261
1529
        self._benchcalls.
1276
1544
            self._benchtime += time.time() - start
1277
1545
 
1278
1546
    def _runCleanups(self):
1279
 
        """Run registered cleanup functions. 
 
1547
        """Run registered cleanup functions.
1280
1548
 
1281
1549
        This should only be called from TestCase.tearDown.
1282
1550
        """
1283
 
        # TODO: Perhaps this should keep running cleanups even if 
 
1551
        # TODO: Perhaps this should keep running cleanups even if
1284
1552
        # one of them fails?
1285
1553
 
1286
1554
        # Actually pop the cleanups from the list so tearDown running
1287
1555
        # twice is safe (this happens for skipped tests).
1288
1556
        while self._cleanups:
1289
 
            self._cleanups.pop()()
 
1557
            cleanup, args, kwargs = self._cleanups.pop()
 
1558
            cleanup(*args, **kwargs)
1290
1559
 
1291
1560
    def log(self, *args):
1292
1561
        mutter(*args)
1302
1571
        """
1303
1572
        # flush the log file, to get all content
1304
1573
        import bzrlib.trace
1305
 
        bzrlib.trace._trace_file.flush()
 
1574
        if bzrlib.trace._trace_file:
 
1575
            bzrlib.trace._trace_file.flush()
1306
1576
        if self._log_contents:
 
1577
            # XXX: this can hardly contain the content flushed above --vila
 
1578
            # 20080128
1307
1579
            return self._log_contents
1308
1580
        if self._log_file_name is not None:
1309
1581
            logfile = open(self._log_file_name)
1346
1618
 
1347
1619
    def _run_bzr_core(self, args, retcode, encoding, stdin,
1348
1620
            working_dir):
 
1621
        # Clear chk_map page cache, because the contents are likely to mask
 
1622
        # locking errors.
 
1623
        chk_map.clear_cache()
1349
1624
        if encoding is None:
1350
 
            encoding = bzrlib.user_encoding
 
1625
            encoding = osutils.get_user_encoding()
1351
1626
        stdout = StringIOWrapper()
1352
1627
        stderr = StringIOWrapper()
1353
1628
        stdout.encoding = encoding
1398
1673
        passed in three ways:
1399
1674
 
1400
1675
        1- A list of strings, eg ["commit", "a"].  This is recommended
1401
 
        when the command contains whitespace or metacharacters, or 
 
1676
        when the command contains whitespace or metacharacters, or
1402
1677
        is built up at run time.
1403
1678
 
1404
 
        2- A single string, eg "add a".  This is the most convenient 
 
1679
        2- A single string, eg "add a".  This is the most convenient
1405
1680
        for hardcoded commands.
1406
1681
 
1407
1682
        This runs bzr through the interface that catches and reports
1429
1704
            stdin=stdin,
1430
1705
            working_dir=working_dir,
1431
1706
            )
 
1707
        self.assertIsInstance(error_regexes, (list, tuple))
1432
1708
        for regex in error_regexes:
1433
1709
            self.assertContainsRe(err, regex)
1434
1710
        return out, err
1466
1742
    def run_bzr_subprocess(self, *args, **kwargs):
1467
1743
        """Run bzr in a subprocess for testing.
1468
1744
 
1469
 
        This starts a new Python interpreter and runs bzr in there. 
 
1745
        This starts a new Python interpreter and runs bzr in there.
1470
1746
        This should only be used for tests that have a justifiable need for
1471
1747
        this isolation: e.g. they are testing startup time, or signal
1472
 
        handling, or early startup code, etc.  Subprocess code can't be 
 
1748
        handling, or early startup code, etc.  Subprocess code can't be
1473
1749
        profiled or debugged so easily.
1474
1750
 
1475
1751
        :keyword retcode: The status code that is expected.  Defaults to 0.  If
1493
1769
            elif isinstance(args[0], basestring):
1494
1770
                args = list(shlex.split(args[0]))
1495
1771
        else:
1496
 
            symbol_versioning.warn(zero_ninetyone %
1497
 
                                   "passing varargs to run_bzr_subprocess",
1498
 
                                   DeprecationWarning, stacklevel=3)
 
1772
            raise ValueError("passing varargs to run_bzr_subprocess")
1499
1773
        process = self.start_bzr_subprocess(args, env_changes=env_changes,
1500
1774
                                            working_dir=working_dir,
1501
1775
                                            allow_plugins=allow_plugins)
1557
1831
            # so we will avoid using it on all platforms, just to
1558
1832
            # make sure the code path is used, and we don't break on win32
1559
1833
            cleanup_environment()
1560
 
            command = [sys.executable, bzr_path]
 
1834
            command = [sys.executable]
 
1835
            # frozen executables don't need the path to bzr
 
1836
            if getattr(sys, "frozen", None) is None:
 
1837
                command.append(bzr_path)
1561
1838
            if not allow_plugins:
1562
1839
                command.append('--no-plugins')
1563
1840
            command.extend(process_args)
1689
1966
        sio.encoding = output_encoding
1690
1967
        return sio
1691
1968
 
 
1969
    def disable_verb(self, verb):
 
1970
        """Disable a smart server verb for one test."""
 
1971
        from bzrlib.smart import request
 
1972
        request_handlers = request.request_handlers
 
1973
        orig_method = request_handlers.get(verb)
 
1974
        request_handlers.remove(verb)
 
1975
        def restoreVerb():
 
1976
            request_handlers.register(verb, orig_method)
 
1977
        self.addCleanup(restoreVerb)
 
1978
 
 
1979
 
 
1980
class CapturedCall(object):
 
1981
    """A helper for capturing smart server calls for easy debug analysis."""
 
1982
 
 
1983
    def __init__(self, params, prefix_length):
 
1984
        """Capture the call with params and skip prefix_length stack frames."""
 
1985
        self.call = params
 
1986
        import traceback
 
1987
        # The last 5 frames are the __init__, the hook frame, and 3 smart
 
1988
        # client frames. Beyond this we could get more clever, but this is good
 
1989
        # enough for now.
 
1990
        stack = traceback.extract_stack()[prefix_length:-5]
 
1991
        self.stack = ''.join(traceback.format_list(stack))
 
1992
 
 
1993
    def __str__(self):
 
1994
        return self.call.method
 
1995
 
 
1996
    def __repr__(self):
 
1997
        return self.call.method
 
1998
 
 
1999
    def stack(self):
 
2000
        return self.stack
 
2001
 
1692
2002
 
1693
2003
class TestCaseWithMemoryTransport(TestCase):
1694
2004
    """Common test class for tests that do not need disk resources.
1713
2023
    _TEST_NAME = 'test'
1714
2024
 
1715
2025
    def __init__(self, methodName='runTest'):
1716
 
        # allow test parameterisation after test construction and before test
1717
 
        # execution. Variables that the parameteriser sets need to be 
 
2026
        # allow test parameterization after test construction and before test
 
2027
        # execution. Variables that the parameterizer sets need to be
1718
2028
        # ones that are not set by setUp, or setUp will trash them.
1719
2029
        super(TestCaseWithMemoryTransport, self).__init__(methodName)
1720
2030
        self.vfs_transport_factory = default_transport
1727
2037
 
1728
2038
        This transport is for the test scratch space relative to
1729
2039
        "self._test_root"
1730
 
        
 
2040
 
1731
2041
        :param relpath: a path relative to the base url.
1732
2042
        """
1733
2043
        t = get_transport(self.get_url(relpath))
1736
2046
 
1737
2047
    def get_readonly_transport(self, relpath=None):
1738
2048
        """Return a readonly transport for the test scratch space
1739
 
        
 
2049
 
1740
2050
        This can be used to test that operations which should only need
1741
2051
        readonly access in fact do not try to write.
1742
2052
 
1773
2083
    def get_readonly_url(self, relpath=None):
1774
2084
        """Get a URL for the readonly transport.
1775
2085
 
1776
 
        This will either be backed by '.' or a decorator to the transport 
 
2086
        This will either be backed by '.' or a decorator to the transport
1777
2087
        used by self.get_url()
1778
2088
        relpath provides for clients to get a path relative to the base url.
1779
2089
        These should only be downwards relative, not upwards.
1912
2222
 
1913
2223
    def makeAndChdirToTestDir(self):
1914
2224
        """Create a temporary directories for this one test.
1915
 
        
 
2225
 
1916
2226
        This must set self.test_home_dir and self.test_dir and chdir to
1917
2227
        self.test_dir.
1918
 
        
 
2228
 
1919
2229
        For TestCaseWithMemoryTransport we chdir to the TEST_ROOT for this test.
1920
2230
        """
1921
2231
        os.chdir(TestCaseWithMemoryTransport.TEST_ROOT)
1922
2232
        self.test_dir = TestCaseWithMemoryTransport.TEST_ROOT
1923
2233
        self.test_home_dir = self.test_dir + "/MemoryTransportMissingHomeDir"
1924
 
        
 
2234
 
1925
2235
    def make_branch(self, relpath, format=None):
1926
2236
        """Create a branch on the transport at relpath."""
1927
2237
        repo = self.make_repository(relpath, format=format)
1945
2255
 
1946
2256
    def make_repository(self, relpath, shared=False, format=None):
1947
2257
        """Create a repository on our default transport at relpath.
1948
 
        
 
2258
 
1949
2259
        Note that relpath must be a relative path, not a full url.
1950
2260
        """
1951
2261
        # FIXME: If you create a remoterepository this returns the underlying
1952
 
        # real format, which is incorrect.  Actually we should make sure that 
 
2262
        # real format, which is incorrect.  Actually we should make sure that
1953
2263
        # RemoteBzrDir returns a RemoteRepository.
1954
2264
        # maybe  mbp 20070410
1955
2265
        made_control = self.make_bzrdir(relpath, format=format)
1956
2266
        return made_control.create_repository(shared=shared)
1957
2267
 
 
2268
    def make_smart_server(self, path):
 
2269
        smart_server = server.SmartTCPServer_for_testing()
 
2270
        smart_server.setUp(self.get_server())
 
2271
        remote_transport = get_transport(smart_server.get_url()).clone(path)
 
2272
        self.addCleanup(smart_server.tearDown)
 
2273
        return remote_transport
 
2274
 
1958
2275
    def make_branch_and_memory_tree(self, relpath, format=None):
1959
2276
        """Create a branch on the default transport and a MemoryTree for it."""
1960
2277
        b = self.make_branch(relpath, format=format)
1961
2278
        return memorytree.MemoryTree.create_on_branch(b)
1962
2279
 
 
2280
    def make_branch_builder(self, relpath, format=None):
 
2281
        branch = self.make_branch(relpath, format=format)
 
2282
        return branchbuilder.BranchBuilder(branch=branch)
 
2283
 
1963
2284
    def overrideEnvironmentForTesting(self):
1964
2285
        os.environ['HOME'] = self.test_home_dir
1965
2286
        os.environ['BZR_HOME'] = self.test_home_dir
1966
 
        
 
2287
 
1967
2288
    def setUp(self):
1968
2289
        super(TestCaseWithMemoryTransport, self).setUp()
1969
2290
        self._make_test_root()
1977
2298
        self.__server = None
1978
2299
        self.reduceLockdirTimeout()
1979
2300
 
1980
 
     
 
2301
    def setup_smart_server_with_call_log(self):
 
2302
        """Sets up a smart server as the transport server with a call log."""
 
2303
        self.transport_server = server.SmartTCPServer_for_testing
 
2304
        self.hpss_calls = []
 
2305
        import traceback
 
2306
        # Skip the current stack down to the caller of
 
2307
        # setup_smart_server_with_call_log
 
2308
        prefix_length = len(traceback.extract_stack()) - 2
 
2309
        def capture_hpss_call(params):
 
2310
            self.hpss_calls.append(
 
2311
                CapturedCall(params, prefix_length))
 
2312
        client._SmartClient.hooks.install_named_hook(
 
2313
            'call', capture_hpss_call, None)
 
2314
 
 
2315
    def reset_smart_call_log(self):
 
2316
        self.hpss_calls = []
 
2317
 
 
2318
 
1981
2319
class TestCaseInTempDir(TestCaseWithMemoryTransport):
1982
2320
    """Derived class that runs a test within a temporary directory.
1983
2321
 
1988
2326
    All test cases create their own directory within that.  If the
1989
2327
    tests complete successfully, the directory is removed.
1990
2328
 
1991
 
    :ivar test_base_dir: The path of the top-level directory for this 
 
2329
    :ivar test_base_dir: The path of the top-level directory for this
1992
2330
    test, which contains a home directory and a work directory.
1993
2331
 
1994
2332
    :ivar test_home_dir: An initially empty directory under test_base_dir
2008
2346
            self.log("actually: %r" % contents)
2009
2347
            self.fail("contents of %s not as expected" % filename)
2010
2348
 
 
2349
    def _getTestDirPrefix(self):
 
2350
        # create a directory within the top level test directory
 
2351
        if sys.platform in ('win32', 'cygwin'):
 
2352
            name_prefix = re.sub('[<>*=+",:;_/\\-]', '_', self.id())
 
2353
            # windows is likely to have path-length limits so use a short name
 
2354
            name_prefix = name_prefix[-30:]
 
2355
        else:
 
2356
            name_prefix = re.sub('[/]', '_', self.id())
 
2357
        return name_prefix
 
2358
 
2011
2359
    def makeAndChdirToTestDir(self):
2012
2360
        """See TestCaseWithMemoryTransport.makeAndChdirToTestDir().
2013
 
        
 
2361
 
2014
2362
        For TestCaseInTempDir we create a temporary directory based on the test
2015
2363
        name and then create two subdirs - test and home under it.
2016
2364
        """
2017
 
        # create a directory within the top level test directory
2018
 
        candidate_dir = osutils.mkdtemp(dir=self.TEST_ROOT)
 
2365
        name_prefix = osutils.pathjoin(TestCaseWithMemoryTransport.TEST_ROOT,
 
2366
            self._getTestDirPrefix())
 
2367
        name = name_prefix
 
2368
        for i in range(100):
 
2369
            if os.path.exists(name):
 
2370
                name = name_prefix + '_' + str(i)
 
2371
            else:
 
2372
                os.mkdir(name)
 
2373
                break
2019
2374
        # now create test and home directories within this dir
2020
 
        self.test_base_dir = candidate_dir
 
2375
        self.test_base_dir = name
2021
2376
        self.test_home_dir = self.test_base_dir + '/home'
2022
2377
        os.mkdir(self.test_home_dir)
2023
2378
        self.test_dir = self.test_base_dir + '/work'
2032
2387
        self.addCleanup(self.deleteTestDir)
2033
2388
 
2034
2389
    def deleteTestDir(self):
2035
 
        os.chdir(self.TEST_ROOT)
 
2390
        os.chdir(TestCaseWithMemoryTransport.TEST_ROOT)
2036
2391
        _rmtree_temp_dir(self.test_base_dir)
2037
2392
 
2038
2393
    def build_tree(self, shape, line_endings='binary', transport=None):
2045
2400
 
2046
2401
        This doesn't add anything to a branch.
2047
2402
 
 
2403
        :type shape:    list or tuple.
2048
2404
        :param line_endings: Either 'binary' or 'native'
2049
2405
            in binary mode, exact contents are written in native mode, the
2050
2406
            line endings match the default platform endings.
2052
2408
            If the transport is readonly or None, "." is opened automatically.
2053
2409
        :return: None
2054
2410
        """
 
2411
        if type(shape) not in (list, tuple):
 
2412
            raise AssertionError("Parameter 'shape' should be "
 
2413
                "a list or a tuple. Got %r instead" % (shape,))
2055
2414
        # It's OK to just create them using forward slashes on windows.
2056
2415
        if transport is None or transport.is_readonly():
2057
2416
            transport = get_transport(".")
2058
2417
        for name in shape:
2059
 
            self.assert_(isinstance(name, basestring))
 
2418
            self.assertIsInstance(name, basestring)
2060
2419
            if name[-1] == '/':
2061
2420
                transport.mkdir(urlutils.escape(name[:-1]))
2062
2421
            else:
2073
2432
    def build_tree_contents(self, shape):
2074
2433
        build_tree_contents(shape)
2075
2434
 
2076
 
    def assertFileEqual(self, content, path):
2077
 
        """Fail if path does not contain 'content'."""
2078
 
        self.failUnlessExists(path)
2079
 
        f = file(path, 'rb')
2080
 
        try:
2081
 
            s = f.read()
2082
 
        finally:
2083
 
            f.close()
2084
 
        self.assertEqualDiff(content, s)
2085
 
 
2086
 
    def failUnlessExists(self, path):
2087
 
        """Fail unless path or paths, which may be abs or relative, exist."""
2088
 
        if not isinstance(path, basestring):
2089
 
            for p in path:
2090
 
                self.failUnlessExists(p)
2091
 
        else:
2092
 
            self.failUnless(osutils.lexists(path),path+" does not exist")
2093
 
 
2094
 
    def failIfExists(self, path):
2095
 
        """Fail if path or paths, which may be abs or relative, exist."""
2096
 
        if not isinstance(path, basestring):
2097
 
            for p in path:
2098
 
                self.failIfExists(p)
2099
 
        else:
2100
 
            self.failIf(osutils.lexists(path),path+" exists")
2101
 
 
2102
2435
    def assertInWorkingTree(self, path, root_path='.', tree=None):
2103
2436
        """Assert whether path or paths are in the WorkingTree"""
2104
2437
        if tree is None:
2105
2438
            tree = workingtree.WorkingTree.open(root_path)
2106
2439
        if not isinstance(path, basestring):
2107
2440
            for p in path:
2108
 
                self.assertInWorkingTree(p,tree=tree)
 
2441
                self.assertInWorkingTree(p, tree=tree)
2109
2442
        else:
2110
2443
            self.assertIsNot(tree.path2id(path), None,
2111
2444
                path+' not in working tree.')
2131
2464
    ReadonlyTransportDecorator is used instead which allows the use of non disk
2132
2465
    based read write transports.
2133
2466
 
2134
 
    If an explicit class is provided for readonly access, that server and the 
 
2467
    If an explicit class is provided for readonly access, that server and the
2135
2468
    readwrite one must both define get_url() as resolving to os.getcwd().
2136
2469
    """
2137
2470
 
2175
2508
                # the branch is colocated on disk, we cannot create a checkout.
2176
2509
                # hopefully callers will expect this.
2177
2510
                local_controldir= bzrdir.BzrDir.open(self.get_vfs_only_url(relpath))
2178
 
                return local_controldir.create_workingtree()
 
2511
                wt = local_controldir.create_workingtree()
 
2512
                if wt.branch._format != b._format:
 
2513
                    wt._branch = b
 
2514
                    # Make sure that assigning to wt._branch fixes wt.branch,
 
2515
                    # in case the implementation details of workingtree objects
 
2516
                    # change.
 
2517
                    self.assertIs(b, wt.branch)
 
2518
                return wt
2179
2519
            else:
2180
2520
                return b.create_checkout(relpath, lightweight=True)
2181
2521
 
2216
2556
    for readonly urls.
2217
2557
 
2218
2558
    TODO RBC 20060127: make this an option to TestCaseWithTransport so it can
2219
 
                       be used without needed to redo it when a different 
 
2559
                       be used without needed to redo it when a different
2220
2560
                       subclass is in use ?
2221
2561
    """
2222
2562
 
2226
2566
            self.transport_readonly_server = HttpServer
2227
2567
 
2228
2568
 
2229
 
def filter_suite_by_re(suite, pattern, exclude_pattern=None,
2230
 
                       random_order=False):
2231
 
    """Create a test suite by filtering another one.
2232
 
    
 
2569
def condition_id_re(pattern):
 
2570
    """Create a condition filter which performs a re check on a test's id.
 
2571
 
 
2572
    :param pattern: A regular expression string.
 
2573
    :return: A callable that returns True if the re matches.
 
2574
    """
 
2575
    filter_re = osutils.re_compile_checked(pattern, 0,
 
2576
        'test filter')
 
2577
    def condition(test):
 
2578
        test_id = test.id()
 
2579
        return filter_re.search(test_id)
 
2580
    return condition
 
2581
 
 
2582
 
 
2583
def condition_isinstance(klass_or_klass_list):
 
2584
    """Create a condition filter which returns isinstance(param, klass).
 
2585
 
 
2586
    :return: A callable which when called with one parameter obj return the
 
2587
        result of isinstance(obj, klass_or_klass_list).
 
2588
    """
 
2589
    def condition(obj):
 
2590
        return isinstance(obj, klass_or_klass_list)
 
2591
    return condition
 
2592
 
 
2593
 
 
2594
def condition_id_in_list(id_list):
 
2595
    """Create a condition filter which verify that test's id in a list.
 
2596
 
 
2597
    :param id_list: A TestIdList object.
 
2598
    :return: A callable that returns True if the test's id appears in the list.
 
2599
    """
 
2600
    def condition(test):
 
2601
        return id_list.includes(test.id())
 
2602
    return condition
 
2603
 
 
2604
 
 
2605
def condition_id_startswith(starts):
 
2606
    """Create a condition filter verifying that test's id starts with a string.
 
2607
 
 
2608
    :param starts: A list of string.
 
2609
    :return: A callable that returns True if the test's id starts with one of
 
2610
        the given strings.
 
2611
    """
 
2612
    def condition(test):
 
2613
        for start in starts:
 
2614
            if test.id().startswith(start):
 
2615
                return True
 
2616
        return False
 
2617
    return condition
 
2618
 
 
2619
 
 
2620
def exclude_tests_by_condition(suite, condition):
 
2621
    """Create a test suite which excludes some tests from suite.
 
2622
 
 
2623
    :param suite: The suite to get tests from.
 
2624
    :param condition: A callable whose result evaluates True when called with a
 
2625
        test case which should be excluded from the result.
 
2626
    :return: A suite which contains the tests found in suite that fail
 
2627
        condition.
 
2628
    """
 
2629
    result = []
 
2630
    for test in iter_suite_tests(suite):
 
2631
        if not condition(test):
 
2632
            result.append(test)
 
2633
    return TestUtil.TestSuite(result)
 
2634
 
 
2635
 
 
2636
def filter_suite_by_condition(suite, condition):
 
2637
    """Create a test suite by filtering another one.
 
2638
 
 
2639
    :param suite: The source suite.
 
2640
    :param condition: A callable whose result evaluates True when called with a
 
2641
        test case which should be included in the result.
 
2642
    :return: A suite which contains the tests found in suite that pass
 
2643
        condition.
 
2644
    """
 
2645
    result = []
 
2646
    for test in iter_suite_tests(suite):
 
2647
        if condition(test):
 
2648
            result.append(test)
 
2649
    return TestUtil.TestSuite(result)
 
2650
 
 
2651
 
 
2652
def filter_suite_by_re(suite, pattern):
 
2653
    """Create a test suite by filtering another one.
 
2654
 
2233
2655
    :param suite:           the source suite
2234
2656
    :param pattern:         pattern that names must match
2235
 
    :param exclude_pattern: pattern that names must not match, if any
2236
 
    :param random_order:    if True, tests in the new suite will be put in
2237
 
                            random order
2238
 
    :returns: the newly created suite
2239
 
    """ 
2240
 
    return sort_suite_by_re(suite, pattern, exclude_pattern,
2241
 
        random_order, False)
2242
 
 
2243
 
 
2244
 
def sort_suite_by_re(suite, pattern, exclude_pattern=None,
2245
 
                     random_order=False, append_rest=True):
2246
 
    """Create a test suite by sorting another one.
2247
 
    
2248
 
    :param suite:           the source suite
2249
 
    :param pattern:         pattern that names must match in order to go
2250
 
                            first in the new suite
2251
 
    :param exclude_pattern: pattern that names must not match, if any
2252
 
    :param random_order:    if True, tests in the new suite will be put in
2253
 
                            random order
2254
 
    :param append_rest:     if False, pattern is a strict filter and not
2255
 
                            just an ordering directive
2256
 
    :returns: the newly created suite
2257
 
    """ 
2258
 
    first = []
2259
 
    second = []
2260
 
    filter_re = re.compile(pattern)
2261
 
    if exclude_pattern is not None:
2262
 
        exclude_re = re.compile(exclude_pattern)
 
2657
    :returns: the newly created suite
 
2658
    """
 
2659
    condition = condition_id_re(pattern)
 
2660
    result_suite = filter_suite_by_condition(suite, condition)
 
2661
    return result_suite
 
2662
 
 
2663
 
 
2664
def filter_suite_by_id_list(suite, test_id_list):
 
2665
    """Create a test suite by filtering another one.
 
2666
 
 
2667
    :param suite: The source suite.
 
2668
    :param test_id_list: A list of the test ids to keep as strings.
 
2669
    :returns: the newly created suite
 
2670
    """
 
2671
    condition = condition_id_in_list(test_id_list)
 
2672
    result_suite = filter_suite_by_condition(suite, condition)
 
2673
    return result_suite
 
2674
 
 
2675
 
 
2676
def filter_suite_by_id_startswith(suite, start):
 
2677
    """Create a test suite by filtering another one.
 
2678
 
 
2679
    :param suite: The source suite.
 
2680
    :param start: A list of string the test id must start with one of.
 
2681
    :returns: the newly created suite
 
2682
    """
 
2683
    condition = condition_id_startswith(start)
 
2684
    result_suite = filter_suite_by_condition(suite, condition)
 
2685
    return result_suite
 
2686
 
 
2687
 
 
2688
def exclude_tests_by_re(suite, pattern):
 
2689
    """Create a test suite which excludes some tests from suite.
 
2690
 
 
2691
    :param suite: The suite to get tests from.
 
2692
    :param pattern: A regular expression string. Test ids that match this
 
2693
        pattern will be excluded from the result.
 
2694
    :return: A TestSuite that contains all the tests from suite without the
 
2695
        tests that matched pattern. The order of tests is the same as it was in
 
2696
        suite.
 
2697
    """
 
2698
    return exclude_tests_by_condition(suite, condition_id_re(pattern))
 
2699
 
 
2700
 
 
2701
def preserve_input(something):
 
2702
    """A helper for performing test suite transformation chains.
 
2703
 
 
2704
    :param something: Anything you want to preserve.
 
2705
    :return: Something.
 
2706
    """
 
2707
    return something
 
2708
 
 
2709
 
 
2710
def randomize_suite(suite):
 
2711
    """Return a new TestSuite with suite's tests in random order.
 
2712
 
 
2713
    The tests in the input suite are flattened into a single suite in order to
 
2714
    accomplish this. Any nested TestSuites are removed to provide global
 
2715
    randomness.
 
2716
    """
 
2717
    tests = list(iter_suite_tests(suite))
 
2718
    random.shuffle(tests)
 
2719
    return TestUtil.TestSuite(tests)
 
2720
 
 
2721
 
 
2722
def split_suite_by_condition(suite, condition):
 
2723
    """Split a test suite into two by a condition.
 
2724
 
 
2725
    :param suite: The suite to split.
 
2726
    :param condition: The condition to match on. Tests that match this
 
2727
        condition are returned in the first test suite, ones that do not match
 
2728
        are in the second suite.
 
2729
    :return: A tuple of two test suites, where the first contains tests from
 
2730
        suite matching the condition, and the second contains the remainder
 
2731
        from suite. The order within each output suite is the same as it was in
 
2732
        suite.
 
2733
    """
 
2734
    matched = []
 
2735
    did_not_match = []
2263
2736
    for test in iter_suite_tests(suite):
2264
 
        test_id = test.id()
2265
 
        if exclude_pattern is None or not exclude_re.search(test_id):
2266
 
            if filter_re.search(test_id):
2267
 
                first.append(test)
2268
 
            elif append_rest:
2269
 
                second.append(test)
2270
 
    if random_order:
2271
 
        random.shuffle(first)
2272
 
        random.shuffle(second)
2273
 
    return TestUtil.TestSuite(first + second)
 
2737
        if condition(test):
 
2738
            matched.append(test)
 
2739
        else:
 
2740
            did_not_match.append(test)
 
2741
    return TestUtil.TestSuite(matched), TestUtil.TestSuite(did_not_match)
 
2742
 
 
2743
 
 
2744
def split_suite_by_re(suite, pattern):
 
2745
    """Split a test suite into two by a regular expression.
 
2746
 
 
2747
    :param suite: The suite to split.
 
2748
    :param pattern: A regular expression string. Test ids that match this
 
2749
        pattern will be in the first test suite returned, and the others in the
 
2750
        second test suite returned.
 
2751
    :return: A tuple of two test suites, where the first contains tests from
 
2752
        suite matching pattern, and the second contains the remainder from
 
2753
        suite. The order within each output suite is the same as it was in
 
2754
        suite.
 
2755
    """
 
2756
    return split_suite_by_condition(suite, condition_id_re(pattern))
2274
2757
 
2275
2758
 
2276
2759
def run_suite(suite, name='test', verbose=False, pattern=".*",
2281
2764
              random_seed=None,
2282
2765
              exclude_pattern=None,
2283
2766
              strict=False,
2284
 
              ):
 
2767
              runner_class=None,
 
2768
              suite_decorators=None,
 
2769
              stream=None):
 
2770
    """Run a test suite for bzr selftest.
 
2771
 
 
2772
    :param runner_class: The class of runner to use. Must support the
 
2773
        constructor arguments passed by run_suite which are more than standard
 
2774
        python uses.
 
2775
    :return: A boolean indicating success.
 
2776
    """
2285
2777
    TestCase._gather_lsprof_in_benchmarks = lsprof_timed
2286
2778
    if verbose:
2287
2779
        verbosity = 2
2288
2780
    else:
2289
2781
        verbosity = 1
2290
 
    runner = TextTestRunner(stream=sys.stdout,
 
2782
    if runner_class is None:
 
2783
        runner_class = TextTestRunner
 
2784
    if stream is None:
 
2785
        stream = sys.stdout
 
2786
    runner = runner_class(stream=stream,
2291
2787
                            descriptions=0,
2292
2788
                            verbosity=verbosity,
2293
2789
                            bench_history=bench_history,
2294
2790
                            list_only=list_only,
 
2791
                            strict=strict,
2295
2792
                            )
2296
2793
    runner.stop_on_failure=stop_on_failure
2297
 
    # Initialise the random number generator and display the seed used.
2298
 
    # We convert the seed to a long to make it reuseable across invocations.
2299
 
    random_order = False
2300
 
    if random_seed is not None:
2301
 
        random_order = True
2302
 
        if random_seed == "now":
2303
 
            random_seed = long(time.time())
 
2794
    # built in decorator factories:
 
2795
    decorators = [
 
2796
        random_order(random_seed, runner),
 
2797
        exclude_tests(exclude_pattern),
 
2798
        ]
 
2799
    if matching_tests_first:
 
2800
        decorators.append(tests_first(pattern))
 
2801
    else:
 
2802
        decorators.append(filter_tests(pattern))
 
2803
    if suite_decorators:
 
2804
        decorators.extend(suite_decorators)
 
2805
    # tell the result object how many tests will be running: (except if
 
2806
    # --parallel=fork is being used. Robert said he will provide a better
 
2807
    # progress design later -- vila 20090817)
 
2808
    if fork_decorator not in decorators:
 
2809
        decorators.append(CountingDecorator)
 
2810
    for decorator in decorators:
 
2811
        suite = decorator(suite)
 
2812
    result = runner.run(suite)
 
2813
    if list_only:
 
2814
        return True
 
2815
    result.done()
 
2816
    if strict:
 
2817
        return result.wasStrictlySuccessful()
 
2818
    else:
 
2819
        return result.wasSuccessful()
 
2820
 
 
2821
 
 
2822
# A registry where get() returns a suite decorator.
 
2823
parallel_registry = registry.Registry()
 
2824
 
 
2825
 
 
2826
def fork_decorator(suite):
 
2827
    concurrency = osutils.local_concurrency()
 
2828
    if concurrency == 1:
 
2829
        return suite
 
2830
    from testtools import ConcurrentTestSuite
 
2831
    return ConcurrentTestSuite(suite, fork_for_tests)
 
2832
parallel_registry.register('fork', fork_decorator)
 
2833
 
 
2834
 
 
2835
def subprocess_decorator(suite):
 
2836
    concurrency = osutils.local_concurrency()
 
2837
    if concurrency == 1:
 
2838
        return suite
 
2839
    from testtools import ConcurrentTestSuite
 
2840
    return ConcurrentTestSuite(suite, reinvoke_for_tests)
 
2841
parallel_registry.register('subprocess', subprocess_decorator)
 
2842
 
 
2843
 
 
2844
def exclude_tests(exclude_pattern):
 
2845
    """Return a test suite decorator that excludes tests."""
 
2846
    if exclude_pattern is None:
 
2847
        return identity_decorator
 
2848
    def decorator(suite):
 
2849
        return ExcludeDecorator(suite, exclude_pattern)
 
2850
    return decorator
 
2851
 
 
2852
 
 
2853
def filter_tests(pattern):
 
2854
    if pattern == '.*':
 
2855
        return identity_decorator
 
2856
    def decorator(suite):
 
2857
        return FilterTestsDecorator(suite, pattern)
 
2858
    return decorator
 
2859
 
 
2860
 
 
2861
def random_order(random_seed, runner):
 
2862
    """Return a test suite decorator factory for randomising tests order.
 
2863
    
 
2864
    :param random_seed: now, a string which casts to a long, or a long.
 
2865
    :param runner: A test runner with a stream attribute to report on.
 
2866
    """
 
2867
    if random_seed is None:
 
2868
        return identity_decorator
 
2869
    def decorator(suite):
 
2870
        return RandomDecorator(suite, random_seed, runner.stream)
 
2871
    return decorator
 
2872
 
 
2873
 
 
2874
def tests_first(pattern):
 
2875
    if pattern == '.*':
 
2876
        return identity_decorator
 
2877
    def decorator(suite):
 
2878
        return TestFirstDecorator(suite, pattern)
 
2879
    return decorator
 
2880
 
 
2881
 
 
2882
def identity_decorator(suite):
 
2883
    """Return suite."""
 
2884
    return suite
 
2885
 
 
2886
 
 
2887
class TestDecorator(TestSuite):
 
2888
    """A decorator for TestCase/TestSuite objects.
 
2889
    
 
2890
    Usually, subclasses should override __iter__(used when flattening test
 
2891
    suites), which we do to filter, reorder, parallelise and so on, run() and
 
2892
    debug().
 
2893
    """
 
2894
 
 
2895
    def __init__(self, suite):
 
2896
        TestSuite.__init__(self)
 
2897
        self.addTest(suite)
 
2898
 
 
2899
    def countTestCases(self):
 
2900
        cases = 0
 
2901
        for test in self:
 
2902
            cases += test.countTestCases()
 
2903
        return cases
 
2904
 
 
2905
    def debug(self):
 
2906
        for test in self:
 
2907
            test.debug()
 
2908
 
 
2909
    def run(self, result):
 
2910
        # Use iteration on self, not self._tests, to allow subclasses to hook
 
2911
        # into __iter__.
 
2912
        for test in self:
 
2913
            if result.shouldStop:
 
2914
                break
 
2915
            test.run(result)
 
2916
        return result
 
2917
 
 
2918
 
 
2919
class CountingDecorator(TestDecorator):
 
2920
    """A decorator which calls result.progress(self.countTestCases)."""
 
2921
 
 
2922
    def run(self, result):
 
2923
        progress_method = getattr(result, 'progress', None)
 
2924
        if callable(progress_method):
 
2925
            progress_method(self.countTestCases(), SUBUNIT_SEEK_SET)
 
2926
        return super(CountingDecorator, self).run(result)
 
2927
 
 
2928
 
 
2929
class ExcludeDecorator(TestDecorator):
 
2930
    """A decorator which excludes test matching an exclude pattern."""
 
2931
 
 
2932
    def __init__(self, suite, exclude_pattern):
 
2933
        TestDecorator.__init__(self, suite)
 
2934
        self.exclude_pattern = exclude_pattern
 
2935
        self.excluded = False
 
2936
 
 
2937
    def __iter__(self):
 
2938
        if self.excluded:
 
2939
            return iter(self._tests)
 
2940
        self.excluded = True
 
2941
        suite = exclude_tests_by_re(self, self.exclude_pattern)
 
2942
        del self._tests[:]
 
2943
        self.addTests(suite)
 
2944
        return iter(self._tests)
 
2945
 
 
2946
 
 
2947
class FilterTestsDecorator(TestDecorator):
 
2948
    """A decorator which filters tests to those matching a pattern."""
 
2949
 
 
2950
    def __init__(self, suite, pattern):
 
2951
        TestDecorator.__init__(self, suite)
 
2952
        self.pattern = pattern
 
2953
        self.filtered = False
 
2954
 
 
2955
    def __iter__(self):
 
2956
        if self.filtered:
 
2957
            return iter(self._tests)
 
2958
        self.filtered = True
 
2959
        suite = filter_suite_by_re(self, self.pattern)
 
2960
        del self._tests[:]
 
2961
        self.addTests(suite)
 
2962
        return iter(self._tests)
 
2963
 
 
2964
 
 
2965
class RandomDecorator(TestDecorator):
 
2966
    """A decorator which randomises the order of its tests."""
 
2967
 
 
2968
    def __init__(self, suite, random_seed, stream):
 
2969
        TestDecorator.__init__(self, suite)
 
2970
        self.random_seed = random_seed
 
2971
        self.randomised = False
 
2972
        self.stream = stream
 
2973
 
 
2974
    def __iter__(self):
 
2975
        if self.randomised:
 
2976
            return iter(self._tests)
 
2977
        self.randomised = True
 
2978
        self.stream.writeln("Randomizing test order using seed %s\n" %
 
2979
            (self.actual_seed()))
 
2980
        # Initialise the random number generator.
 
2981
        random.seed(self.actual_seed())
 
2982
        suite = randomize_suite(self)
 
2983
        del self._tests[:]
 
2984
        self.addTests(suite)
 
2985
        return iter(self._tests)
 
2986
 
 
2987
    def actual_seed(self):
 
2988
        if self.random_seed == "now":
 
2989
            # We convert the seed to a long to make it reuseable across
 
2990
            # invocations (because the user can reenter it).
 
2991
            self.random_seed = long(time.time())
2304
2992
        else:
2305
2993
            # Convert the seed to a long if we can
2306
2994
            try:
2307
 
                random_seed = long(random_seed)
 
2995
                self.random_seed = long(self.random_seed)
2308
2996
            except:
2309
2997
                pass
2310
 
        runner.stream.writeln("Randomizing test order using seed %s\n" %
2311
 
            (random_seed))
2312
 
        random.seed(random_seed)
2313
 
    # Customise the list of tests if requested
2314
 
    if pattern != '.*' or exclude_pattern is not None or random_order:
2315
 
        if matching_tests_first:
2316
 
            suite = sort_suite_by_re(suite, pattern, exclude_pattern,
2317
 
                random_order)
2318
 
        else:
2319
 
            suite = filter_suite_by_re(suite, pattern, exclude_pattern,
2320
 
                random_order)
2321
 
    result = runner.run(suite)
2322
 
 
2323
 
    if strict:
2324
 
        return result.wasStrictlySuccessful()
2325
 
 
2326
 
    return result.wasSuccessful()
 
2998
        return self.random_seed
 
2999
 
 
3000
 
 
3001
class TestFirstDecorator(TestDecorator):
 
3002
    """A decorator which moves named tests to the front."""
 
3003
 
 
3004
    def __init__(self, suite, pattern):
 
3005
        TestDecorator.__init__(self, suite)
 
3006
        self.pattern = pattern
 
3007
        self.filtered = False
 
3008
 
 
3009
    def __iter__(self):
 
3010
        if self.filtered:
 
3011
            return iter(self._tests)
 
3012
        self.filtered = True
 
3013
        suites = split_suite_by_re(self, self.pattern)
 
3014
        del self._tests[:]
 
3015
        self.addTests(suites)
 
3016
        return iter(self._tests)
 
3017
 
 
3018
 
 
3019
def partition_tests(suite, count):
 
3020
    """Partition suite into count lists of tests."""
 
3021
    result = []
 
3022
    tests = list(iter_suite_tests(suite))
 
3023
    tests_per_process = int(math.ceil(float(len(tests)) / count))
 
3024
    for block in range(count):
 
3025
        low_test = block * tests_per_process
 
3026
        high_test = low_test + tests_per_process
 
3027
        process_tests = tests[low_test:high_test]
 
3028
        result.append(process_tests)
 
3029
    return result
 
3030
 
 
3031
 
 
3032
def fork_for_tests(suite):
 
3033
    """Take suite and start up one runner per CPU by forking()
 
3034
 
 
3035
    :return: An iterable of TestCase-like objects which can each have
 
3036
        run(result) called on them to feed tests to result.
 
3037
    """
 
3038
    concurrency = osutils.local_concurrency()
 
3039
    result = []
 
3040
    from subunit import TestProtocolClient, ProtocolTestCase
 
3041
    try:
 
3042
        from subunit.test_results import AutoTimingTestResultDecorator
 
3043
    except ImportError:
 
3044
        AutoTimingTestResultDecorator = lambda x:x
 
3045
    class TestInOtherProcess(ProtocolTestCase):
 
3046
        # Should be in subunit, I think. RBC.
 
3047
        def __init__(self, stream, pid):
 
3048
            ProtocolTestCase.__init__(self, stream)
 
3049
            self.pid = pid
 
3050
 
 
3051
        def run(self, result):
 
3052
            try:
 
3053
                ProtocolTestCase.run(self, result)
 
3054
            finally:
 
3055
                os.waitpid(self.pid, os.WNOHANG)
 
3056
 
 
3057
    test_blocks = partition_tests(suite, concurrency)
 
3058
    for process_tests in test_blocks:
 
3059
        process_suite = TestSuite()
 
3060
        process_suite.addTests(process_tests)
 
3061
        c2pread, c2pwrite = os.pipe()
 
3062
        pid = os.fork()
 
3063
        if pid == 0:
 
3064
            try:
 
3065
                os.close(c2pread)
 
3066
                # Leave stderr and stdout open so we can see test noise
 
3067
                # Close stdin so that the child goes away if it decides to
 
3068
                # read from stdin (otherwise its a roulette to see what
 
3069
                # child actually gets keystrokes for pdb etc).
 
3070
                sys.stdin.close()
 
3071
                sys.stdin = None
 
3072
                stream = os.fdopen(c2pwrite, 'wb', 1)
 
3073
                subunit_result = AutoTimingTestResultDecorator(
 
3074
                    TestProtocolClient(stream))
 
3075
                process_suite.run(subunit_result)
 
3076
            finally:
 
3077
                os._exit(0)
 
3078
        else:
 
3079
            os.close(c2pwrite)
 
3080
            stream = os.fdopen(c2pread, 'rb', 1)
 
3081
            test = TestInOtherProcess(stream, pid)
 
3082
            result.append(test)
 
3083
    return result
 
3084
 
 
3085
 
 
3086
def reinvoke_for_tests(suite):
 
3087
    """Take suite and start up one runner per CPU using subprocess().
 
3088
 
 
3089
    :return: An iterable of TestCase-like objects which can each have
 
3090
        run(result) called on them to feed tests to result.
 
3091
    """
 
3092
    concurrency = osutils.local_concurrency()
 
3093
    result = []
 
3094
    from subunit import ProtocolTestCase
 
3095
    class TestInSubprocess(ProtocolTestCase):
 
3096
        def __init__(self, process, name):
 
3097
            ProtocolTestCase.__init__(self, process.stdout)
 
3098
            self.process = process
 
3099
            self.process.stdin.close()
 
3100
            self.name = name
 
3101
 
 
3102
        def run(self, result):
 
3103
            try:
 
3104
                ProtocolTestCase.run(self, result)
 
3105
            finally:
 
3106
                self.process.wait()
 
3107
                os.unlink(self.name)
 
3108
            # print "pid %d finished" % finished_process
 
3109
    test_blocks = partition_tests(suite, concurrency)
 
3110
    for process_tests in test_blocks:
 
3111
        # ugly; currently reimplement rather than reuses TestCase methods.
 
3112
        bzr_path = os.path.dirname(os.path.dirname(bzrlib.__file__))+'/bzr'
 
3113
        if not os.path.isfile(bzr_path):
 
3114
            # We are probably installed. Assume sys.argv is the right file
 
3115
            bzr_path = sys.argv[0]
 
3116
        fd, test_list_file_name = tempfile.mkstemp()
 
3117
        test_list_file = os.fdopen(fd, 'wb', 1)
 
3118
        for test in process_tests:
 
3119
            test_list_file.write(test.id() + '\n')
 
3120
        test_list_file.close()
 
3121
        try:
 
3122
            argv = [bzr_path, 'selftest', '--load-list', test_list_file_name,
 
3123
                '--subunit']
 
3124
            if '--no-plugins' in sys.argv:
 
3125
                argv.append('--no-plugins')
 
3126
            # stderr=STDOUT would be ideal, but until we prevent noise on
 
3127
            # stderr it can interrupt the subunit protocol.
 
3128
            process = Popen(argv, stdin=PIPE, stdout=PIPE, stderr=PIPE,
 
3129
                bufsize=1)
 
3130
            test = TestInSubprocess(process, test_list_file_name)
 
3131
            result.append(test)
 
3132
        except:
 
3133
            os.unlink(test_list_file_name)
 
3134
            raise
 
3135
    return result
 
3136
 
 
3137
 
 
3138
class BZRTransformingResult(unittest.TestResult):
 
3139
 
 
3140
    def __init__(self, target):
 
3141
        unittest.TestResult.__init__(self)
 
3142
        self.result = target
 
3143
 
 
3144
    def startTest(self, test):
 
3145
        self.result.startTest(test)
 
3146
 
 
3147
    def stopTest(self, test):
 
3148
        self.result.stopTest(test)
 
3149
 
 
3150
    def addError(self, test, err):
 
3151
        feature = self._error_looks_like('UnavailableFeature: ', err)
 
3152
        if feature is not None:
 
3153
            self.result.addNotSupported(test, feature)
 
3154
        else:
 
3155
            self.result.addError(test, err)
 
3156
 
 
3157
    def addFailure(self, test, err):
 
3158
        known = self._error_looks_like('KnownFailure: ', err)
 
3159
        if known is not None:
 
3160
            self.result._addKnownFailure(test, [KnownFailure,
 
3161
                                                KnownFailure(known), None])
 
3162
        else:
 
3163
            self.result.addFailure(test, err)
 
3164
 
 
3165
    def addSkip(self, test, reason):
 
3166
        self.result.addSkip(test, reason)
 
3167
 
 
3168
    def addSuccess(self, test):
 
3169
        self.result.addSuccess(test)
 
3170
 
 
3171
    def _error_looks_like(self, prefix, err):
 
3172
        """Deserialize exception and returns the stringify value."""
 
3173
        import subunit
 
3174
        value = None
 
3175
        typ, exc, _ = err
 
3176
        if isinstance(exc, subunit.RemoteException):
 
3177
            # stringify the exception gives access to the remote traceback
 
3178
            # We search the last line for 'prefix'
 
3179
            lines = str(exc).split('\n')
 
3180
            while lines and not lines[-1]:
 
3181
                lines.pop(-1)
 
3182
            if lines:
 
3183
                if lines[-1].startswith(prefix):
 
3184
                    value = lines[-1][len(prefix):]
 
3185
        return value
 
3186
 
 
3187
 
 
3188
# Controlled by "bzr selftest -E=..." option
 
3189
# Currently supported:
 
3190
#   -Eallow_debug           Will no longer clear debug.debug_flags() so it
 
3191
#                           preserves any flags supplied at the command line.
 
3192
#   -Edisable_lock_checks   Turns errors in mismatched locks into simple prints
 
3193
#                           rather than failing tests. And no longer raise
 
3194
#                           LockContention when fctnl locks are not being used
 
3195
#                           with proper exclusion rules.
 
3196
selftest_debug_flags = set()
2327
3197
 
2328
3198
 
2329
3199
def selftest(verbose=False, pattern=".*", stop_on_failure=True,
2336
3206
             random_seed=None,
2337
3207
             exclude_pattern=None,
2338
3208
             strict=False,
 
3209
             load_list=None,
 
3210
             debug_flags=None,
 
3211
             starting_with=None,
 
3212
             runner_class=None,
 
3213
             suite_decorators=None,
 
3214
             stream=None,
2339
3215
             ):
2340
3216
    """Run the whole test suite under the enhanced runner"""
2341
3217
    # XXX: Very ugly way to do this...
2349
3225
        transport = default_transport
2350
3226
    old_transport = default_transport
2351
3227
    default_transport = transport
 
3228
    global selftest_debug_flags
 
3229
    old_debug_flags = selftest_debug_flags
 
3230
    if debug_flags is not None:
 
3231
        selftest_debug_flags = set(debug_flags)
2352
3232
    try:
 
3233
        if load_list is None:
 
3234
            keep_only = None
 
3235
        else:
 
3236
            keep_only = load_test_id_list(load_list)
 
3237
        if starting_with:
 
3238
            starting_with = [test_prefix_alias_registry.resolve_alias(start)
 
3239
                             for start in starting_with]
2353
3240
        if test_suite_factory is None:
2354
 
            suite = test_suite()
 
3241
            # Reduce loading time by loading modules based on the starting_with
 
3242
            # patterns.
 
3243
            suite = test_suite(keep_only, starting_with)
2355
3244
        else:
2356
3245
            suite = test_suite_factory()
 
3246
        if starting_with:
 
3247
            # But always filter as requested.
 
3248
            suite = filter_suite_by_id_startswith(suite, starting_with)
2357
3249
        return run_suite(suite, 'testbzr', verbose=verbose, pattern=pattern,
2358
3250
                     stop_on_failure=stop_on_failure,
2359
3251
                     transport=transport,
2363
3255
                     list_only=list_only,
2364
3256
                     random_seed=random_seed,
2365
3257
                     exclude_pattern=exclude_pattern,
2366
 
                     strict=strict)
 
3258
                     strict=strict,
 
3259
                     runner_class=runner_class,
 
3260
                     suite_decorators=suite_decorators,
 
3261
                     stream=stream,
 
3262
                     )
2367
3263
    finally:
2368
3264
        default_transport = old_transport
2369
 
 
2370
 
 
2371
 
def test_suite():
 
3265
        selftest_debug_flags = old_debug_flags
 
3266
 
 
3267
 
 
3268
def load_test_id_list(file_name):
 
3269
    """Load a test id list from a text file.
 
3270
 
 
3271
    The format is one test id by line.  No special care is taken to impose
 
3272
    strict rules, these test ids are used to filter the test suite so a test id
 
3273
    that do not match an existing test will do no harm. This allows user to add
 
3274
    comments, leave blank lines, etc.
 
3275
    """
 
3276
    test_list = []
 
3277
    try:
 
3278
        ftest = open(file_name, 'rt')
 
3279
    except IOError, e:
 
3280
        if e.errno != errno.ENOENT:
 
3281
            raise
 
3282
        else:
 
3283
            raise errors.NoSuchFile(file_name)
 
3284
 
 
3285
    for test_name in ftest.readlines():
 
3286
        test_list.append(test_name.strip())
 
3287
    ftest.close()
 
3288
    return test_list
 
3289
 
 
3290
 
 
3291
def suite_matches_id_list(test_suite, id_list):
 
3292
    """Warns about tests not appearing or appearing more than once.
 
3293
 
 
3294
    :param test_suite: A TestSuite object.
 
3295
    :param test_id_list: The list of test ids that should be found in
 
3296
         test_suite.
 
3297
 
 
3298
    :return: (absents, duplicates) absents is a list containing the test found
 
3299
        in id_list but not in test_suite, duplicates is a list containing the
 
3300
        test found multiple times in test_suite.
 
3301
 
 
3302
    When using a prefined test id list, it may occurs that some tests do not
 
3303
    exist anymore or that some tests use the same id. This function warns the
 
3304
    tester about potential problems in his workflow (test lists are volatile)
 
3305
    or in the test suite itself (using the same id for several tests does not
 
3306
    help to localize defects).
 
3307
    """
 
3308
    # Build a dict counting id occurrences
 
3309
    tests = dict()
 
3310
    for test in iter_suite_tests(test_suite):
 
3311
        id = test.id()
 
3312
        tests[id] = tests.get(id, 0) + 1
 
3313
 
 
3314
    not_found = []
 
3315
    duplicates = []
 
3316
    for id in id_list:
 
3317
        occurs = tests.get(id, 0)
 
3318
        if not occurs:
 
3319
            not_found.append(id)
 
3320
        elif occurs > 1:
 
3321
            duplicates.append(id)
 
3322
 
 
3323
    return not_found, duplicates
 
3324
 
 
3325
 
 
3326
class TestIdList(object):
 
3327
    """Test id list to filter a test suite.
 
3328
 
 
3329
    Relying on the assumption that test ids are built as:
 
3330
    <module>[.<class>.<method>][(<param>+)], <module> being in python dotted
 
3331
    notation, this class offers methods to :
 
3332
    - avoid building a test suite for modules not refered to in the test list,
 
3333
    - keep only the tests listed from the module test suite.
 
3334
    """
 
3335
 
 
3336
    def __init__(self, test_id_list):
 
3337
        # When a test suite needs to be filtered against us we compare test ids
 
3338
        # for equality, so a simple dict offers a quick and simple solution.
 
3339
        self.tests = dict().fromkeys(test_id_list, True)
 
3340
 
 
3341
        # While unittest.TestCase have ids like:
 
3342
        # <module>.<class>.<method>[(<param+)],
 
3343
        # doctest.DocTestCase can have ids like:
 
3344
        # <module>
 
3345
        # <module>.<class>
 
3346
        # <module>.<function>
 
3347
        # <module>.<class>.<method>
 
3348
 
 
3349
        # Since we can't predict a test class from its name only, we settle on
 
3350
        # a simple constraint: a test id always begins with its module name.
 
3351
 
 
3352
        modules = {}
 
3353
        for test_id in test_id_list:
 
3354
            parts = test_id.split('.')
 
3355
            mod_name = parts.pop(0)
 
3356
            modules[mod_name] = True
 
3357
            for part in parts:
 
3358
                mod_name += '.' + part
 
3359
                modules[mod_name] = True
 
3360
        self.modules = modules
 
3361
 
 
3362
    def refers_to(self, module_name):
 
3363
        """Is there tests for the module or one of its sub modules."""
 
3364
        return self.modules.has_key(module_name)
 
3365
 
 
3366
    def includes(self, test_id):
 
3367
        return self.tests.has_key(test_id)
 
3368
 
 
3369
 
 
3370
class TestPrefixAliasRegistry(registry.Registry):
 
3371
    """A registry for test prefix aliases.
 
3372
 
 
3373
    This helps implement shorcuts for the --starting-with selftest
 
3374
    option. Overriding existing prefixes is not allowed but not fatal (a
 
3375
    warning will be emitted).
 
3376
    """
 
3377
 
 
3378
    def register(self, key, obj, help=None, info=None,
 
3379
                 override_existing=False):
 
3380
        """See Registry.register.
 
3381
 
 
3382
        Trying to override an existing alias causes a warning to be emitted,
 
3383
        not a fatal execption.
 
3384
        """
 
3385
        try:
 
3386
            super(TestPrefixAliasRegistry, self).register(
 
3387
                key, obj, help=help, info=info, override_existing=False)
 
3388
        except KeyError:
 
3389
            actual = self.get(key)
 
3390
            note('Test prefix alias %s is already used for %s, ignoring %s'
 
3391
                 % (key, actual, obj))
 
3392
 
 
3393
    def resolve_alias(self, id_start):
 
3394
        """Replace the alias by the prefix in the given string.
 
3395
 
 
3396
        Using an unknown prefix is an error to help catching typos.
 
3397
        """
 
3398
        parts = id_start.split('.')
 
3399
        try:
 
3400
            parts[0] = self.get(parts[0])
 
3401
        except KeyError:
 
3402
            raise errors.BzrCommandError(
 
3403
                '%s is not a known test prefix alias' % parts[0])
 
3404
        return '.'.join(parts)
 
3405
 
 
3406
 
 
3407
test_prefix_alias_registry = TestPrefixAliasRegistry()
 
3408
"""Registry of test prefix aliases."""
 
3409
 
 
3410
 
 
3411
# This alias allows to detect typos ('bzrlin.') by making all valid test ids
 
3412
# appear prefixed ('bzrlib.' is "replaced" by 'bzrlib.').
 
3413
test_prefix_alias_registry.register('bzrlib', 'bzrlib')
 
3414
 
 
3415
# Obvious higest levels prefixes, feel free to add your own via a plugin
 
3416
test_prefix_alias_registry.register('bd', 'bzrlib.doc')
 
3417
test_prefix_alias_registry.register('bu', 'bzrlib.utils')
 
3418
test_prefix_alias_registry.register('bt', 'bzrlib.tests')
 
3419
test_prefix_alias_registry.register('bb', 'bzrlib.tests.blackbox')
 
3420
test_prefix_alias_registry.register('bp', 'bzrlib.plugins')
 
3421
 
 
3422
 
 
3423
def test_suite(keep_only=None, starting_with=None):
2372
3424
    """Build and return TestSuite for the whole of bzrlib.
2373
 
    
 
3425
 
 
3426
    :param keep_only: A list of test ids limiting the suite returned.
 
3427
 
 
3428
    :param starting_with: An id limiting the suite returned to the tests
 
3429
         starting with it.
 
3430
 
2374
3431
    This function can be replaced if you need to change the default test
2375
3432
    suite on a global basis, but it is not encouraged.
2376
3433
    """
2377
3434
    testmod_names = [
2378
 
                   'bzrlib.util.tests.test_bencode',
 
3435
                   'bzrlib.doc',
 
3436
                   'bzrlib.tests.blackbox',
 
3437
                   'bzrlib.tests.commands',
 
3438
                   'bzrlib.tests.per_branch',
 
3439
                   'bzrlib.tests.per_bzrdir',
 
3440
                   'bzrlib.tests.per_interrepository',
 
3441
                   'bzrlib.tests.per_intertree',
 
3442
                   'bzrlib.tests.per_inventory',
 
3443
                   'bzrlib.tests.per_interbranch',
 
3444
                   'bzrlib.tests.per_lock',
 
3445
                   'bzrlib.tests.per_transport',
 
3446
                   'bzrlib.tests.per_tree',
 
3447
                   'bzrlib.tests.per_pack_repository',
 
3448
                   'bzrlib.tests.per_repository',
 
3449
                   'bzrlib.tests.per_repository_chk',
 
3450
                   'bzrlib.tests.per_repository_reference',
 
3451
                   'bzrlib.tests.per_versionedfile',
 
3452
                   'bzrlib.tests.per_workingtree',
 
3453
                   'bzrlib.tests.test__annotator',
 
3454
                   'bzrlib.tests.test__chk_map',
2379
3455
                   'bzrlib.tests.test__dirstate_helpers',
 
3456
                   'bzrlib.tests.test__groupcompress',
 
3457
                   'bzrlib.tests.test__known_graph',
 
3458
                   'bzrlib.tests.test__rio',
 
3459
                   'bzrlib.tests.test__walkdirs_win32',
2380
3460
                   'bzrlib.tests.test_ancestry',
2381
3461
                   'bzrlib.tests.test_annotate',
2382
3462
                   'bzrlib.tests.test_api',
2383
3463
                   'bzrlib.tests.test_atomicfile',
2384
3464
                   'bzrlib.tests.test_bad_files',
 
3465
                   'bzrlib.tests.test_bencode',
2385
3466
                   'bzrlib.tests.test_bisect_multi',
2386
3467
                   'bzrlib.tests.test_branch',
2387
3468
                   'bzrlib.tests.test_branchbuilder',
 
3469
                   'bzrlib.tests.test_btree_index',
2388
3470
                   'bzrlib.tests.test_bugtracker',
2389
3471
                   'bzrlib.tests.test_bundle',
2390
3472
                   'bzrlib.tests.test_bzrdir',
 
3473
                   'bzrlib.tests.test__chunks_to_lines',
2391
3474
                   'bzrlib.tests.test_cache_utf8',
 
3475
                   'bzrlib.tests.test_chk_map',
 
3476
                   'bzrlib.tests.test_chk_serializer',
 
3477
                   'bzrlib.tests.test_chunk_writer',
 
3478
                   'bzrlib.tests.test_clean_tree',
2392
3479
                   'bzrlib.tests.test_commands',
2393
3480
                   'bzrlib.tests.test_commit',
2394
3481
                   'bzrlib.tests.test_commit_merge',
2395
3482
                   'bzrlib.tests.test_config',
2396
3483
                   'bzrlib.tests.test_conflicts',
2397
3484
                   'bzrlib.tests.test_counted_lock',
 
3485
                   'bzrlib.tests.test_crash',
2398
3486
                   'bzrlib.tests.test_decorators',
2399
3487
                   'bzrlib.tests.test_delta',
 
3488
                   'bzrlib.tests.test_debug',
2400
3489
                   'bzrlib.tests.test_deprecated_graph',
2401
3490
                   'bzrlib.tests.test_diff',
 
3491
                   'bzrlib.tests.test_directory_service',
2402
3492
                   'bzrlib.tests.test_dirstate',
2403
3493
                   'bzrlib.tests.test_email_message',
 
3494
                   'bzrlib.tests.test_eol_filters',
2404
3495
                   'bzrlib.tests.test_errors',
2405
 
                   'bzrlib.tests.test_escaped_store',
 
3496
                   'bzrlib.tests.test_export',
2406
3497
                   'bzrlib.tests.test_extract',
2407
3498
                   'bzrlib.tests.test_fetch',
 
3499
                   'bzrlib.tests.test_fifo_cache',
 
3500
                   'bzrlib.tests.test_filters',
2408
3501
                   'bzrlib.tests.test_ftp_transport',
 
3502
                   'bzrlib.tests.test_foreign',
2409
3503
                   'bzrlib.tests.test_generate_docs',
2410
3504
                   'bzrlib.tests.test_generate_ids',
2411
3505
                   'bzrlib.tests.test_globbing',
2412
3506
                   'bzrlib.tests.test_gpg',
2413
3507
                   'bzrlib.tests.test_graph',
 
3508
                   'bzrlib.tests.test_groupcompress',
2414
3509
                   'bzrlib.tests.test_hashcache',
2415
3510
                   'bzrlib.tests.test_help',
2416
3511
                   'bzrlib.tests.test_hooks',
2422
3517
                   'bzrlib.tests.test_index',
2423
3518
                   'bzrlib.tests.test_info',
2424
3519
                   'bzrlib.tests.test_inv',
 
3520
                   'bzrlib.tests.test_inventory_delta',
2425
3521
                   'bzrlib.tests.test_knit',
2426
3522
                   'bzrlib.tests.test_lazy_import',
2427
3523
                   'bzrlib.tests.test_lazy_regex',
 
3524
                   'bzrlib.tests.test_lock',
 
3525
                   'bzrlib.tests.test_lockable_files',
2428
3526
                   'bzrlib.tests.test_lockdir',
2429
 
                   'bzrlib.tests.test_lockable_files',
2430
3527
                   'bzrlib.tests.test_log',
 
3528
                   'bzrlib.tests.test_lru_cache',
2431
3529
                   'bzrlib.tests.test_lsprof',
2432
3530
                   'bzrlib.tests.test_mail_client',
2433
3531
                   'bzrlib.tests.test_memorytree',
2438
3536
                   'bzrlib.tests.test_missing',
2439
3537
                   'bzrlib.tests.test_msgeditor',
2440
3538
                   'bzrlib.tests.test_multiparent',
 
3539
                   'bzrlib.tests.test_mutabletree',
2441
3540
                   'bzrlib.tests.test_nonascii',
2442
3541
                   'bzrlib.tests.test_options',
2443
3542
                   'bzrlib.tests.test_osutils',
2448
3547
                   'bzrlib.tests.test_permissions',
2449
3548
                   'bzrlib.tests.test_plugins',
2450
3549
                   'bzrlib.tests.test_progress',
 
3550
                   'bzrlib.tests.test_read_bundle',
 
3551
                   'bzrlib.tests.test_reconcile',
2451
3552
                   'bzrlib.tests.test_reconfigure',
2452
 
                   'bzrlib.tests.test_reconcile',
2453
3553
                   'bzrlib.tests.test_registry',
2454
3554
                   'bzrlib.tests.test_remote',
 
3555
                   'bzrlib.tests.test_rename_map',
2455
3556
                   'bzrlib.tests.test_repository',
2456
3557
                   'bzrlib.tests.test_revert',
2457
3558
                   'bzrlib.tests.test_revision',
2458
 
                   'bzrlib.tests.test_revisionnamespaces',
 
3559
                   'bzrlib.tests.test_revisionspec',
2459
3560
                   'bzrlib.tests.test_revisiontree',
2460
3561
                   'bzrlib.tests.test_rio',
 
3562
                   'bzrlib.tests.test_rules',
2461
3563
                   'bzrlib.tests.test_sampler',
2462
3564
                   'bzrlib.tests.test_selftest',
 
3565
                   'bzrlib.tests.test_serializer',
2463
3566
                   'bzrlib.tests.test_setup',
2464
3567
                   'bzrlib.tests.test_sftp_transport',
 
3568
                   'bzrlib.tests.test_shelf',
 
3569
                   'bzrlib.tests.test_shelf_ui',
2465
3570
                   'bzrlib.tests.test_smart',
2466
3571
                   'bzrlib.tests.test_smart_add',
 
3572
                   'bzrlib.tests.test_smart_request',
2467
3573
                   'bzrlib.tests.test_smart_transport',
2468
3574
                   'bzrlib.tests.test_smtp_connection',
2469
3575
                   'bzrlib.tests.test_source',
2472
3578
                   'bzrlib.tests.test_store',
2473
3579
                   'bzrlib.tests.test_strace',
2474
3580
                   'bzrlib.tests.test_subsume',
 
3581
                   'bzrlib.tests.test_switch',
2475
3582
                   'bzrlib.tests.test_symbol_versioning',
2476
3583
                   'bzrlib.tests.test_tag',
2477
3584
                   'bzrlib.tests.test_testament',
2482
3589
                   'bzrlib.tests.test_transactions',
2483
3590
                   'bzrlib.tests.test_transform',
2484
3591
                   'bzrlib.tests.test_transport',
 
3592
                   'bzrlib.tests.test_transport_log',
2485
3593
                   'bzrlib.tests.test_tree',
2486
3594
                   'bzrlib.tests.test_treebuilder',
2487
3595
                   'bzrlib.tests.test_tsort',
2488
3596
                   'bzrlib.tests.test_tuned_gzip',
2489
3597
                   'bzrlib.tests.test_ui',
 
3598
                   'bzrlib.tests.test_uncommit',
2490
3599
                   'bzrlib.tests.test_upgrade',
 
3600
                   'bzrlib.tests.test_upgrade_stacked',
2491
3601
                   'bzrlib.tests.test_urlutils',
2492
 
                   'bzrlib.tests.test_versionedfile',
2493
3602
                   'bzrlib.tests.test_version',
2494
3603
                   'bzrlib.tests.test_version_info',
2495
3604
                   'bzrlib.tests.test_weave',
2500
3609
                   'bzrlib.tests.test_wsgi',
2501
3610
                   'bzrlib.tests.test_xml',
2502
3611
                   ]
2503
 
    test_transport_implementations = [
2504
 
        'bzrlib.tests.test_transport_implementations',
2505
 
        'bzrlib.tests.test_read_bundle',
2506
 
        ]
2507
 
    suite = TestUtil.TestSuite()
 
3612
 
2508
3613
    loader = TestUtil.TestLoader()
 
3614
 
 
3615
    if keep_only is not None:
 
3616
        id_filter = TestIdList(keep_only)
 
3617
    if starting_with:
 
3618
        # We take precedence over keep_only because *at loading time* using
 
3619
        # both options means we will load less tests for the same final result.
 
3620
        def interesting_module(name):
 
3621
            for start in starting_with:
 
3622
                if (
 
3623
                    # Either the module name starts with the specified string
 
3624
                    name.startswith(start)
 
3625
                    # or it may contain tests starting with the specified string
 
3626
                    or start.startswith(name)
 
3627
                    ):
 
3628
                    return True
 
3629
            return False
 
3630
        loader = TestUtil.FilteredByModuleTestLoader(interesting_module)
 
3631
 
 
3632
    elif keep_only is not None:
 
3633
        loader = TestUtil.FilteredByModuleTestLoader(id_filter.refers_to)
 
3634
        def interesting_module(name):
 
3635
            return id_filter.refers_to(name)
 
3636
 
 
3637
    else:
 
3638
        loader = TestUtil.TestLoader()
 
3639
        def interesting_module(name):
 
3640
            # No filtering, all modules are interesting
 
3641
            return True
 
3642
 
 
3643
    suite = loader.suiteClass()
 
3644
 
 
3645
    # modules building their suite with loadTestsFromModuleNames
2509
3646
    suite.addTest(loader.loadTestsFromModuleNames(testmod_names))
2510
 
    from bzrlib.tests.test_transport_implementations import TransportTestProviderAdapter
2511
 
    adapter = TransportTestProviderAdapter()
2512
 
    adapt_modules(test_transport_implementations, adapter, loader, suite)
2513
 
    for package in packages_to_test():
2514
 
        suite.addTest(package.test_suite())
2515
 
    for m in MODULES_TO_TEST:
2516
 
        suite.addTest(loader.loadTestsFromModule(m))
2517
 
    for m in MODULES_TO_DOCTEST:
 
3647
 
 
3648
    modules_to_doctest = [
 
3649
        'bzrlib',
 
3650
        'bzrlib.branchbuilder',
 
3651
        'bzrlib.export',
 
3652
        'bzrlib.inventory',
 
3653
        'bzrlib.iterablefile',
 
3654
        'bzrlib.lockdir',
 
3655
        'bzrlib.merge3',
 
3656
        'bzrlib.option',
 
3657
        'bzrlib.symbol_versioning',
 
3658
        'bzrlib.tests',
 
3659
        'bzrlib.timestamp',
 
3660
        'bzrlib.version_info_formats.format_custom',
 
3661
        ]
 
3662
 
 
3663
    for mod in modules_to_doctest:
 
3664
        if not interesting_module(mod):
 
3665
            # No tests to keep here, move along
 
3666
            continue
2518
3667
        try:
2519
 
            suite.addTest(doctest.DocTestSuite(m))
 
3668
            # note that this really does mean "report only" -- doctest
 
3669
            # still runs the rest of the examples
 
3670
            doc_suite = doctest.DocTestSuite(mod,
 
3671
                optionflags=doctest.REPORT_ONLY_FIRST_FAILURE)
2520
3672
        except ValueError, e:
2521
 
            print '**failed to get doctest for: %s\n%s' %(m,e)
 
3673
            print '**failed to get doctest for: %s\n%s' % (mod, e)
2522
3674
            raise
 
3675
        if len(doc_suite._tests) == 0:
 
3676
            raise errors.BzrError("no doctests found in %s" % (mod,))
 
3677
        suite.addTest(doc_suite)
 
3678
 
2523
3679
    default_encoding = sys.getdefaultencoding()
2524
3680
    for name, plugin in bzrlib.plugin.plugins().items():
2525
 
        try:
2526
 
            plugin_suite = plugin.test_suite()
2527
 
        except ImportError, e:
2528
 
            bzrlib.trace.warning(
2529
 
                'Unable to test plugin "%s": %s', name, e)
2530
 
        else:
2531
 
            if plugin_suite is not None:
2532
 
                suite.addTest(plugin_suite)
 
3681
        if not interesting_module(plugin.module.__name__):
 
3682
            continue
 
3683
        plugin_suite = plugin.test_suite()
 
3684
        # We used to catch ImportError here and turn it into just a warning,
 
3685
        # but really if you don't have --no-plugins this should be a failure.
 
3686
        # mbp 20080213 - see http://bugs.launchpad.net/bugs/189771
 
3687
        if plugin_suite is None:
 
3688
            plugin_suite = plugin.load_plugin_tests(loader)
 
3689
        if plugin_suite is not None:
 
3690
            suite.addTest(plugin_suite)
2533
3691
        if default_encoding != sys.getdefaultencoding():
2534
3692
            bzrlib.trace.warning(
2535
3693
                'Plugin "%s" tried to reset default encoding to: %s', name,
2536
3694
                sys.getdefaultencoding())
2537
3695
            reload(sys)
2538
3696
            sys.setdefaultencoding(default_encoding)
2539
 
    return suite
2540
 
 
2541
 
 
2542
 
def multiply_tests_from_modules(module_name_list, scenario_iter):
2543
 
    """Adapt all tests in some given modules to given scenarios.
2544
 
 
2545
 
    This is the recommended public interface for test parameterization.
2546
 
    Typically the test_suite() method for a per-implementation test
2547
 
    suite will call multiply_tests_from_modules and return the 
2548
 
    result.
2549
 
 
2550
 
    :param module_name_list: List of fully-qualified names of test
2551
 
        modules.
2552
 
    :param scenario_iter: Iterable of pairs of (scenario_name, 
2553
 
        scenario_param_dict).
2554
 
 
2555
 
    This returns a new TestSuite containing the cross product of
2556
 
    all the tests in all the modules, each repeated for each scenario.
2557
 
    Each test is adapted by adding the scenario name at the end 
2558
 
    of its name, and updating the test object's __dict__ with the
2559
 
    scenario_param_dict.
2560
 
 
2561
 
    >>> r = multiply_tests_from_modules(
2562
 
    ...     ['bzrlib.tests.test_sampler'],
2563
 
    ...     [('one', dict(param=1)), 
2564
 
    ...      ('two', dict(param=2))])
2565
 
    >>> tests = list(iter_suite_tests(r))
2566
 
    >>> len(tests)
2567
 
    2
2568
 
    >>> tests[0].id()
2569
 
    'bzrlib.tests.test_sampler.DemoTest.test_nothing(one)'
2570
 
    >>> tests[0].param
2571
 
    1
2572
 
    >>> tests[1].param
2573
 
    2
2574
 
    """
2575
 
    loader = TestLoader()
2576
 
    suite = TestSuite()
2577
 
    adapter = TestScenarioApplier()
2578
 
    adapter.scenarios = list(scenario_iter)
2579
 
    adapt_modules(module_name_list, adapter, loader, suite)
 
3697
 
 
3698
    if keep_only is not None:
 
3699
        # Now that the referred modules have loaded their tests, keep only the
 
3700
        # requested ones.
 
3701
        suite = filter_suite_by_id_list(suite, id_filter)
 
3702
        # Do some sanity checks on the id_list filtering
 
3703
        not_found, duplicates = suite_matches_id_list(suite, keep_only)
 
3704
        if starting_with:
 
3705
            # The tester has used both keep_only and starting_with, so he is
 
3706
            # already aware that some tests are excluded from the list, there
 
3707
            # is no need to tell him which.
 
3708
            pass
 
3709
        else:
 
3710
            # Some tests mentioned in the list are not in the test suite. The
 
3711
            # list may be out of date, report to the tester.
 
3712
            for id in not_found:
 
3713
                bzrlib.trace.warning('"%s" not found in the test suite', id)
 
3714
        for id in duplicates:
 
3715
            bzrlib.trace.warning('"%s" is used as an id by several tests', id)
 
3716
 
2580
3717
    return suite
2581
3718
 
2582
3719
 
2594
3731
        for right_name, right_dict in scenarios_right]
2595
3732
 
2596
3733
 
2597
 
 
2598
 
def adapt_modules(mods_list, adapter, loader, suite):
2599
 
    """Adapt the modules in mods_list using adapter and add to suite."""
2600
 
    for test in iter_suite_tests(loader.loadTestsFromModuleNames(mods_list)):
2601
 
        suite.addTests(adapter.adapt(test))
 
3734
def multiply_tests(tests, scenarios, result):
 
3735
    """Multiply tests_list by scenarios into result.
 
3736
 
 
3737
    This is the core workhorse for test parameterisation.
 
3738
 
 
3739
    Typically the load_tests() method for a per-implementation test suite will
 
3740
    call multiply_tests and return the result.
 
3741
 
 
3742
    :param tests: The tests to parameterise.
 
3743
    :param scenarios: The scenarios to apply: pairs of (scenario_name,
 
3744
        scenario_param_dict).
 
3745
    :param result: A TestSuite to add created tests to.
 
3746
 
 
3747
    This returns the passed in result TestSuite with the cross product of all
 
3748
    the tests repeated once for each scenario.  Each test is adapted by adding
 
3749
    the scenario name at the end of its id(), and updating the test object's
 
3750
    __dict__ with the scenario_param_dict.
 
3751
 
 
3752
    >>> import bzrlib.tests.test_sampler
 
3753
    >>> r = multiply_tests(
 
3754
    ...     bzrlib.tests.test_sampler.DemoTest('test_nothing'),
 
3755
    ...     [('one', dict(param=1)),
 
3756
    ...      ('two', dict(param=2))],
 
3757
    ...     TestSuite())
 
3758
    >>> tests = list(iter_suite_tests(r))
 
3759
    >>> len(tests)
 
3760
    2
 
3761
    >>> tests[0].id()
 
3762
    'bzrlib.tests.test_sampler.DemoTest.test_nothing(one)'
 
3763
    >>> tests[0].param
 
3764
    1
 
3765
    >>> tests[1].param
 
3766
    2
 
3767
    """
 
3768
    for test in iter_suite_tests(tests):
 
3769
        apply_scenarios(test, scenarios, result)
 
3770
    return result
 
3771
 
 
3772
 
 
3773
def apply_scenarios(test, scenarios, result):
 
3774
    """Apply the scenarios in scenarios to test and add to result.
 
3775
 
 
3776
    :param test: The test to apply scenarios to.
 
3777
    :param scenarios: An iterable of scenarios to apply to test.
 
3778
    :return: result
 
3779
    :seealso: apply_scenario
 
3780
    """
 
3781
    for scenario in scenarios:
 
3782
        result.addTest(apply_scenario(test, scenario))
 
3783
    return result
 
3784
 
 
3785
 
 
3786
def apply_scenario(test, scenario):
 
3787
    """Copy test and apply scenario to it.
 
3788
 
 
3789
    :param test: A test to adapt.
 
3790
    :param scenario: A tuple describing the scenarion.
 
3791
        The first element of the tuple is the new test id.
 
3792
        The second element is a dict containing attributes to set on the
 
3793
        test.
 
3794
    :return: The adapted test.
 
3795
    """
 
3796
    new_id = "%s(%s)" % (test.id(), scenario[0])
 
3797
    new_test = clone_test(test, new_id)
 
3798
    for name, value in scenario[1].items():
 
3799
        setattr(new_test, name, value)
 
3800
    return new_test
 
3801
 
 
3802
 
 
3803
def clone_test(test, new_id):
 
3804
    """Clone a test giving it a new id.
 
3805
 
 
3806
    :param test: The test to clone.
 
3807
    :param new_id: The id to assign to it.
 
3808
    :return: The new test.
 
3809
    """
 
3810
    from copy import deepcopy
 
3811
    new_test = deepcopy(test)
 
3812
    new_test.id = lambda: new_id
 
3813
    return new_test
2602
3814
 
2603
3815
 
2604
3816
def _rmtree_temp_dir(dirname):
2616
3828
    try:
2617
3829
        osutils.rmtree(dirname)
2618
3830
    except OSError, e:
2619
 
        if sys.platform == 'win32' and e.errno == errno.EACCES:
2620
 
            sys.stderr.write(('Permission denied: '
2621
 
                                 'unable to remove testing dir '
2622
 
                                 '%s\n' % os.path.basename(dirname)))
2623
 
        else:
2624
 
            raise
 
3831
        # We don't want to fail here because some useful display will be lost
 
3832
        # otherwise. Polluting the tmp dir is bad, but not giving all the
 
3833
        # possible info to the test runner is even worse.
 
3834
        sys.stderr.write('Unable to remove testing dir %s\n%s'
 
3835
                         % (os.path.basename(dirname), e))
2625
3836
 
2626
3837
 
2627
3838
class Feature(object):
2663
3874
SymlinkFeature = _SymlinkFeature()
2664
3875
 
2665
3876
 
 
3877
class _HardlinkFeature(Feature):
 
3878
 
 
3879
    def _probe(self):
 
3880
        return osutils.has_hardlinks()
 
3881
 
 
3882
    def feature_name(self):
 
3883
        return 'hardlinks'
 
3884
 
 
3885
HardlinkFeature = _HardlinkFeature()
 
3886
 
 
3887
 
2666
3888
class _OsFifoFeature(Feature):
2667
3889
 
2668
3890
    def _probe(self):
2674
3896
OsFifoFeature = _OsFifoFeature()
2675
3897
 
2676
3898
 
2677
 
class TestScenarioApplier(object):
2678
 
    """A tool to apply scenarios to tests."""
2679
 
 
2680
 
    def adapt(self, test):
2681
 
        """Return a TestSuite containing a copy of test for each scenario."""
2682
 
        result = unittest.TestSuite()
2683
 
        for scenario in self.scenarios:
2684
 
            result.addTest(self.adapt_test_to_scenario(test, scenario))
2685
 
        return result
2686
 
 
2687
 
    def adapt_test_to_scenario(self, test, scenario):
2688
 
        """Copy test and apply scenario to it.
2689
 
 
2690
 
        :param test: A test to adapt.
2691
 
        :param scenario: A tuple describing the scenarion.
2692
 
            The first element of the tuple is the new test id.
2693
 
            The second element is a dict containing attributes to set on the
2694
 
            test.
2695
 
        :return: The adapted test.
2696
 
        """
2697
 
        from copy import deepcopy
2698
 
        new_test = deepcopy(test)
2699
 
        for name, value in scenario[1].items():
2700
 
            setattr(new_test, name, value)
2701
 
        new_id = "%s(%s)" % (new_test.id(), scenario[0])
2702
 
        new_test.id = lambda: new_id
2703
 
        return new_test
 
3899
class _UnicodeFilenameFeature(Feature):
 
3900
    """Does the filesystem support Unicode filenames?"""
 
3901
 
 
3902
    def _probe(self):
 
3903
        try:
 
3904
            # Check for character combinations unlikely to be covered by any
 
3905
            # single non-unicode encoding. We use the characters
 
3906
            # - greek small letter alpha (U+03B1) and
 
3907
            # - braille pattern dots-123456 (U+283F).
 
3908
            os.stat(u'\u03b1\u283f')
 
3909
        except UnicodeEncodeError:
 
3910
            return False
 
3911
        except (IOError, OSError):
 
3912
            # The filesystem allows the Unicode filename but the file doesn't
 
3913
            # exist.
 
3914
            return True
 
3915
        else:
 
3916
            # The filesystem allows the Unicode filename and the file exists,
 
3917
            # for some reason.
 
3918
            return True
 
3919
 
 
3920
UnicodeFilenameFeature = _UnicodeFilenameFeature()
2704
3921
 
2705
3922
 
2706
3923
def probe_unicode_in_user_encoding():
2712
3929
    possible_vals = [u'm\xb5', u'\xe1', u'\u0410']
2713
3930
    for uni_val in possible_vals:
2714
3931
        try:
2715
 
            str_val = uni_val.encode(bzrlib.user_encoding)
 
3932
            str_val = uni_val.encode(osutils.get_user_encoding())
2716
3933
        except UnicodeEncodeError:
2717
3934
            # Try a different character
2718
3935
            pass
2736
3953
    return None
2737
3954
 
2738
3955
 
2739
 
class _FTPServerFeature(Feature):
2740
 
    """Some tests want an FTP Server, check if one is available.
2741
 
 
2742
 
    Right now, the only way this is available is if 'medusa' is installed.
2743
 
    http://www.amk.ca/python/code/medusa.html
2744
 
    """
2745
 
 
2746
 
    def _probe(self):
2747
 
        try:
2748
 
            import bzrlib.tests.ftp_server
2749
 
            return True
2750
 
        except ImportError:
2751
 
            return False
2752
 
 
2753
 
    def feature_name(self):
2754
 
        return 'FTPServer'
2755
 
 
2756
 
FTPServerFeature = _FTPServerFeature()
 
3956
class _HTTPSServerFeature(Feature):
 
3957
    """Some tests want an https Server, check if one is available.
 
3958
 
 
3959
    Right now, the only way this is available is under python2.6 which provides
 
3960
    an ssl module.
 
3961
    """
 
3962
 
 
3963
    def _probe(self):
 
3964
        try:
 
3965
            import ssl
 
3966
            return True
 
3967
        except ImportError:
 
3968
            return False
 
3969
 
 
3970
    def feature_name(self):
 
3971
        return 'HTTPSServer'
 
3972
 
 
3973
 
 
3974
HTTPSServerFeature = _HTTPSServerFeature()
 
3975
 
 
3976
 
 
3977
class _UnicodeFilename(Feature):
 
3978
    """Does the filesystem support Unicode filenames?"""
 
3979
 
 
3980
    def _probe(self):
 
3981
        try:
 
3982
            os.stat(u'\u03b1')
 
3983
        except UnicodeEncodeError:
 
3984
            return False
 
3985
        except (IOError, OSError):
 
3986
            # The filesystem allows the Unicode filename but the file doesn't
 
3987
            # exist.
 
3988
            return True
 
3989
        else:
 
3990
            # The filesystem allows the Unicode filename and the file exists,
 
3991
            # for some reason.
 
3992
            return True
 
3993
 
 
3994
UnicodeFilename = _UnicodeFilename()
 
3995
 
 
3996
 
 
3997
class _UTF8Filesystem(Feature):
 
3998
    """Is the filesystem UTF-8?"""
 
3999
 
 
4000
    def _probe(self):
 
4001
        if osutils._fs_enc.upper() in ('UTF-8', 'UTF8'):
 
4002
            return True
 
4003
        return False
 
4004
 
 
4005
UTF8Filesystem = _UTF8Filesystem()
 
4006
 
 
4007
 
 
4008
class _CaseInsCasePresFilenameFeature(Feature):
 
4009
    """Is the file-system case insensitive, but case-preserving?"""
 
4010
 
 
4011
    def _probe(self):
 
4012
        fileno, name = tempfile.mkstemp(prefix='MixedCase')
 
4013
        try:
 
4014
            # first check truly case-preserving for created files, then check
 
4015
            # case insensitive when opening existing files.
 
4016
            name = osutils.normpath(name)
 
4017
            base, rel = osutils.split(name)
 
4018
            found_rel = osutils.canonical_relpath(base, name)
 
4019
            return (found_rel == rel
 
4020
                    and os.path.isfile(name.upper())
 
4021
                    and os.path.isfile(name.lower()))
 
4022
        finally:
 
4023
            os.close(fileno)
 
4024
            os.remove(name)
 
4025
 
 
4026
    def feature_name(self):
 
4027
        return "case-insensitive case-preserving filesystem"
 
4028
 
 
4029
CaseInsCasePresFilenameFeature = _CaseInsCasePresFilenameFeature()
 
4030
 
 
4031
 
 
4032
class _CaseInsensitiveFilesystemFeature(Feature):
 
4033
    """Check if underlying filesystem is case-insensitive but *not* case
 
4034
    preserving.
 
4035
    """
 
4036
    # Note that on Windows, Cygwin, MacOS etc, the file-systems are far
 
4037
    # more likely to be case preserving, so this case is rare.
 
4038
 
 
4039
    def _probe(self):
 
4040
        if CaseInsCasePresFilenameFeature.available():
 
4041
            return False
 
4042
 
 
4043
        if TestCaseWithMemoryTransport.TEST_ROOT is None:
 
4044
            root = osutils.mkdtemp(prefix='testbzr-', suffix='.tmp')
 
4045
            TestCaseWithMemoryTransport.TEST_ROOT = root
 
4046
        else:
 
4047
            root = TestCaseWithMemoryTransport.TEST_ROOT
 
4048
        tdir = osutils.mkdtemp(prefix='case-sensitive-probe-', suffix='',
 
4049
            dir=root)
 
4050
        name_a = osutils.pathjoin(tdir, 'a')
 
4051
        name_A = osutils.pathjoin(tdir, 'A')
 
4052
        os.mkdir(name_a)
 
4053
        result = osutils.isdir(name_A)
 
4054
        _rmtree_temp_dir(tdir)
 
4055
        return result
 
4056
 
 
4057
    def feature_name(self):
 
4058
        return 'case-insensitive filesystem'
 
4059
 
 
4060
CaseInsensitiveFilesystemFeature = _CaseInsensitiveFilesystemFeature()
 
4061
 
 
4062
 
 
4063
class _SubUnitFeature(Feature):
 
4064
    """Check if subunit is available."""
 
4065
 
 
4066
    def _probe(self):
 
4067
        try:
 
4068
            import subunit
 
4069
            return True
 
4070
        except ImportError:
 
4071
            return False
 
4072
 
 
4073
    def feature_name(self):
 
4074
        return 'subunit'
 
4075
 
 
4076
SubUnitFeature = _SubUnitFeature()
 
4077
# Only define SubUnitBzrRunner if subunit is available.
 
4078
try:
 
4079
    from subunit import TestProtocolClient
 
4080
    try:
 
4081
        from subunit.test_results import AutoTimingTestResultDecorator
 
4082
    except ImportError:
 
4083
        AutoTimingTestResultDecorator = lambda x:x
 
4084
    class SubUnitBzrRunner(TextTestRunner):
 
4085
        def run(self, test):
 
4086
            result = AutoTimingTestResultDecorator(
 
4087
                TestProtocolClient(self.stream))
 
4088
            test.run(result)
 
4089
            return result
 
4090
except ImportError:
 
4091
    pass