~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/__init__.py

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