~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/__init__.py

  • Committer: John Arbash Meinel
  • Date: 2009-08-13 21:54:04 UTC
  • mto: This revision was merged to the branch mainline in revision 4629.
  • Revision ID: john@arbash-meinel.com-20090813215404-f1e6vemv7vxyivoe
Create the crude merge_sort implementation that just thunks over to the old implementation.
The main win here is that we get to copy across all the tests so far, and they all pass. :)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2011 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
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
 
"""Testing framework extensions"""
18
17
 
19
18
# TODO: Perhaps there should be an API to find out if bzr running under the
20
19
# test suite -- some plugins might want to avoid making intrusive changes if
29
28
 
30
29
import atexit
31
30
import codecs
32
 
import copy
33
31
from cStringIO import StringIO
34
32
import difflib
35
33
import doctest
36
34
import errno
37
 
import itertools
38
35
import logging
 
36
import math
39
37
import os
40
 
import platform
41
 
import pprint
 
38
from pprint import pformat
42
39
import random
43
40
import re
44
41
import shlex
45
42
import stat
46
 
import subprocess
 
43
from subprocess import Popen, PIPE, STDOUT
47
44
import sys
48
45
import tempfile
49
46
import threading
50
47
import time
51
 
import traceback
52
48
import unittest
53
49
import warnings
54
50
 
55
 
import testtools
56
 
# nb: check this before importing anything else from within it
57
 
_testtools_version = getattr(testtools, '__version__', ())
58
 
if _testtools_version < (0, 9, 5):
59
 
    raise ImportError("need at least testtools 0.9.5: %s is %r"
60
 
        % (testtools.__file__, _testtools_version))
61
 
from testtools import content
62
51
 
63
 
import bzrlib
64
52
from bzrlib import (
65
53
    branchbuilder,
66
54
    bzrdir,
67
 
    chk_map,
68
 
    commands as _mod_commands,
69
 
    config,
70
55
    debug,
71
56
    errors,
72
57
    hooks,
73
58
    lock as _mod_lock,
74
 
    lockdir,
75
59
    memorytree,
76
60
    osutils,
77
 
    plugin as _mod_plugin,
78
 
    pyutils,
 
61
    progress,
79
62
    ui,
80
63
    urlutils,
81
64
    registry,
82
 
    symbol_versioning,
83
 
    trace,
84
 
    transport as _mod_transport,
85
65
    workingtree,
86
66
    )
 
67
import bzrlib.branch
 
68
import bzrlib.commands
 
69
import bzrlib.timestamp
 
70
import bzrlib.export
 
71
import bzrlib.inventory
 
72
import bzrlib.iterablefile
 
73
import bzrlib.lockdir
87
74
try:
88
75
    import bzrlib.lsprof
89
76
except ImportError:
90
77
    # lsprof not available
91
78
    pass
92
 
from bzrlib.smart import client, request
93
 
from bzrlib.transport import (
94
 
    memory,
95
 
    pathfilter,
96
 
    )
97
 
from bzrlib.tests import (
98
 
    test_server,
99
 
    TestUtil,
100
 
    treeshape,
101
 
    )
 
79
from bzrlib.merge import merge_inner
 
80
import bzrlib.merge3
 
81
import bzrlib.plugin
 
82
from bzrlib.smart import client, request, server
 
83
import bzrlib.store
 
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
    )
 
91
import bzrlib.trace
 
92
from bzrlib.transport import get_transport
 
93
import bzrlib.transport
 
94
from bzrlib.transport.local import LocalURLServer
 
95
from bzrlib.transport.memory import MemoryServer
 
96
from bzrlib.transport.readonly import ReadonlyServer
 
97
from bzrlib.trace import mutter, note
 
98
from bzrlib.tests import TestUtil
 
99
from bzrlib.tests.http_server import HttpServer
 
100
from bzrlib.tests.TestUtil import (
 
101
                          TestSuite,
 
102
                          TestLoader,
 
103
                          )
 
104
from bzrlib.tests.treeshape import build_tree_contents
102
105
from bzrlib.ui import NullProgressView
103
106
from bzrlib.ui.text import TextUIFactory
 
107
import bzrlib.version_info_formats.format_custom
 
108
from bzrlib.workingtree import WorkingTree, WorkingTreeFormat2
104
109
 
105
110
# Mark this python module as being part of the implementation
106
111
# of unittest: this gives us better tracebacks where the last
107
112
# shown frame is the test code, not our assertXYZ.
108
113
__unittest = 1
109
114
 
110
 
default_transport = test_server.LocalURLServer
111
 
 
112
 
 
113
 
_unitialized_attr = object()
114
 
"""A sentinel needed to act as a default value in a method signature."""
115
 
 
 
115
default_transport = LocalURLServer
116
116
 
117
117
# Subunit result codes, defined here to prevent a hard dependency on subunit.
118
118
SUBUNIT_SEEK_SET = 0
119
119
SUBUNIT_SEEK_CUR = 1
120
120
 
121
 
# These are intentionally brought into this namespace. That way plugins, etc
122
 
# can just "from bzrlib.tests import TestCase, TestLoader, etc"
123
 
TestSuite = TestUtil.TestSuite
124
 
TestLoader = TestUtil.TestLoader
125
 
 
126
 
# Tests should run in a clean and clearly defined environment. The goal is to
127
 
# keep them isolated from the running environment as mush as possible. The test
128
 
# framework ensures the variables defined below are set (or deleted if the
129
 
# value is None) before a test is run and reset to their original value after
130
 
# the test is run. Generally if some code depends on an environment variable,
131
 
# the tests should start without this variable in the environment. There are a
132
 
# few exceptions but you shouldn't violate this rule lightly.
133
 
isolated_environ = {
134
 
    'BZR_HOME': None,
135
 
    'HOME': None,
136
 
    # bzr now uses the Win32 API and doesn't rely on APPDATA, but the
137
 
    # tests do check our impls match APPDATA
138
 
    'BZR_EDITOR': None, # test_msgeditor manipulates this variable
139
 
    'VISUAL': None,
140
 
    'EDITOR': None,
141
 
    'BZR_EMAIL': None,
142
 
    'BZREMAIL': None, # may still be present in the environment
143
 
    'EMAIL': 'jrandom@example.com', # set EMAIL as bzr does not guess
144
 
    'BZR_PROGRESS_BAR': None,
145
 
    # This should trap leaks to ~/.bzr.log. This occurs when tests use TestCase
146
 
    # as a base class instead of TestCaseInTempDir. Tests inheriting from
147
 
    # TestCase should not use disk resources, BZR_LOG is one.
148
 
    'BZR_LOG': '/you-should-use-TestCaseInTempDir-if-you-need-a-log-file',
149
 
    'BZR_PLUGIN_PATH': None,
150
 
    'BZR_DISABLE_PLUGINS': None,
151
 
    'BZR_PLUGINS_AT': None,
152
 
    'BZR_CONCURRENCY': None,
153
 
    # Make sure that any text ui tests are consistent regardless of
154
 
    # the environment the test case is run in; you may want tests that
155
 
    # test other combinations.  'dumb' is a reasonable guess for tests
156
 
    # going to a pipe or a StringIO.
157
 
    'TERM': 'dumb',
158
 
    'LINES': '25',
159
 
    'COLUMNS': '80',
160
 
    'BZR_COLUMNS': '80',
161
 
    # Disable SSH Agent
162
 
    'SSH_AUTH_SOCK': None,
163
 
    # Proxies
164
 
    'http_proxy': None,
165
 
    'HTTP_PROXY': None,
166
 
    'https_proxy': None,
167
 
    'HTTPS_PROXY': None,
168
 
    'no_proxy': None,
169
 
    'NO_PROXY': None,
170
 
    'all_proxy': None,
171
 
    'ALL_PROXY': None,
172
 
    # Nobody cares about ftp_proxy, FTP_PROXY AFAIK. So far at
173
 
    # least. If you do (care), please update this comment
174
 
    # -- vila 20080401
175
 
    'ftp_proxy': None,
176
 
    'FTP_PROXY': None,
177
 
    'BZR_REMOTE_PATH': None,
178
 
    # Generally speaking, we don't want apport reporting on crashes in
179
 
    # the test envirnoment unless we're specifically testing apport,
180
 
    # so that it doesn't leak into the real system environment.  We
181
 
    # use an env var so it propagates to subprocesses.
182
 
    'APPORT_DISABLE': '1',
183
 
    }
184
 
 
185
 
 
186
 
def override_os_environ(test, env=None):
187
 
    """Modify os.environ keeping a copy.
188
 
    
189
 
    :param test: A test instance
190
 
 
191
 
    :param env: A dict containing variable definitions to be installed
192
 
    """
193
 
    if env is None:
194
 
        env = isolated_environ
195
 
    test._original_os_environ = dict([(var, value)
196
 
                                      for var, value in os.environ.iteritems()])
197
 
    for var, value in env.iteritems():
198
 
        osutils.set_or_unset_env(var, value)
199
 
        if var not in test._original_os_environ:
200
 
            # The var is new, add it with a value of None, so
201
 
            # restore_os_environ will delete it
202
 
            test._original_os_environ[var] = None
203
 
 
204
 
 
205
 
def restore_os_environ(test):
206
 
    """Restore os.environ to its original state.
207
 
 
208
 
    :param test: A test instance previously passed to override_os_environ.
209
 
    """
210
 
    for var, value in test._original_os_environ.iteritems():
211
 
        # Restore the original value (or delete it if the value has been set to
212
 
        # None in override_os_environ).
213
 
        osutils.set_or_unset_env(var, value)
214
 
 
215
 
 
216
 
class ExtendedTestResult(testtools.TextTestResult):
 
121
 
 
122
class ExtendedTestResult(unittest._TextTestResult):
217
123
    """Accepts, reports and accumulates the results of running tests.
218
124
 
219
125
    Compared to the unittest version this class adds support for
240
146
        :param bench_history: Optionally, a writable file object to accumulate
241
147
            benchmark results.
242
148
        """
243
 
        testtools.TextTestResult.__init__(self, stream)
 
149
        unittest._TextTestResult.__init__(self, stream, descriptions, verbosity)
244
150
        if bench_history is not None:
245
151
            from bzrlib.version import _get_bzr_source_tree
246
152
            src_tree = _get_bzr_source_tree()
267
173
        self.count = 0
268
174
        self._overall_start_time = time.time()
269
175
        self._strict = strict
270
 
        self._first_thread_leaker_id = None
271
 
        self._tests_leaking_threads_count = 0
272
 
        self._traceback_from_test = None
273
176
 
274
 
    def stopTestRun(self):
275
 
        run = self.testsRun
276
 
        actionTaken = "Ran"
277
 
        stopTime = time.time()
278
 
        timeTaken = stopTime - self.startTime
279
 
        # GZ 2010-07-19: Seems testtools has no printErrors method, and though
280
 
        #                the parent class method is similar have to duplicate
281
 
        self._show_list('ERROR', self.errors)
282
 
        self._show_list('FAIL', self.failures)
283
 
        self.stream.write(self.sep2)
284
 
        self.stream.write("%s %d test%s in %.3fs\n\n" % (actionTaken,
285
 
                            run, run != 1 and "s" or "", timeTaken))
286
 
        if not self.wasSuccessful():
287
 
            self.stream.write("FAILED (")
288
 
            failed, errored = map(len, (self.failures, self.errors))
289
 
            if failed:
290
 
                self.stream.write("failures=%d" % failed)
291
 
            if errored:
292
 
                if failed: self.stream.write(", ")
293
 
                self.stream.write("errors=%d" % errored)
294
 
            if self.known_failure_count:
295
 
                if failed or errored: self.stream.write(", ")
296
 
                self.stream.write("known_failure_count=%d" %
297
 
                    self.known_failure_count)
298
 
            self.stream.write(")\n")
299
 
        else:
300
 
            if self.known_failure_count:
301
 
                self.stream.write("OK (known_failures=%d)\n" %
302
 
                    self.known_failure_count)
303
 
            else:
304
 
                self.stream.write("OK\n")
305
 
        if self.skip_count > 0:
306
 
            skipped = self.skip_count
307
 
            self.stream.write('%d test%s skipped\n' %
308
 
                                (skipped, skipped != 1 and "s" or ""))
309
 
        if self.unsupported:
310
 
            for feature, count in sorted(self.unsupported.items()):
311
 
                self.stream.write("Missing feature '%s' skipped %d tests.\n" %
312
 
                    (feature, count))
 
177
    def done(self):
 
178
        # nb: called stopTestRun in the version of this that Python merged
 
179
        # upstream, according to lifeless 20090803
313
180
        if self._strict:
314
181
            ok = self.wasStrictlySuccessful()
315
182
        else:
316
183
            ok = self.wasSuccessful()
317
 
        if self._first_thread_leaker_id:
 
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:
318
189
            self.stream.write(
319
190
                '%s is leaking threads among %d leaking tests.\n' % (
320
 
                self._first_thread_leaker_id,
321
 
                self._tests_leaking_threads_count))
322
 
            # We don't report the main thread as an active one.
323
 
            self.stream.write(
324
 
                '%d non-main threads were left active in the end.\n'
325
 
                % (len(self._active_threads) - 1))
326
 
 
327
 
    def getDescription(self, test):
328
 
        return test.id()
329
 
 
330
 
    def _extractBenchmarkTime(self, testCase, details=None):
 
191
                TestCase._first_thread_leaker_id,
 
192
                TestCase._leaking_threads_tests))
 
193
 
 
194
    def _extractBenchmarkTime(self, testCase):
331
195
        """Add a benchmark time for the current test case."""
332
 
        if details and 'benchtime' in details:
333
 
            return float(''.join(details['benchtime'].iter_bytes()))
334
196
        return getattr(testCase, "_benchtime", None)
335
197
 
336
198
    def _elapsedTestTimeString(self):
337
199
        """Return a time string for the overall time the current test has taken."""
338
 
        return self._formatTime(self._delta_to_float(
339
 
            self._now() - self._start_datetime))
 
200
        return self._formatTime(time.time() - self._start_time)
340
201
 
341
202
    def _testTimeString(self, testCase):
342
203
        benchmark_time = self._extractBenchmarkTime(testCase)
353
214
 
354
215
    def _shortened_test_description(self, test):
355
216
        what = test.id()
356
 
        what = re.sub(r'^bzrlib\.tests\.', '', what)
 
217
        what = re.sub(r'^bzrlib\.(tests|benchmarks)\.', '', what)
357
218
        return what
358
219
 
359
 
    # GZ 2010-10-04: Cloned tests may end up harmlessly calling this method
360
 
    #                multiple times in a row, because the handler is added for
361
 
    #                each test but the container list is shared between cases.
362
 
    #                See lp:498869 lp:625574 and lp:637725 for background.
363
 
    def _record_traceback_from_test(self, exc_info):
364
 
        """Store the traceback from passed exc_info tuple till"""
365
 
        self._traceback_from_test = exc_info[2]
366
 
 
367
220
    def startTest(self, test):
368
 
        super(ExtendedTestResult, self).startTest(test)
 
221
        unittest.TestResult.startTest(self, test)
369
222
        if self.count == 0:
370
223
            self.startTests()
371
 
        self.count += 1
372
224
        self.report_test_start(test)
373
225
        test.number = self.count
374
226
        self._recordTestStartTime()
375
 
        # Make testtools cases give us the real traceback on failure
376
 
        addOnException = getattr(test, "addOnException", None)
377
 
        if addOnException is not None:
378
 
            addOnException(self._record_traceback_from_test)
379
 
        # Only check for thread leaks on bzrlib derived test cases
380
 
        if isinstance(test, TestCase):
381
 
            test.addCleanup(self._check_leaked_threads, test)
382
 
 
383
 
    def stopTest(self, test):
384
 
        super(ExtendedTestResult, self).stopTest(test)
385
 
        # Manually break cycles, means touching various private things but hey
386
 
        getDetails = getattr(test, "getDetails", None)
387
 
        if getDetails is not None:
388
 
            getDetails().clear()
389
 
        type_equality_funcs = getattr(test, "_type_equality_funcs", None)
390
 
        if type_equality_funcs is not None:
391
 
            type_equality_funcs.clear()
392
 
        self._traceback_from_test = None
393
227
 
394
228
    def startTests(self):
395
 
        self.report_tests_starting()
396
 
        self._active_threads = threading.enumerate()
397
 
 
398
 
    def _check_leaked_threads(self, test):
399
 
        """See if any threads have leaked since last call
400
 
 
401
 
        A sample of live threads is stored in the _active_threads attribute,
402
 
        when this method runs it compares the current live threads and any not
403
 
        in the previous sample are treated as having leaked.
404
 
        """
405
 
        now_active_threads = set(threading.enumerate())
406
 
        threads_leaked = now_active_threads.difference(self._active_threads)
407
 
        if threads_leaked:
408
 
            self._report_thread_leak(test, threads_leaked, now_active_threads)
409
 
            self._tests_leaking_threads_count += 1
410
 
            if self._first_thread_leaker_id is None:
411
 
                self._first_thread_leaker_id = test.id()
412
 
            self._active_threads = now_active_threads
 
229
        self.stream.write(
 
230
            'testing: %s\n' % (osutils.realpath(sys.argv[0]),))
 
231
        self.stream.write(
 
232
            '   %s (%s python%s)\n' % (
 
233
                    bzrlib.__path__[0],
 
234
                    bzrlib.version_string,
 
235
                    bzrlib._format_version_tuple(sys.version_info),
 
236
                    ))
 
237
        self.stream.write('\n')
413
238
 
414
239
    def _recordTestStartTime(self):
415
240
        """Record that a test has started."""
416
 
        self._start_datetime = self._now()
 
241
        self._start_time = time.time()
 
242
 
 
243
    def _cleanupLogFile(self, test):
 
244
        # We can only do this if we have one of our TestCases, not if
 
245
        # we have a doctest.
 
246
        setKeepLogfile = getattr(test, 'setKeepLogfile', None)
 
247
        if setKeepLogfile is not None:
 
248
            setKeepLogfile()
417
249
 
418
250
    def addError(self, test, err):
419
251
        """Tell result that test finished with an error.
421
253
        Called from the TestCase run() method when the test
422
254
        fails with an unexpected error.
423
255
        """
424
 
        self._post_mortem(self._traceback_from_test)
425
 
        super(ExtendedTestResult, self).addError(test, err)
426
 
        self.error_count += 1
427
 
        self.report_error(test, err)
428
 
        if self.stop_early:
429
 
            self.stop()
 
256
        self._testConcluded(test)
 
257
        if isinstance(err[1], TestNotApplicable):
 
258
            return self._addNotApplicable(test, err)
 
259
        elif isinstance(err[1], UnavailableFeature):
 
260
            return self.addNotSupported(test, err[1].args[0])
 
261
        else:
 
262
            unittest.TestResult.addError(self, test, err)
 
263
            self.error_count += 1
 
264
            self.report_error(test, err)
 
265
            if self.stop_early:
 
266
                self.stop()
 
267
            self._cleanupLogFile(test)
430
268
 
431
269
    def addFailure(self, test, err):
432
270
        """Tell result that test failed.
434
272
        Called from the TestCase run() method when the test
435
273
        fails because e.g. an assert() method failed.
436
274
        """
437
 
        self._post_mortem(self._traceback_from_test)
438
 
        super(ExtendedTestResult, self).addFailure(test, err)
439
 
        self.failure_count += 1
440
 
        self.report_failure(test, err)
441
 
        if self.stop_early:
442
 
            self.stop()
 
275
        self._testConcluded(test)
 
276
        if isinstance(err[1], KnownFailure):
 
277
            return self._addKnownFailure(test, err)
 
278
        else:
 
279
            unittest.TestResult.addFailure(self, test, err)
 
280
            self.failure_count += 1
 
281
            self.report_failure(test, err)
 
282
            if self.stop_early:
 
283
                self.stop()
 
284
            self._cleanupLogFile(test)
443
285
 
444
 
    def addSuccess(self, test, details=None):
 
286
    def addSuccess(self, test):
445
287
        """Tell result that test completed successfully.
446
288
 
447
289
        Called from the TestCase run()
448
290
        """
 
291
        self._testConcluded(test)
449
292
        if self._bench_history is not None:
450
 
            benchmark_time = self._extractBenchmarkTime(test, details)
 
293
            benchmark_time = self._extractBenchmarkTime(test)
451
294
            if benchmark_time is not None:
452
295
                self._bench_history.write("%s %s\n" % (
453
296
                    self._formatTime(benchmark_time),
454
297
                    test.id()))
455
298
        self.report_success(test)
456
 
        super(ExtendedTestResult, self).addSuccess(test)
 
299
        self._cleanupLogFile(test)
 
300
        unittest.TestResult.addSuccess(self, test)
457
301
        test._log_contents = ''
458
302
 
459
 
    def addExpectedFailure(self, test, err):
 
303
    def _testConcluded(self, test):
 
304
        """Common code when a test has finished.
 
305
 
 
306
        Called regardless of whether it succeded, failed, etc.
 
307
        """
 
308
        pass
 
309
 
 
310
    def _addKnownFailure(self, test, err):
460
311
        self.known_failure_count += 1
461
312
        self.report_known_failure(test, err)
462
313
 
463
 
    def addUnexpectedSuccess(self, test, details=None):
464
 
        """Tell result the test unexpectedly passed, counting as a failure
465
 
 
466
 
        When the minimum version of testtools required becomes 0.9.8 this
467
 
        can be updated to use the new handling there.
468
 
        """
469
 
        super(ExtendedTestResult, self).addFailure(test, details=details)
470
 
        self.failure_count += 1
471
 
        self.report_unexpected_success(test,
472
 
            "".join(details["reason"].iter_text()))
473
 
        if self.stop_early:
474
 
            self.stop()
475
 
 
476
314
    def addNotSupported(self, test, feature):
477
315
        """The test will not be run because of a missing feature.
478
316
        """
479
317
        # this can be called in two different ways: it may be that the
480
 
        # test started running, and then raised (through requireFeature)
 
318
        # test started running, and then raised (through addError)
481
319
        # UnavailableFeature.  Alternatively this method can be called
482
 
        # while probing for features before running the test code proper; in
483
 
        # that case we will see startTest and stopTest, but the test will
484
 
        # never actually run.
 
320
        # while probing for features before running the tests; in that
 
321
        # case we will see startTest and stopTest, but the test will never
 
322
        # actually run.
485
323
        self.unsupported.setdefault(str(feature), 0)
486
324
        self.unsupported[str(feature)] += 1
487
325
        self.report_unsupported(test, feature)
491
329
        self.skip_count += 1
492
330
        self.report_skip(test, reason)
493
331
 
494
 
    def addNotApplicable(self, test, reason):
495
 
        self.not_applicable_count += 1
496
 
        self.report_not_applicable(test, reason)
 
332
    def _addNotApplicable(self, test, skip_excinfo):
 
333
        if isinstance(skip_excinfo[1], TestNotApplicable):
 
334
            self.not_applicable_count += 1
 
335
            self.report_not_applicable(test, skip_excinfo)
 
336
        try:
 
337
            test.tearDown()
 
338
        except KeyboardInterrupt:
 
339
            raise
 
340
        except:
 
341
            self.addError(test, test.exc_info())
 
342
        else:
 
343
            # seems best to treat this as success from point-of-view of unittest
 
344
            # -- it actually does nothing so it barely matters :)
 
345
            unittest.TestResult.addSuccess(self, test)
 
346
            test._log_contents = ''
497
347
 
498
 
    def _post_mortem(self, tb=None):
499
 
        """Start a PDB post mortem session."""
500
 
        if os.environ.get('BZR_TEST_PDB', None):
501
 
            import pdb
502
 
            pdb.post_mortem(tb)
 
348
    def printErrorList(self, flavour, errors):
 
349
        for test, err in errors:
 
350
            self.stream.writeln(self.separator1)
 
351
            self.stream.write("%s: " % flavour)
 
352
            self.stream.writeln(self.getDescription(test))
 
353
            if getattr(test, '_get_log', None) is not None:
 
354
                log_contents = test._get_log()
 
355
                if log_contents:
 
356
                    self.stream.write('\n')
 
357
                    self.stream.write(
 
358
                            ('vvvv[log from %s]' % test.id()).ljust(78,'-'))
 
359
                    self.stream.write('\n')
 
360
                    self.stream.write(log_contents)
 
361
                    self.stream.write('\n')
 
362
                    self.stream.write(
 
363
                            ('^^^^[log from %s]' % test.id()).ljust(78,'-'))
 
364
                    self.stream.write('\n')
 
365
            self.stream.writeln(self.separator2)
 
366
            self.stream.writeln("%s" % err)
503
367
 
504
368
    def progress(self, offset, whence):
505
369
        """The test is adjusting the count of tests to run."""
510
374
        else:
511
375
            raise errors.BzrError("Unknown whence %r" % whence)
512
376
 
513
 
    def report_tests_starting(self):
514
 
        """Display information before the test run begins"""
515
 
        if getattr(sys, 'frozen', None) is None:
516
 
            bzr_path = osutils.realpath(sys.argv[0])
517
 
        else:
518
 
            bzr_path = sys.executable
519
 
        self.stream.write(
520
 
            'bzr selftest: %s\n' % (bzr_path,))
521
 
        self.stream.write(
522
 
            '   %s\n' % (
523
 
                    bzrlib.__path__[0],))
524
 
        self.stream.write(
525
 
            '   bzr-%s python-%s %s\n' % (
526
 
                    bzrlib.version_string,
527
 
                    bzrlib._format_version_tuple(sys.version_info),
528
 
                    platform.platform(aliased=1),
529
 
                    ))
530
 
        self.stream.write('\n')
531
 
 
532
 
    def report_test_start(self, test):
533
 
        """Display information on the test just about to be run"""
534
 
 
535
 
    def _report_thread_leak(self, test, leaked_threads, active_threads):
536
 
        """Display information on a test that leaked one or more threads"""
537
 
        # GZ 2010-09-09: A leak summary reported separately from the general
538
 
        #                thread debugging would be nice. Tests under subunit
539
 
        #                need something not using stream, perhaps adding a
540
 
        #                testtools details object would be fitting.
541
 
        if 'threads' in selftest_debug_flags:
542
 
            self.stream.write('%s is leaking, active is now %d\n' %
543
 
                (test.id(), len(active_threads)))
544
 
 
545
 
    def startTestRun(self):
546
 
        self.startTime = time.time()
 
377
    def finished(self):
 
378
        pass
 
379
 
 
380
    def report_cleaning_up(self):
 
381
        pass
547
382
 
548
383
    def report_success(self, test):
549
384
        pass
577
412
        self.pb.update_latency = 0
578
413
        self.pb.show_transport_activity = False
579
414
 
580
 
    def stopTestRun(self):
 
415
    def done(self):
581
416
        # called when the tests that are going to run have run
582
417
        self.pb.clear()
 
418
        super(TextTestResult, self).done()
 
419
 
 
420
    def finished(self):
583
421
        self.pb.finished()
584
 
        super(TextTestResult, self).stopTestRun()
585
422
 
586
 
    def report_tests_starting(self):
587
 
        super(TextTestResult, self).report_tests_starting()
 
423
    def report_starting(self):
588
424
        self.pb.update('[test 0/%d] Starting' % (self.num_tests))
589
425
 
 
426
    def printErrors(self):
 
427
        # clear the pb to make room for the error listing
 
428
        self.pb.clear()
 
429
        super(TextTestResult, self).printErrors()
 
430
 
590
431
    def _progress_prefix_text(self):
591
432
        # the longer this text, the less space we have to show the test
592
433
        # name...
605
446
            a += '%dm%ds' % (runtime / 60, runtime % 60)
606
447
        else:
607
448
            a += '%ds' % runtime
608
 
        total_fail_count = self.error_count + self.failure_count
609
 
        if total_fail_count:
610
 
            a += ', %d failed' % total_fail_count
611
 
        # if self.unsupported:
612
 
        #     a += ', %d missing' % len(self.unsupported)
 
449
        if self.error_count:
 
450
            a += ', %d err' % self.error_count
 
451
        if self.failure_count:
 
452
            a += ', %d fail' % self.failure_count
 
453
        if self.unsupported:
 
454
            a += ', %d missing' % len(self.unsupported)
613
455
        a += ']'
614
456
        return a
615
457
 
616
458
    def report_test_start(self, test):
 
459
        self.count += 1
617
460
        self.pb.update(
618
461
                self._progress_prefix_text()
619
462
                + ' '
623
466
        return self._shortened_test_description(test)
624
467
 
625
468
    def report_error(self, test, err):
626
 
        self.stream.write('ERROR: %s\n    %s\n' % (
 
469
        self.pb.note('ERROR: %s\n    %s\n',
627
470
            self._test_description(test),
628
471
            err[1],
629
 
            ))
 
472
            )
630
473
 
631
474
    def report_failure(self, test, err):
632
 
        self.stream.write('FAIL: %s\n    %s\n' % (
 
475
        self.pb.note('FAIL: %s\n    %s\n',
633
476
            self._test_description(test),
634
477
            err[1],
635
 
            ))
 
478
            )
636
479
 
637
480
    def report_known_failure(self, test, err):
638
 
        pass
639
 
 
640
 
    def report_unexpected_success(self, test, reason):
641
 
        self.stream.write('FAIL: %s\n    %s: %s\n' % (
642
 
            self._test_description(test),
643
 
            "Unexpected success. Should have failed",
644
 
            reason,
645
 
            ))
 
481
        self.pb.note('XFAIL: %s\n%s\n',
 
482
            self._test_description(test), err[1])
646
483
 
647
484
    def report_skip(self, test, reason):
648
485
        pass
649
486
 
650
 
    def report_not_applicable(self, test, reason):
 
487
    def report_not_applicable(self, test, skip_excinfo):
651
488
        pass
652
489
 
653
490
    def report_unsupported(self, test, feature):
654
491
        """test cannot be run because feature is missing."""
655
492
 
 
493
    def report_cleaning_up(self):
 
494
        self.pb.update('Cleaning up')
 
495
 
656
496
 
657
497
class VerboseTestResult(ExtendedTestResult):
658
498
    """Produce long output, with one line per test run plus times"""
665
505
            result = a_string
666
506
        return result.ljust(final_width)
667
507
 
668
 
    def report_tests_starting(self):
 
508
    def report_starting(self):
669
509
        self.stream.write('running %d tests...\n' % self.num_tests)
670
 
        super(VerboseTestResult, self).report_tests_starting()
671
510
 
672
511
    def report_test_start(self, test):
 
512
        self.count += 1
673
513
        name = self._shortened_test_description(test)
674
 
        width = osutils.terminal_width()
675
 
        if width is not None:
676
 
            # width needs space for 6 char status, plus 1 for slash, plus an
677
 
            # 11-char time string, plus a trailing blank
678
 
            # when NUMBERED_DIRS: plus 5 chars on test number, plus 1 char on
679
 
            # space
680
 
            self.stream.write(self._ellipsize_to_right(name, width-18))
681
 
        else:
682
 
            self.stream.write(name)
 
514
        # width needs space for 6 char status, plus 1 for slash, plus an
 
515
        # 11-char time string, plus a trailing blank
 
516
        # when NUMBERED_DIRS: plus 5 chars on test number, plus 1 char on space
 
517
        self.stream.write(self._ellipsize_to_right(name,
 
518
                          osutils.terminal_width()-18))
683
519
        self.stream.flush()
684
520
 
685
521
    def _error_summary(self, err):
687
523
        return '%s%s' % (indent, err[1])
688
524
 
689
525
    def report_error(self, test, err):
690
 
        self.stream.write('ERROR %s\n%s\n'
 
526
        self.stream.writeln('ERROR %s\n%s'
691
527
                % (self._testTimeString(test),
692
528
                   self._error_summary(err)))
693
529
 
694
530
    def report_failure(self, test, err):
695
 
        self.stream.write(' FAIL %s\n%s\n'
 
531
        self.stream.writeln(' FAIL %s\n%s'
696
532
                % (self._testTimeString(test),
697
533
                   self._error_summary(err)))
698
534
 
699
535
    def report_known_failure(self, test, err):
700
 
        self.stream.write('XFAIL %s\n%s\n'
 
536
        self.stream.writeln('XFAIL %s\n%s'
701
537
                % (self._testTimeString(test),
702
538
                   self._error_summary(err)))
703
539
 
704
 
    def report_unexpected_success(self, test, reason):
705
 
        self.stream.write(' FAIL %s\n%s: %s\n'
706
 
                % (self._testTimeString(test),
707
 
                   "Unexpected success. Should have failed",
708
 
                   reason))
709
 
 
710
540
    def report_success(self, test):
711
 
        self.stream.write('   OK %s\n' % self._testTimeString(test))
 
541
        self.stream.writeln('   OK %s' % self._testTimeString(test))
712
542
        for bench_called, stats in getattr(test, '_benchcalls', []):
713
 
            self.stream.write('LSProf output for %s(%s, %s)\n' % bench_called)
 
543
            self.stream.writeln('LSProf output for %s(%s, %s)' % bench_called)
714
544
            stats.pprint(file=self.stream)
715
545
        # flush the stream so that we get smooth output. This verbose mode is
716
546
        # used to show the output in PQM.
717
547
        self.stream.flush()
718
548
 
719
549
    def report_skip(self, test, reason):
720
 
        self.stream.write(' SKIP %s\n%s\n'
 
550
        self.stream.writeln(' SKIP %s\n%s'
721
551
                % (self._testTimeString(test), reason))
722
552
 
723
 
    def report_not_applicable(self, test, reason):
724
 
        self.stream.write('  N/A %s\n    %s\n'
725
 
                % (self._testTimeString(test), reason))
 
553
    def report_not_applicable(self, test, skip_excinfo):
 
554
        self.stream.writeln('  N/A %s\n%s'
 
555
                % (self._testTimeString(test),
 
556
                   self._error_summary(skip_excinfo)))
726
557
 
727
558
    def report_unsupported(self, test, feature):
728
559
        """test cannot be run because feature is missing."""
729
 
        self.stream.write("NODEP %s\n    The feature '%s' is not available.\n"
 
560
        self.stream.writeln("NODEP %s\n    The feature '%s' is not available."
730
561
                %(self._testTimeString(test), feature))
731
562
 
732
563
 
738
569
                 descriptions=0,
739
570
                 verbosity=1,
740
571
                 bench_history=None,
 
572
                 list_only=False,
741
573
                 strict=False,
742
 
                 result_decorators=None,
743
574
                 ):
744
 
        """Create a TextTestRunner.
745
 
 
746
 
        :param result_decorators: An optional list of decorators to apply
747
 
            to the result object being used by the runner. Decorators are
748
 
            applied left to right - the first element in the list is the 
749
 
            innermost decorator.
750
 
        """
751
 
        # stream may know claim to know to write unicode strings, but in older
752
 
        # pythons this goes sufficiently wrong that it is a bad idea. (
753
 
        # specifically a built in file with encoding 'UTF-8' will still try
754
 
        # to encode using ascii.
755
 
        new_encoding = osutils.get_terminal_encoding()
756
 
        codec = codecs.lookup(new_encoding)
757
 
        if type(codec) is tuple:
758
 
            # Python 2.4
759
 
            encode = codec[0]
760
 
        else:
761
 
            encode = codec.encode
762
 
        # GZ 2010-09-08: Really we don't want to be writing arbitrary bytes,
763
 
        #                so should swap to the plain codecs.StreamWriter
764
 
        stream = osutils.UnicodeOrBytesToBytesWriter(encode, stream,
765
 
            "backslashreplace")
766
 
        stream.encoding = new_encoding
767
 
        self.stream = stream
 
575
        self.stream = unittest._WritelnDecorator(stream)
768
576
        self.descriptions = descriptions
769
577
        self.verbosity = verbosity
770
578
        self._bench_history = bench_history
 
579
        self.list_only = list_only
771
580
        self._strict = strict
772
 
        self._result_decorators = result_decorators or []
773
581
 
774
582
    def run(self, test):
775
583
        "Run the given test case or test suite."
 
584
        startTime = time.time()
776
585
        if self.verbosity == 1:
777
586
            result_class = TextTestResult
778
587
        elif self.verbosity >= 2:
779
588
            result_class = VerboseTestResult
780
 
        original_result = result_class(self.stream,
 
589
        result = result_class(self.stream,
781
590
                              self.descriptions,
782
591
                              self.verbosity,
783
592
                              bench_history=self._bench_history,
784
593
                              strict=self._strict,
785
594
                              )
786
 
        # Signal to result objects that look at stop early policy to stop,
787
 
        original_result.stop_early = self.stop_on_failure
788
 
        result = original_result
789
 
        for decorator in self._result_decorators:
790
 
            result = decorator(result)
791
 
            result.stop_early = self.stop_on_failure
792
 
        result.startTestRun()
793
 
        try:
794
 
            test.run(result)
795
 
        finally:
796
 
            result.stopTestRun()
797
 
        # higher level code uses our extended protocol to determine
798
 
        # what exit code to give.
799
 
        return original_result
 
595
        result.stop_early = self.stop_on_failure
 
596
        result.report_starting()
 
597
        if self.list_only:
 
598
            if self.verbosity >= 2:
 
599
                self.stream.writeln("Listing tests only ...\n")
 
600
            run = 0
 
601
            for t in iter_suite_tests(test):
 
602
                self.stream.writeln("%s" % (t.id()))
 
603
                run += 1
 
604
            return None
 
605
        else:
 
606
            try:
 
607
                import testtools
 
608
            except ImportError:
 
609
                test.run(result)
 
610
            else:
 
611
                if isinstance(test, testtools.ConcurrentTestSuite):
 
612
                    # We need to catch bzr specific behaviors
 
613
                    test.run(BZRTransformingResult(result))
 
614
                else:
 
615
                    test.run(result)
 
616
            run = result.testsRun
 
617
            actionTaken = "Ran"
 
618
        stopTime = time.time()
 
619
        timeTaken = stopTime - startTime
 
620
        result.printErrors()
 
621
        self.stream.writeln(result.separator2)
 
622
        self.stream.writeln("%s %d test%s in %.3fs" % (actionTaken,
 
623
                            run, run != 1 and "s" or "", timeTaken))
 
624
        self.stream.writeln()
 
625
        if not result.wasSuccessful():
 
626
            self.stream.write("FAILED (")
 
627
            failed, errored = map(len, (result.failures, result.errors))
 
628
            if failed:
 
629
                self.stream.write("failures=%d" % failed)
 
630
            if errored:
 
631
                if failed: self.stream.write(", ")
 
632
                self.stream.write("errors=%d" % errored)
 
633
            if result.known_failure_count:
 
634
                if failed or errored: self.stream.write(", ")
 
635
                self.stream.write("known_failure_count=%d" %
 
636
                    result.known_failure_count)
 
637
            self.stream.writeln(")")
 
638
        else:
 
639
            if result.known_failure_count:
 
640
                self.stream.writeln("OK (known_failures=%d)" %
 
641
                    result.known_failure_count)
 
642
            else:
 
643
                self.stream.writeln("OK")
 
644
        if result.skip_count > 0:
 
645
            skipped = result.skip_count
 
646
            self.stream.writeln('%d test%s skipped' %
 
647
                                (skipped, skipped != 1 and "s" or ""))
 
648
        if result.unsupported:
 
649
            for feature, count in sorted(result.unsupported.items()):
 
650
                self.stream.writeln("Missing feature '%s' skipped %d tests." %
 
651
                    (feature, count))
 
652
        result.finished()
 
653
        return result
800
654
 
801
655
 
802
656
def iter_suite_tests(suite):
812
666
                        % (type(suite), suite))
813
667
 
814
668
 
815
 
TestSkipped = testtools.testcase.TestSkipped
 
669
class TestSkipped(Exception):
 
670
    """Indicates that a test was intentionally skipped, rather than failing."""
816
671
 
817
672
 
818
673
class TestNotApplicable(TestSkipped):
824
679
    """
825
680
 
826
681
 
827
 
# traceback._some_str fails to format exceptions that have the default
828
 
# __str__ which does an implicit ascii conversion. However, repr() on those
829
 
# objects works, for all that its not quite what the doctor may have ordered.
830
 
def _clever_some_str(value):
831
 
    try:
832
 
        return str(value)
833
 
    except:
834
 
        try:
835
 
            return repr(value).replace('\\n', '\n')
836
 
        except:
837
 
            return '<unprintable %s object>' % type(value).__name__
838
 
 
839
 
traceback._some_str = _clever_some_str
840
 
 
841
 
 
842
 
# deprecated - use self.knownFailure(), or self.expectFailure.
843
 
KnownFailure = testtools.testcase._ExpectedFailure
 
682
class KnownFailure(AssertionError):
 
683
    """Indicates that a test failed in a precisely expected manner.
 
684
 
 
685
    Such failures dont block the whole test suite from passing because they are
 
686
    indicators of partially completed code or of future work. We have an
 
687
    explicit error for them so that we can ensure that they are always visible:
 
688
    KnownFailures are always shown in the output of bzr selftest.
 
689
    """
844
690
 
845
691
 
846
692
class UnavailableFeature(Exception):
847
693
    """A feature required for this test was not available.
848
694
 
849
 
    This can be considered a specialised form of SkippedTest.
850
 
 
851
695
    The feature should be used to construct the exception.
852
696
    """
853
697
 
854
698
 
 
699
class CommandFailed(Exception):
 
700
    pass
 
701
 
 
702
 
855
703
class StringIOWrapper(object):
856
704
    """A wrapper around cStringIO which just adds an encoding attribute.
857
705
 
894
742
    # XXX: Should probably unify more with CannedInputUIFactory or a
895
743
    # particular configuration of TextUIFactory, or otherwise have a clearer
896
744
    # idea of how they're supposed to be different.
897
 
    # See https://bugs.launchpad.net/bzr/+bug/408213
 
745
    # See https://bugs.edge.launchpad.net/bzr/+bug/408213
898
746
 
899
747
    def __init__(self, stdout=None, stderr=None, stdin=None):
900
748
        if stdin is not None:
918
766
        return NullProgressView()
919
767
 
920
768
 
921
 
def isolated_doctest_setUp(test):
922
 
    override_os_environ(test)
923
 
 
924
 
 
925
 
def isolated_doctest_tearDown(test):
926
 
    restore_os_environ(test)
927
 
 
928
 
 
929
 
def IsolatedDocTestSuite(*args, **kwargs):
930
 
    """Overrides doctest.DocTestSuite to handle isolation.
931
 
 
932
 
    The method is really a factory and users are expected to use it as such.
933
 
    """
934
 
 
935
 
    kwargs['setUp'] = isolated_doctest_setUp
936
 
    kwargs['tearDown'] = isolated_doctest_tearDown
937
 
    return doctest.DocTestSuite(*args, **kwargs)
938
 
 
939
 
 
940
 
class TestCase(testtools.TestCase):
 
769
class TestCase(unittest.TestCase):
941
770
    """Base class for bzr unit tests.
942
771
 
943
772
    Tests that need access to disk resources should subclass
953
782
    routine, and to build and check bzr trees.
954
783
 
955
784
    In addition to the usual method of overriding tearDown(), this class also
956
 
    allows subclasses to register cleanup functions via addCleanup, which are
 
785
    allows subclasses to register functions into the _cleanups list, which is
957
786
    run in order as the object is torn down.  It's less likely this will be
958
787
    accidentally overlooked.
959
788
    """
960
789
 
961
 
    _log_file = None
 
790
    _active_threads = None
 
791
    _leaking_threads_tests = 0
 
792
    _first_thread_leaker_id = None
 
793
    _log_file_name = None
 
794
    _log_contents = ''
 
795
    _keep_log_file = False
962
796
    # record lsprof data when performing benchmark calls.
963
797
    _gather_lsprof_in_benchmarks = False
 
798
    attrs_to_keep = ('id', '_testMethodName', '_testMethodDoc',
 
799
                     '_log_contents', '_log_file_name', '_benchtime',
 
800
                     '_TestCase__testMethodName', '_TestCase__testMethodDoc',)
964
801
 
965
802
    def __init__(self, methodName='testMethod'):
966
803
        super(TestCase, self).__init__(methodName)
967
 
        self._directory_isolation = True
968
 
        self.exception_handlers.insert(0,
969
 
            (UnavailableFeature, self._do_unsupported_or_skip))
970
 
        self.exception_handlers.insert(0,
971
 
            (TestNotApplicable, self._do_not_applicable))
 
804
        self._cleanups = []
 
805
        self._bzr_test_setUp_run = False
 
806
        self._bzr_test_tearDown_run = False
972
807
 
973
808
    def setUp(self):
974
 
        super(TestCase, self).setUp()
975
 
        for feature in getattr(self, '_test_needs_features', []):
976
 
            self.requireFeature(feature)
 
809
        unittest.TestCase.setUp(self)
 
810
        self._bzr_test_setUp_run = True
977
811
        self._cleanEnvironment()
978
812
        self._silenceUI()
979
813
        self._startLogFile()
980
814
        self._benchcalls = []
981
815
        self._benchtime = None
982
816
        self._clear_hooks()
983
 
        self._track_transports()
 
817
        # Track locks - needs to be called before _clear_debug_flags.
984
818
        self._track_locks()
985
819
        self._clear_debug_flags()
986
 
        # Isolate global verbosity level, to make sure it's reproducible
987
 
        # between tests.  We should get rid of this altogether: bug 656694. --
988
 
        # mbp 20101008
989
 
        self.overrideAttr(bzrlib.trace, '_verbosity_level', 0)
990
 
        # Isolate config option expansion until its default value for bzrlib is
991
 
        # settled on or a the FIXME associated with _get_expand_default_value
992
 
        # is addressed -- vila 20110219
993
 
        self.overrideAttr(config, '_expand_default_value', None)
994
 
        self._log_files = set()
995
 
        # Each key in the ``_counters`` dict holds a value for a different
996
 
        # counter. When the test ends, addDetail() should be used to output the
997
 
        # counter values. This happens in install_counter_hook().
998
 
        self._counters = {}
999
 
        if 'config_stats' in selftest_debug_flags:
1000
 
            self._install_config_stats_hooks()
 
820
        TestCase._active_threads = threading.activeCount()
 
821
        self.addCleanup(self._check_leaked_threads)
1001
822
 
1002
823
    def debug(self):
1003
824
        # debug a frame up.
1004
825
        import pdb
1005
826
        pdb.Pdb().set_trace(sys._getframe().f_back)
1006
827
 
1007
 
    def discardDetail(self, name):
1008
 
        """Extend the addDetail, getDetails api so we can remove a detail.
1009
 
 
1010
 
        eg. bzr always adds the 'log' detail at startup, but we don't want to
1011
 
        include it for skipped, xfail, etc tests.
1012
 
 
1013
 
        It is safe to call this for a detail that doesn't exist, in case this
1014
 
        gets called multiple times.
1015
 
        """
1016
 
        # We cheat. details is stored in __details which means we shouldn't
1017
 
        # touch it. but getDetails() returns the dict directly, so we can
1018
 
        # mutate it.
1019
 
        details = self.getDetails()
1020
 
        if name in details:
1021
 
            del details[name]
1022
 
 
1023
 
    def install_counter_hook(self, hooks, name, counter_name=None):
1024
 
        """Install a counting hook.
1025
 
 
1026
 
        Any hook can be counted as long as it doesn't need to return a value.
1027
 
 
1028
 
        :param hooks: Where the hook should be installed.
1029
 
 
1030
 
        :param name: The hook name that will be counted.
1031
 
 
1032
 
        :param counter_name: The counter identifier in ``_counters``, defaults
1033
 
            to ``name``.
1034
 
        """
1035
 
        _counters = self._counters # Avoid closing over self
1036
 
        if counter_name is None:
1037
 
            counter_name = name
1038
 
        if _counters.has_key(counter_name):
1039
 
            raise AssertionError('%s is already used as a counter name'
1040
 
                                  % (counter_name,))
1041
 
        _counters[counter_name] = 0
1042
 
        self.addDetail(counter_name, content.Content(content.UTF8_TEXT,
1043
 
            lambda: ['%d' % (_counters[counter_name],)]))
1044
 
        def increment_counter(*args, **kwargs):
1045
 
            _counters[counter_name] += 1
1046
 
        label = 'count %s calls' % (counter_name,)
1047
 
        hooks.install_named_hook(name, increment_counter, label)
1048
 
        self.addCleanup(hooks.uninstall_named_hook, name, label)
1049
 
 
1050
 
    def _install_config_stats_hooks(self):
1051
 
        """Install config hooks to count hook calls.
1052
 
 
1053
 
        """
1054
 
        for hook_name in ('get', 'set', 'remove', 'load', 'save'):
1055
 
            self.install_counter_hook(config.ConfigHooks, hook_name,
1056
 
                                       'config.%s' % (hook_name,))
1057
 
 
1058
 
        # The OldConfigHooks are private and need special handling to protect
1059
 
        # against recursive tests (tests that run other tests), so we just do
1060
 
        # manually what registering them into _builtin_known_hooks will provide
1061
 
        # us.
1062
 
        self.overrideAttr(config, 'OldConfigHooks', config._OldConfigHooks())
1063
 
        for hook_name in ('get', 'set', 'remove', 'load', 'save'):
1064
 
            self.install_counter_hook(config.OldConfigHooks, hook_name,
1065
 
                                      'old_config.%s' % (hook_name,))
 
828
    def _check_leaked_threads(self):
 
829
        active = threading.activeCount()
 
830
        leaked_threads = active - TestCase._active_threads
 
831
        TestCase._active_threads = active
 
832
        if leaked_threads:
 
833
            TestCase._leaking_threads_tests += 1
 
834
            if TestCase._first_thread_leaker_id is None:
 
835
                TestCase._first_thread_leaker_id = self.id()
1066
836
 
1067
837
    def _clear_debug_flags(self):
1068
838
        """Prevent externally set debug flags affecting tests.
1070
840
        Tests that want to use debug flags can just set them in the
1071
841
        debug_flags set during setup/teardown.
1072
842
        """
1073
 
        # Start with a copy of the current debug flags we can safely modify.
1074
 
        self.overrideAttr(debug, 'debug_flags', set(debug.debug_flags))
 
843
        self._preserved_debug_flags = set(debug.debug_flags)
1075
844
        if 'allow_debug' not in selftest_debug_flags:
1076
845
            debug.debug_flags.clear()
1077
 
        if 'disable_lock_checks' not in selftest_debug_flags:
1078
 
            debug.debug_flags.add('strict_locks')
 
846
        self.addCleanup(self._restore_debug_flags)
1079
847
 
1080
848
    def _clear_hooks(self):
1081
849
        # prevent hooks affecting tests
1082
 
        known_hooks = hooks.known_hooks
1083
850
        self._preserved_hooks = {}
1084
 
        for key, (parent, name) in known_hooks.iter_parent_objects():
1085
 
            current_hooks = getattr(parent, name)
 
851
        for key, factory in hooks.known_hooks.items():
 
852
            parent, name = hooks.known_hooks_key_to_parent_and_attribute(key)
 
853
            current_hooks = hooks.known_hooks_key_to_object(key)
1086
854
            self._preserved_hooks[parent] = (name, current_hooks)
1087
 
        self._preserved_lazy_hooks = hooks._lazy_hooks
1088
 
        hooks._lazy_hooks = {}
1089
855
        self.addCleanup(self._restoreHooks)
1090
 
        for key, (parent, name) in known_hooks.iter_parent_objects():
1091
 
            factory = known_hooks.get(key)
 
856
        for key, factory in hooks.known_hooks.items():
 
857
            parent, name = hooks.known_hooks_key_to_parent_and_attribute(key)
1092
858
            setattr(parent, name, factory())
1093
859
        # this hook should always be installed
1094
860
        request._install_hook()
1095
861
 
1096
 
    def disable_directory_isolation(self):
1097
 
        """Turn off directory isolation checks."""
1098
 
        self._directory_isolation = False
1099
 
 
1100
 
    def enable_directory_isolation(self):
1101
 
        """Enable directory isolation checks."""
1102
 
        self._directory_isolation = True
1103
 
 
1104
862
    def _silenceUI(self):
1105
863
        """Turn off UI for duration of test"""
1106
864
        # by default the UI is off; tests can turn it on if they want it.
1107
 
        self.overrideAttr(ui, 'ui_factory', ui.SilentUIFactory())
 
865
        saved = ui.ui_factory
 
866
        def _restore():
 
867
            ui.ui_factory = saved
 
868
        ui.ui_factory = ui.SilentUIFactory()
 
869
        self.addCleanup(_restore)
1108
870
 
1109
871
    def _check_locks(self):
1110
872
        """Check that all lock take/release actions have been paired."""
1111
 
        # We always check for mismatched locks. If a mismatch is found, we
1112
 
        # fail unless -Edisable_lock_checks is supplied to selftest, in which
1113
 
        # case we just print a warning.
 
873
        # once we have fixed all the current lock problems, we can change the
 
874
        # following code to always check for mismatched locks, but only do
 
875
        # traceback showing with -Dlock (self._lock_check_thorough is True).
 
876
        # For now, because the test suite will fail, we only assert that lock
 
877
        # matching has occured with -Dlock.
1114
878
        # unhook:
1115
879
        acquired_locks = [lock for action, lock in self._lock_actions
1116
880
                          if action == 'acquired']
1123
887
        # break some locks on purpose and should be taken into account by
1124
888
        # considering that breaking a lock is just a dirty way of releasing it.
1125
889
        if len(acquired_locks) != (len(released_locks) + len(broken_locks)):
1126
 
            message = (
1127
 
                'Different number of acquired and '
1128
 
                'released or broken locks.\n'
1129
 
                'acquired=%s\n'
1130
 
                'released=%s\n'
1131
 
                'broken=%s\n' %
1132
 
                (acquired_locks, released_locks, broken_locks))
 
890
            message = ('Different number of acquired and '
 
891
                       'released or broken locks. (%s, %s + %s)' %
 
892
                       (acquired_locks, released_locks, broken_locks))
1133
893
            if not self._lock_check_thorough:
1134
894
                # Rather than fail, just warn
1135
895
                print "Broken test %s: %s" % (self, message)
1139
899
    def _track_locks(self):
1140
900
        """Track lock activity during tests."""
1141
901
        self._lock_actions = []
1142
 
        if 'disable_lock_checks' in selftest_debug_flags:
1143
 
            self._lock_check_thorough = False
1144
 
        else:
1145
 
            self._lock_check_thorough = True
1146
 
 
 
902
        self._lock_check_thorough = 'lock' not in debug.debug_flags
1147
903
        self.addCleanup(self._check_locks)
1148
904
        _mod_lock.Lock.hooks.install_named_hook('lock_acquired',
1149
905
                                                self._lock_acquired, None)
1161
917
    def _lock_broken(self, result):
1162
918
        self._lock_actions.append(('broken', result))
1163
919
 
1164
 
    def permit_dir(self, name):
1165
 
        """Permit a directory to be used by this test. See permit_url."""
1166
 
        name_transport = _mod_transport.get_transport(name)
1167
 
        self.permit_url(name)
1168
 
        self.permit_url(name_transport.base)
1169
 
 
1170
 
    def permit_url(self, url):
1171
 
        """Declare that url is an ok url to use in this test.
1172
 
        
1173
 
        Do this for memory transports, temporary test directory etc.
1174
 
        
1175
 
        Do not do this for the current working directory, /tmp, or any other
1176
 
        preexisting non isolated url.
1177
 
        """
1178
 
        if not url.endswith('/'):
1179
 
            url += '/'
1180
 
        self._bzr_selftest_roots.append(url)
1181
 
 
1182
 
    def permit_source_tree_branch_repo(self):
1183
 
        """Permit the source tree bzr is running from to be opened.
1184
 
 
1185
 
        Some code such as bzrlib.version attempts to read from the bzr branch
1186
 
        that bzr is executing from (if any). This method permits that directory
1187
 
        to be used in the test suite.
1188
 
        """
1189
 
        path = self.get_source_path()
1190
 
        self.record_directory_isolation()
1191
 
        try:
1192
 
            try:
1193
 
                workingtree.WorkingTree.open(path)
1194
 
            except (errors.NotBranchError, errors.NoWorkingTree):
1195
 
                raise TestSkipped('Needs a working tree of bzr sources')
1196
 
        finally:
1197
 
            self.enable_directory_isolation()
1198
 
 
1199
 
    def _preopen_isolate_transport(self, transport):
1200
 
        """Check that all transport openings are done in the test work area."""
1201
 
        while isinstance(transport, pathfilter.PathFilteringTransport):
1202
 
            # Unwrap pathfiltered transports
1203
 
            transport = transport.server.backing_transport.clone(
1204
 
                transport._filter('.'))
1205
 
        url = transport.base
1206
 
        # ReadonlySmartTCPServer_for_testing decorates the backing transport
1207
 
        # urls it is given by prepending readonly+. This is appropriate as the
1208
 
        # client shouldn't know that the server is readonly (or not readonly).
1209
 
        # We could register all servers twice, with readonly+ prepending, but
1210
 
        # that makes for a long list; this is about the same but easier to
1211
 
        # read.
1212
 
        if url.startswith('readonly+'):
1213
 
            url = url[len('readonly+'):]
1214
 
        self._preopen_isolate_url(url)
1215
 
 
1216
 
    def _preopen_isolate_url(self, url):
1217
 
        if not self._directory_isolation:
1218
 
            return
1219
 
        if self._directory_isolation == 'record':
1220
 
            self._bzr_selftest_roots.append(url)
1221
 
            return
1222
 
        # This prevents all transports, including e.g. sftp ones backed on disk
1223
 
        # from working unless they are explicitly granted permission. We then
1224
 
        # depend on the code that sets up test transports to check that they are
1225
 
        # appropriately isolated and enable their use by calling
1226
 
        # self.permit_transport()
1227
 
        if not osutils.is_inside_any(self._bzr_selftest_roots, url):
1228
 
            raise errors.BzrError("Attempt to escape test isolation: %r %r"
1229
 
                % (url, self._bzr_selftest_roots))
1230
 
 
1231
 
    def record_directory_isolation(self):
1232
 
        """Gather accessed directories to permit later access.
1233
 
        
1234
 
        This is used for tests that access the branch bzr is running from.
1235
 
        """
1236
 
        self._directory_isolation = "record"
1237
 
 
1238
 
    def start_server(self, transport_server, backing_server=None):
1239
 
        """Start transport_server for this test.
1240
 
 
1241
 
        This starts the server, registers a cleanup for it and permits the
1242
 
        server's urls to be used.
1243
 
        """
1244
 
        if backing_server is None:
1245
 
            transport_server.start_server()
1246
 
        else:
1247
 
            transport_server.start_server(backing_server)
1248
 
        self.addCleanup(transport_server.stop_server)
1249
 
        # Obtain a real transport because if the server supplies a password, it
1250
 
        # will be hidden from the base on the client side.
1251
 
        t = _mod_transport.get_transport(transport_server.get_url())
1252
 
        # Some transport servers effectively chroot the backing transport;
1253
 
        # others like SFTPServer don't - users of the transport can walk up the
1254
 
        # transport to read the entire backing transport. This wouldn't matter
1255
 
        # except that the workdir tests are given - and that they expect the
1256
 
        # server's url to point at - is one directory under the safety net. So
1257
 
        # Branch operations into the transport will attempt to walk up one
1258
 
        # directory. Chrooting all servers would avoid this but also mean that
1259
 
        # we wouldn't be testing directly against non-root urls. Alternatively
1260
 
        # getting the test framework to start the server with a backing server
1261
 
        # at the actual safety net directory would work too, but this then
1262
 
        # means that the self.get_url/self.get_transport methods would need
1263
 
        # to transform all their results. On balance its cleaner to handle it
1264
 
        # here, and permit a higher url when we have one of these transports.
1265
 
        if t.base.endswith('/work/'):
1266
 
            # we have safety net/test root/work
1267
 
            t = t.clone('../..')
1268
 
        elif isinstance(transport_server,
1269
 
                        test_server.SmartTCPServer_for_testing):
1270
 
            # The smart server adds a path similar to work, which is traversed
1271
 
            # up from by the client. But the server is chrooted - the actual
1272
 
            # backing transport is not escaped from, and VFS requests to the
1273
 
            # root will error (because they try to escape the chroot).
1274
 
            t2 = t.clone('..')
1275
 
            while t2.base != t.base:
1276
 
                t = t2
1277
 
                t2 = t.clone('..')
1278
 
        self.permit_url(t.base)
1279
 
 
1280
 
    def _track_transports(self):
1281
 
        """Install checks for transport usage."""
1282
 
        # TestCase has no safe place it can write to.
1283
 
        self._bzr_selftest_roots = []
1284
 
        # Currently the easiest way to be sure that nothing is going on is to
1285
 
        # hook into bzr dir opening. This leaves a small window of error for
1286
 
        # transport tests, but they are well known, and we can improve on this
1287
 
        # step.
1288
 
        bzrdir.BzrDir.hooks.install_named_hook("pre_open",
1289
 
            self._preopen_isolate_transport, "Check bzr directories are safe.")
1290
 
 
1291
920
    def _ndiff_strings(self, a, b):
1292
921
        """Return ndiff between two strings containing lines.
1293
922
 
1310
939
        except UnicodeError, e:
1311
940
            # If we can't compare without getting a UnicodeError, then
1312
941
            # obviously they are different
1313
 
            trace.mutter('UnicodeError: %s', e)
 
942
            mutter('UnicodeError: %s', e)
1314
943
        if message:
1315
944
            message += '\n'
1316
945
        raise AssertionError("%snot equal:\na = %s\nb = %s\n"
1317
946
            % (message,
1318
 
               pprint.pformat(a), pprint.pformat(b)))
 
947
               pformat(a), pformat(b)))
1319
948
 
1320
949
    assertEquals = assertEqual
1321
950
 
1330
959
            return
1331
960
        if message is None:
1332
961
            message = "texts not equal:\n"
 
962
        if a == b + '\n':
 
963
            message = 'first string is missing a final newline.\n'
1333
964
        if a + '\n' == b:
1334
 
            message = 'first string is missing a final newline.\n'
1335
 
        if a == b + '\n':
1336
965
            message = 'second string is missing a final newline.\n'
1337
966
        raise AssertionError(message +
1338
967
                             self._ndiff_strings(a, b))
1349
978
        :raises AssertionError: If the expected and actual stat values differ
1350
979
            other than by atime.
1351
980
        """
1352
 
        self.assertEqual(expected.st_size, actual.st_size,
1353
 
                         'st_size did not match')
1354
 
        self.assertEqual(expected.st_mtime, actual.st_mtime,
1355
 
                         'st_mtime did not match')
1356
 
        self.assertEqual(expected.st_ctime, actual.st_ctime,
1357
 
                         'st_ctime did not match')
1358
 
        if sys.platform == 'win32':
1359
 
            # On Win32 both 'dev' and 'ino' cannot be trusted. In python2.4 it
1360
 
            # is 'dev' that varies, in python 2.5 (6?) it is st_ino that is
1361
 
            # odd. We just force it to always be 0 to avoid any problems.
1362
 
            self.assertEqual(0, expected.st_dev)
1363
 
            self.assertEqual(0, actual.st_dev)
1364
 
            self.assertEqual(0, expected.st_ino)
1365
 
            self.assertEqual(0, actual.st_ino)
1366
 
        else:
1367
 
            self.assertEqual(expected.st_dev, actual.st_dev,
1368
 
                             'st_dev did not match')
1369
 
            self.assertEqual(expected.st_ino, actual.st_ino,
1370
 
                             'st_ino did not match')
1371
 
        self.assertEqual(expected.st_mode, actual.st_mode,
1372
 
                         'st_mode did not match')
 
981
        self.assertEqual(expected.st_size, actual.st_size)
 
982
        self.assertEqual(expected.st_mtime, actual.st_mtime)
 
983
        self.assertEqual(expected.st_ctime, actual.st_ctime)
 
984
        self.assertEqual(expected.st_dev, actual.st_dev)
 
985
        self.assertEqual(expected.st_ino, actual.st_ino)
 
986
        self.assertEqual(expected.st_mode, actual.st_mode)
1373
987
 
1374
988
    def assertLength(self, length, obj_with_len):
1375
989
        """Assert that obj_with_len is of length length."""
1377
991
            self.fail("Incorrect length: wanted %d, got %d for %r" % (
1378
992
                length, len(obj_with_len), obj_with_len))
1379
993
 
1380
 
    def assertLogsError(self, exception_class, func, *args, **kwargs):
1381
 
        """Assert that `func(*args, **kwargs)` quietly logs a specific error.
1382
 
        """
1383
 
        captured = []
1384
 
        orig_log_exception_quietly = trace.log_exception_quietly
1385
 
        try:
1386
 
            def capture():
1387
 
                orig_log_exception_quietly()
1388
 
                captured.append(sys.exc_info()[1])
1389
 
            trace.log_exception_quietly = capture
1390
 
            func(*args, **kwargs)
1391
 
        finally:
1392
 
            trace.log_exception_quietly = orig_log_exception_quietly
1393
 
        self.assertLength(1, captured)
1394
 
        err = captured[0]
1395
 
        self.assertIsInstance(err, exception_class)
1396
 
        return err
1397
 
 
1398
994
    def assertPositive(self, val):
1399
995
        """Assert that val is greater than 0."""
1400
996
        self.assertTrue(val > 0, 'expected a positive value, but got %s' % val)
1430
1026
            raise AssertionError('pattern "%s" found in "%s"'
1431
1027
                    % (needle_re, haystack))
1432
1028
 
1433
 
    def assertContainsString(self, haystack, needle):
1434
 
        if haystack.find(needle) == -1:
1435
 
            self.fail("string %r not found in '''%s'''" % (needle, haystack))
1436
 
 
1437
 
    def assertNotContainsString(self, haystack, needle):
1438
 
        if haystack.find(needle) != -1:
1439
 
            self.fail("string %r found in '''%s'''" % (needle, haystack))
1440
 
 
1441
1029
    def assertSubset(self, sublist, superlist):
1442
1030
        """Assert that every entry in sublist is present in superlist."""
1443
1031
        missing = set(sublist) - set(superlist)
1530
1118
                m += ": " + msg
1531
1119
            self.fail(m)
1532
1120
 
 
1121
    def expectFailure(self, reason, assertion, *args, **kwargs):
 
1122
        """Invoke a test, expecting it to fail for the given reason.
 
1123
 
 
1124
        This is for assertions that ought to succeed, but currently fail.
 
1125
        (The failure is *expected* but not *wanted*.)  Please be very precise
 
1126
        about the failure you're expecting.  If a new bug is introduced,
 
1127
        AssertionError should be raised, not KnownFailure.
 
1128
 
 
1129
        Frequently, expectFailure should be followed by an opposite assertion.
 
1130
        See example below.
 
1131
 
 
1132
        Intended to be used with a callable that raises AssertionError as the
 
1133
        'assertion' parameter.  args and kwargs are passed to the 'assertion'.
 
1134
 
 
1135
        Raises KnownFailure if the test fails.  Raises AssertionError if the
 
1136
        test succeeds.
 
1137
 
 
1138
        example usage::
 
1139
 
 
1140
          self.expectFailure('Math is broken', self.assertNotEqual, 54,
 
1141
                             dynamic_val)
 
1142
          self.assertEqual(42, dynamic_val)
 
1143
 
 
1144
          This means that a dynamic_val of 54 will cause the test to raise
 
1145
          a KnownFailure.  Once math is fixed and the expectFailure is removed,
 
1146
          only a dynamic_val of 42 will allow the test to pass.  Anything other
 
1147
          than 54 or 42 will cause an AssertionError.
 
1148
        """
 
1149
        try:
 
1150
            assertion(*args, **kwargs)
 
1151
        except AssertionError:
 
1152
            raise KnownFailure(reason)
 
1153
        else:
 
1154
            self.fail('Unexpected success.  Should have failed: %s' % reason)
 
1155
 
1533
1156
    def assertFileEqual(self, content, path):
1534
1157
        """Fail if path does not contain 'content'."""
1535
 
        self.assertPathExists(path)
 
1158
        self.failUnlessExists(path)
1536
1159
        f = file(path, 'rb')
1537
1160
        try:
1538
1161
            s = f.read()
1540
1163
            f.close()
1541
1164
        self.assertEqualDiff(content, s)
1542
1165
 
1543
 
    def assertDocstring(self, expected_docstring, obj):
1544
 
        """Fail if obj does not have expected_docstring"""
1545
 
        if __doc__ is None:
1546
 
            # With -OO the docstring should be None instead
1547
 
            self.assertIs(obj.__doc__, None)
1548
 
        else:
1549
 
            self.assertEqual(expected_docstring, obj.__doc__)
1550
 
 
1551
 
    @symbol_versioning.deprecated_method(symbol_versioning.deprecated_in((2, 4)))
1552
1166
    def failUnlessExists(self, path):
1553
 
        return self.assertPathExists(path)
1554
 
 
1555
 
    def assertPathExists(self, path):
1556
1167
        """Fail unless path or paths, which may be abs or relative, exist."""
1557
1168
        if not isinstance(path, basestring):
1558
1169
            for p in path:
1559
 
                self.assertPathExists(p)
 
1170
                self.failUnlessExists(p)
1560
1171
        else:
1561
 
            self.assertTrue(osutils.lexists(path),
1562
 
                path + " does not exist")
 
1172
            self.failUnless(osutils.lexists(path),path+" does not exist")
1563
1173
 
1564
 
    @symbol_versioning.deprecated_method(symbol_versioning.deprecated_in((2, 4)))
1565
1174
    def failIfExists(self, path):
1566
 
        return self.assertPathDoesNotExist(path)
1567
 
 
1568
 
    def assertPathDoesNotExist(self, path):
1569
1175
        """Fail if path or paths, which may be abs or relative, exist."""
1570
1176
        if not isinstance(path, basestring):
1571
1177
            for p in path:
1572
 
                self.assertPathDoesNotExist(p)
 
1178
                self.failIfExists(p)
1573
1179
        else:
1574
 
            self.assertFalse(osutils.lexists(path),
1575
 
                path + " exists")
 
1180
            self.failIf(osutils.lexists(path),path+" exists")
1576
1181
 
1577
1182
    def _capture_deprecation_warnings(self, a_callable, *args, **kwargs):
1578
1183
        """A helper for callDeprecated and applyDeprecated.
1604
1209
        not other callers that go direct to the warning module.
1605
1210
 
1606
1211
        To test that a deprecated method raises an error, do something like
1607
 
        this (remember that both assertRaises and applyDeprecated delays *args
1608
 
        and **kwargs passing)::
 
1212
        this::
1609
1213
 
1610
1214
            self.assertRaises(errors.ReservedId,
1611
1215
                self.applyDeprecated,
1693
1297
 
1694
1298
        The file is removed as the test is torn down.
1695
1299
        """
1696
 
        pseudo_log_file = StringIO()
1697
 
        def _get_log_contents_for_weird_testtools_api():
1698
 
            return [pseudo_log_file.getvalue().decode(
1699
 
                "utf-8", "replace").encode("utf-8")]
1700
 
        self.addDetail("log", content.Content(content.ContentType("text",
1701
 
            "plain", {"charset": "utf8"}),
1702
 
            _get_log_contents_for_weird_testtools_api))
1703
 
        self._log_file = pseudo_log_file
1704
 
        self._log_memento = trace.push_log_file(self._log_file)
 
1300
        fileno, name = tempfile.mkstemp(suffix='.log', prefix='testbzr')
 
1301
        self._log_file = os.fdopen(fileno, 'w+')
 
1302
        self._log_memento = bzrlib.trace.push_log_file(self._log_file)
 
1303
        self._log_file_name = name
1705
1304
        self.addCleanup(self._finishLogFile)
1706
1305
 
1707
1306
    def _finishLogFile(self):
1708
1307
        """Finished with the log file.
1709
1308
 
1710
 
        Close the file and delete it.
1711
 
        """
1712
 
        if trace._trace_file:
1713
 
            # flush the log file, to get all content
1714
 
            trace._trace_file.flush()
1715
 
        trace.pop_log_file(self._log_memento)
1716
 
 
1717
 
    def thisFailsStrictLockCheck(self):
1718
 
        """It is known that this test would fail with -Dstrict_locks.
1719
 
 
1720
 
        By default, all tests are run with strict lock checking unless
1721
 
        -Edisable_lock_checks is supplied. However there are some tests which
1722
 
        we know fail strict locks at this point that have not been fixed.
1723
 
        They should call this function to disable the strict checking.
1724
 
 
1725
 
        This should be used sparingly, it is much better to fix the locking
1726
 
        issues rather than papering over the problem by calling this function.
1727
 
        """
1728
 
        debug.debug_flags.discard('strict_locks')
1729
 
 
1730
 
    def overrideAttr(self, obj, attr_name, new=_unitialized_attr):
1731
 
        """Overrides an object attribute restoring it after the test.
1732
 
 
1733
 
        :param obj: The object that will be mutated.
1734
 
 
1735
 
        :param attr_name: The attribute name we want to preserve/override in
1736
 
            the object.
1737
 
 
1738
 
        :param new: The optional value we want to set the attribute to.
1739
 
 
1740
 
        :returns: The actual attr value.
1741
 
        """
1742
 
        value = getattr(obj, attr_name)
1743
 
        # The actual value is captured by the call below
1744
 
        self.addCleanup(setattr, obj, attr_name, value)
1745
 
        if new is not _unitialized_attr:
1746
 
            setattr(obj, attr_name, new)
1747
 
        return value
1748
 
 
1749
 
    def overrideEnv(self, name, new):
1750
 
        """Set an environment variable, and reset it after the test.
1751
 
 
1752
 
        :param name: The environment variable name.
1753
 
 
1754
 
        :param new: The value to set the variable to. If None, the 
1755
 
            variable is deleted from the environment.
1756
 
 
1757
 
        :returns: The actual variable value.
1758
 
        """
1759
 
        value = osutils.set_or_unset_env(name, new)
1760
 
        self.addCleanup(osutils.set_or_unset_env, name, value)
1761
 
        return value
 
1309
        Close the file and delete it, unless setKeepLogfile was called.
 
1310
        """
 
1311
        if self._log_file is None:
 
1312
            return
 
1313
        bzrlib.trace.pop_log_file(self._log_memento)
 
1314
        self._log_file.close()
 
1315
        self._log_file = None
 
1316
        if not self._keep_log_file:
 
1317
            os.remove(self._log_file_name)
 
1318
            self._log_file_name = None
 
1319
 
 
1320
    def setKeepLogfile(self):
 
1321
        """Make the logfile not be deleted when _finishLogFile is called."""
 
1322
        self._keep_log_file = True
 
1323
 
 
1324
    def addCleanup(self, callable, *args, **kwargs):
 
1325
        """Arrange to run a callable when this case is torn down.
 
1326
 
 
1327
        Callables are run in the reverse of the order they are registered,
 
1328
        ie last-in first-out.
 
1329
        """
 
1330
        self._cleanups.append((callable, args, kwargs))
1762
1331
 
1763
1332
    def _cleanEnvironment(self):
1764
 
        for name, value in isolated_environ.iteritems():
1765
 
            self.overrideEnv(name, value)
 
1333
        new_env = {
 
1334
            'BZR_HOME': None, # Don't inherit BZR_HOME to all the tests.
 
1335
            'HOME': os.getcwd(),
 
1336
            # bzr now uses the Win32 API and doesn't rely on APPDATA, but the
 
1337
            # tests do check our impls match APPDATA
 
1338
            'BZR_EDITOR': None, # test_msgeditor manipulates this variable
 
1339
            'VISUAL': None,
 
1340
            'EDITOR': None,
 
1341
            'BZR_EMAIL': None,
 
1342
            'BZREMAIL': None, # may still be present in the environment
 
1343
            'EMAIL': None,
 
1344
            'BZR_PROGRESS_BAR': None,
 
1345
            'BZR_LOG': None,
 
1346
            'BZR_PLUGIN_PATH': None,
 
1347
            # Make sure that any text ui tests are consistent regardless of
 
1348
            # the environment the test case is run in; you may want tests that
 
1349
            # test other combinations.  'dumb' is a reasonable guess for tests
 
1350
            # going to a pipe or a StringIO.
 
1351
            'TERM': 'dumb',
 
1352
            'LINES': '25',
 
1353
            'COLUMNS': '80',
 
1354
            # SSH Agent
 
1355
            'SSH_AUTH_SOCK': None,
 
1356
            # Proxies
 
1357
            'http_proxy': None,
 
1358
            'HTTP_PROXY': None,
 
1359
            'https_proxy': None,
 
1360
            'HTTPS_PROXY': None,
 
1361
            'no_proxy': None,
 
1362
            'NO_PROXY': None,
 
1363
            'all_proxy': None,
 
1364
            'ALL_PROXY': None,
 
1365
            # Nobody cares about ftp_proxy, FTP_PROXY AFAIK. So far at
 
1366
            # least. If you do (care), please update this comment
 
1367
            # -- vila 20080401
 
1368
            'ftp_proxy': None,
 
1369
            'FTP_PROXY': None,
 
1370
            'BZR_REMOTE_PATH': None,
 
1371
        }
 
1372
        self.__old_env = {}
 
1373
        self.addCleanup(self._restoreEnvironment)
 
1374
        for name, value in new_env.iteritems():
 
1375
            self._captureVar(name, value)
 
1376
 
 
1377
    def _captureVar(self, name, newvalue):
 
1378
        """Set an environment variable, and reset it when finished."""
 
1379
        self.__old_env[name] = osutils.set_or_unset_env(name, newvalue)
 
1380
 
 
1381
    def _restore_debug_flags(self):
 
1382
        debug.debug_flags.clear()
 
1383
        debug.debug_flags.update(self._preserved_debug_flags)
 
1384
 
 
1385
    def _restoreEnvironment(self):
 
1386
        for name, value in self.__old_env.iteritems():
 
1387
            osutils.set_or_unset_env(name, value)
1766
1388
 
1767
1389
    def _restoreHooks(self):
1768
1390
        for klass, (name, hooks) in self._preserved_hooks.items():
1769
1391
            setattr(klass, name, hooks)
1770
 
        self._preserved_hooks.clear()
1771
 
        bzrlib.hooks._lazy_hooks = self._preserved_lazy_hooks
1772
 
        self._preserved_lazy_hooks.clear()
1773
1392
 
1774
1393
    def knownFailure(self, reason):
1775
1394
        """This test has failed for some known reason."""
1776
1395
        raise KnownFailure(reason)
1777
1396
 
1778
 
    def _suppress_log(self):
1779
 
        """Remove the log info from details."""
1780
 
        self.discardDetail('log')
1781
 
 
1782
1397
    def _do_skip(self, result, reason):
1783
 
        self._suppress_log()
1784
1398
        addSkip = getattr(result, 'addSkip', None)
1785
1399
        if not callable(addSkip):
1786
 
            result.addSuccess(result)
 
1400
            result.addError(self, sys.exc_info())
1787
1401
        else:
1788
1402
            addSkip(self, reason)
1789
1403
 
1790
 
    @staticmethod
1791
 
    def _do_known_failure(self, result, e):
1792
 
        self._suppress_log()
1793
 
        err = sys.exc_info()
1794
 
        addExpectedFailure = getattr(result, 'addExpectedFailure', None)
1795
 
        if addExpectedFailure is not None:
1796
 
            addExpectedFailure(self, err)
1797
 
        else:
1798
 
            result.addSuccess(self)
1799
 
 
1800
 
    @staticmethod
1801
 
    def _do_not_applicable(self, result, e):
1802
 
        if not e.args:
1803
 
            reason = 'No reason given'
1804
 
        else:
1805
 
            reason = e.args[0]
1806
 
        self._suppress_log ()
1807
 
        addNotApplicable = getattr(result, 'addNotApplicable', None)
1808
 
        if addNotApplicable is not None:
1809
 
            result.addNotApplicable(self, reason)
1810
 
        else:
1811
 
            self._do_skip(result, reason)
1812
 
 
1813
 
    @staticmethod
1814
 
    def _report_skip(self, result, err):
1815
 
        """Override the default _report_skip.
1816
 
 
1817
 
        We want to strip the 'log' detail. If we waint until _do_skip, it has
1818
 
        already been formatted into the 'reason' string, and we can't pull it
1819
 
        out again.
1820
 
        """
1821
 
        self._suppress_log()
1822
 
        super(TestCase, self)._report_skip(self, result, err)
1823
 
 
1824
 
    @staticmethod
1825
 
    def _report_expected_failure(self, result, err):
1826
 
        """Strip the log.
1827
 
 
1828
 
        See _report_skip for motivation.
1829
 
        """
1830
 
        self._suppress_log()
1831
 
        super(TestCase, self)._report_expected_failure(self, result, err)
1832
 
 
1833
 
    @staticmethod
1834
 
    def _do_unsupported_or_skip(self, result, e):
1835
 
        reason = e.args[0]
1836
 
        self._suppress_log()
1837
 
        addNotSupported = getattr(result, 'addNotSupported', None)
1838
 
        if addNotSupported is not None:
1839
 
            result.addNotSupported(self, reason)
1840
 
        else:
1841
 
            self._do_skip(result, reason)
 
1404
    def run(self, result=None):
 
1405
        if result is None: result = self.defaultTestResult()
 
1406
        for feature in getattr(self, '_test_needs_features', []):
 
1407
            if not feature.available():
 
1408
                result.startTest(self)
 
1409
                if getattr(result, 'addNotSupported', None):
 
1410
                    result.addNotSupported(self, feature)
 
1411
                else:
 
1412
                    result.addSuccess(self)
 
1413
                result.stopTest(self)
 
1414
                return result
 
1415
        try:
 
1416
            try:
 
1417
                result.startTest(self)
 
1418
                absent_attr = object()
 
1419
                # Python 2.5
 
1420
                method_name = getattr(self, '_testMethodName', absent_attr)
 
1421
                if method_name is absent_attr:
 
1422
                    # Python 2.4
 
1423
                    method_name = getattr(self, '_TestCase__testMethodName')
 
1424
                testMethod = getattr(self, method_name)
 
1425
                try:
 
1426
                    try:
 
1427
                        self.setUp()
 
1428
                        if not self._bzr_test_setUp_run:
 
1429
                            self.fail(
 
1430
                                "test setUp did not invoke "
 
1431
                                "bzrlib.tests.TestCase's setUp")
 
1432
                    except KeyboardInterrupt:
 
1433
                        self._runCleanups()
 
1434
                        raise
 
1435
                    except TestSkipped, e:
 
1436
                        self._do_skip(result, e.args[0])
 
1437
                        self.tearDown()
 
1438
                        return result
 
1439
                    except:
 
1440
                        result.addError(self, sys.exc_info())
 
1441
                        self._runCleanups()
 
1442
                        return result
 
1443
 
 
1444
                    ok = False
 
1445
                    try:
 
1446
                        testMethod()
 
1447
                        ok = True
 
1448
                    except self.failureException:
 
1449
                        result.addFailure(self, sys.exc_info())
 
1450
                    except TestSkipped, e:
 
1451
                        if not e.args:
 
1452
                            reason = "No reason given."
 
1453
                        else:
 
1454
                            reason = e.args[0]
 
1455
                        self._do_skip(result, reason)
 
1456
                    except KeyboardInterrupt:
 
1457
                        self._runCleanups()
 
1458
                        raise
 
1459
                    except:
 
1460
                        result.addError(self, sys.exc_info())
 
1461
 
 
1462
                    try:
 
1463
                        self.tearDown()
 
1464
                        if not self._bzr_test_tearDown_run:
 
1465
                            self.fail(
 
1466
                                "test tearDown did not invoke "
 
1467
                                "bzrlib.tests.TestCase's tearDown")
 
1468
                    except KeyboardInterrupt:
 
1469
                        self._runCleanups()
 
1470
                        raise
 
1471
                    except:
 
1472
                        result.addError(self, sys.exc_info())
 
1473
                        self._runCleanups()
 
1474
                        ok = False
 
1475
                    if ok: result.addSuccess(self)
 
1476
                finally:
 
1477
                    result.stopTest(self)
 
1478
                return result
 
1479
            except TestNotApplicable:
 
1480
                # Not moved from the result [yet].
 
1481
                self._runCleanups()
 
1482
                raise
 
1483
            except KeyboardInterrupt:
 
1484
                self._runCleanups()
 
1485
                raise
 
1486
        finally:
 
1487
            saved_attrs = {}
 
1488
            for attr_name in self.attrs_to_keep:
 
1489
                if attr_name in self.__dict__:
 
1490
                    saved_attrs[attr_name] = self.__dict__[attr_name]
 
1491
            self.__dict__ = saved_attrs
 
1492
 
 
1493
    def tearDown(self):
 
1494
        self._runCleanups()
 
1495
        self._log_contents = ''
 
1496
        self._bzr_test_tearDown_run = True
 
1497
        unittest.TestCase.tearDown(self)
1842
1498
 
1843
1499
    def time(self, callable, *args, **kwargs):
1844
1500
        """Run callable and accrue the time it takes to the benchmark time.
1848
1504
        self._benchcalls.
1849
1505
        """
1850
1506
        if self._benchtime is None:
1851
 
            self.addDetail('benchtime', content.Content(content.ContentType(
1852
 
                "text", "plain"), lambda:[str(self._benchtime)]))
1853
1507
            self._benchtime = 0
1854
1508
        start = time.time()
1855
1509
        try:
1864
1518
        finally:
1865
1519
            self._benchtime += time.time() - start
1866
1520
 
 
1521
    def _runCleanups(self):
 
1522
        """Run registered cleanup functions.
 
1523
 
 
1524
        This should only be called from TestCase.tearDown.
 
1525
        """
 
1526
        # TODO: Perhaps this should keep running cleanups even if
 
1527
        # one of them fails?
 
1528
 
 
1529
        # Actually pop the cleanups from the list so tearDown running
 
1530
        # twice is safe (this happens for skipped tests).
 
1531
        while self._cleanups:
 
1532
            cleanup, args, kwargs = self._cleanups.pop()
 
1533
            cleanup(*args, **kwargs)
 
1534
 
1867
1535
    def log(self, *args):
1868
 
        trace.mutter(*args)
1869
 
 
1870
 
    def get_log(self):
1871
 
        """Get a unicode string containing the log from bzrlib.trace.
1872
 
 
1873
 
        Undecodable characters are replaced.
 
1536
        mutter(*args)
 
1537
 
 
1538
    def _get_log(self, keep_log_file=False):
 
1539
        """Get the log from bzrlib.trace calls from this test.
 
1540
 
 
1541
        :param keep_log_file: When True, if the log is still a file on disk
 
1542
            leave it as a file on disk. When False, if the log is still a file
 
1543
            on disk, the log file is deleted and the log preserved as
 
1544
            self._log_contents.
 
1545
        :return: A string containing the log.
1874
1546
        """
1875
 
        return u"".join(self.getDetails()['log'].iter_text())
 
1547
        # flush the log file, to get all content
 
1548
        import bzrlib.trace
 
1549
        if bzrlib.trace._trace_file:
 
1550
            bzrlib.trace._trace_file.flush()
 
1551
        if self._log_contents:
 
1552
            # XXX: this can hardly contain the content flushed above --vila
 
1553
            # 20080128
 
1554
            return self._log_contents
 
1555
        if self._log_file_name is not None:
 
1556
            logfile = open(self._log_file_name)
 
1557
            try:
 
1558
                log_contents = logfile.read()
 
1559
            finally:
 
1560
                logfile.close()
 
1561
            if not keep_log_file:
 
1562
                self._log_contents = log_contents
 
1563
                try:
 
1564
                    os.remove(self._log_file_name)
 
1565
                except OSError, e:
 
1566
                    if sys.platform == 'win32' and e.errno == errno.EACCES:
 
1567
                        sys.stderr.write(('Unable to delete log file '
 
1568
                                             ' %r\n' % self._log_file_name))
 
1569
                    else:
 
1570
                        raise
 
1571
            return log_contents
 
1572
        else:
 
1573
            return "DELETED log file to reduce memory footprint"
1876
1574
 
1877
1575
    def requireFeature(self, feature):
1878
1576
        """This test requires a specific feature is available.
1895
1593
 
1896
1594
    def _run_bzr_core(self, args, retcode, encoding, stdin,
1897
1595
            working_dir):
1898
 
        # Clear chk_map page cache, because the contents are likely to mask
1899
 
        # locking errors.
1900
 
        chk_map.clear_cache()
1901
1596
        if encoding is None:
1902
1597
            encoding = osutils.get_user_encoding()
1903
1598
        stdout = StringIOWrapper()
1920
1615
            os.chdir(working_dir)
1921
1616
 
1922
1617
        try:
1923
 
            try:
1924
 
                result = self.apply_redirected(
1925
 
                    ui.ui_factory.stdin,
1926
 
                    stdout, stderr,
1927
 
                    _mod_commands.run_bzr_catch_user_errors,
1928
 
                    args)
1929
 
            except KeyboardInterrupt:
1930
 
                # Reraise KeyboardInterrupt with contents of redirected stdout
1931
 
                # and stderr as arguments, for tests which are interested in
1932
 
                # stdout and stderr and are expecting the exception.
1933
 
                out = stdout.getvalue()
1934
 
                err = stderr.getvalue()
1935
 
                if out:
1936
 
                    self.log('output:\n%r', out)
1937
 
                if err:
1938
 
                    self.log('errors:\n%r', err)
1939
 
                raise KeyboardInterrupt(out, err)
 
1618
            result = self.apply_redirected(ui.ui_factory.stdin,
 
1619
                stdout, stderr,
 
1620
                bzrlib.commands.run_bzr_catch_user_errors,
 
1621
                args)
1940
1622
        finally:
1941
1623
            logger.removeHandler(handler)
1942
1624
            ui.ui_factory = old_ui_factory
1952
1634
        if retcode is not None:
1953
1635
            self.assertEquals(retcode, result,
1954
1636
                              message='Unexpected return code')
1955
 
        return result, out, err
 
1637
        return out, err
1956
1638
 
1957
1639
    def run_bzr(self, args, retcode=0, encoding=None, stdin=None,
1958
1640
                working_dir=None, error_regexes=[], output_encoding=None):
1987
1669
        :keyword error_regexes: A list of expected error messages.  If
1988
1670
            specified they must be seen in the error output of the command.
1989
1671
        """
1990
 
        retcode, out, err = self._run_bzr_autosplit(
 
1672
        out, err = self._run_bzr_autosplit(
1991
1673
            args=args,
1992
1674
            retcode=retcode,
1993
1675
            encoding=encoding,
2072
1754
    def start_bzr_subprocess(self, process_args, env_changes=None,
2073
1755
                             skip_if_plan_to_signal=False,
2074
1756
                             working_dir=None,
2075
 
                             allow_plugins=False, stderr=subprocess.PIPE):
 
1757
                             allow_plugins=False):
2076
1758
        """Start bzr in a subprocess for testing.
2077
1759
 
2078
1760
        This starts a new Python interpreter and runs bzr in there.
2087
1769
            variables. A value of None will unset the env variable.
2088
1770
            The values must be strings. The change will only occur in the
2089
1771
            child, so you don't need to fix the environment after running.
2090
 
        :param skip_if_plan_to_signal: raise TestSkipped when true and system
2091
 
            doesn't support signalling subprocesses.
 
1772
        :param skip_if_plan_to_signal: raise TestSkipped when true and os.kill
 
1773
            is not available.
2092
1774
        :param allow_plugins: If False (default) pass --no-plugins to bzr.
2093
 
        :param stderr: file to use for the subprocess's stderr.  Valid values
2094
 
            are those valid for the stderr argument of `subprocess.Popen`.
2095
 
            Default value is ``subprocess.PIPE``.
2096
1775
 
2097
1776
        :returns: Popen object for the started process.
2098
1777
        """
2099
1778
        if skip_if_plan_to_signal:
2100
 
            if os.name != "posix":
2101
 
                raise TestSkipped("Sending signals not supported")
 
1779
            if not getattr(os, 'kill', None):
 
1780
                raise TestSkipped("os.kill not available.")
2102
1781
 
2103
1782
        if env_changes is None:
2104
1783
            env_changes = {}
2124
1803
            # so we will avoid using it on all platforms, just to
2125
1804
            # make sure the code path is used, and we don't break on win32
2126
1805
            cleanup_environment()
2127
 
            # Include the subprocess's log file in the test details, in case
2128
 
            # the test fails due to an error in the subprocess.
2129
 
            self._add_subprocess_log(trace._get_bzr_log_filename())
2130
1806
            command = [sys.executable]
2131
1807
            # frozen executables don't need the path to bzr
2132
1808
            if getattr(sys, "frozen", None) is None:
2134
1810
            if not allow_plugins:
2135
1811
                command.append('--no-plugins')
2136
1812
            command.extend(process_args)
2137
 
            process = self._popen(command, stdin=subprocess.PIPE,
2138
 
                                  stdout=subprocess.PIPE,
2139
 
                                  stderr=stderr)
 
1813
            process = self._popen(command, stdin=PIPE, stdout=PIPE, stderr=PIPE)
2140
1814
        finally:
2141
1815
            restore_environment()
2142
1816
            if cwd is not None:
2144
1818
 
2145
1819
        return process
2146
1820
 
2147
 
    def _add_subprocess_log(self, log_file_path):
2148
 
        if len(self._log_files) == 0:
2149
 
            # Register an addCleanup func.  We do this on the first call to
2150
 
            # _add_subprocess_log rather than in TestCase.setUp so that this
2151
 
            # addCleanup is registered after any cleanups for tempdirs that
2152
 
            # subclasses might create, which will probably remove the log file
2153
 
            # we want to read.
2154
 
            self.addCleanup(self._subprocess_log_cleanup)
2155
 
        # self._log_files is a set, so if a log file is reused we won't grab it
2156
 
        # twice.
2157
 
        self._log_files.add(log_file_path)
2158
 
 
2159
 
    def _subprocess_log_cleanup(self):
2160
 
        for count, log_file_path in enumerate(self._log_files):
2161
 
            # We use buffer_now=True to avoid holding the file open beyond
2162
 
            # the life of this function, which might interfere with e.g.
2163
 
            # cleaning tempdirs on Windows.
2164
 
            # XXX: Testtools 0.9.5 doesn't have the content_from_file helper
2165
 
            #detail_content = content.content_from_file(
2166
 
            #    log_file_path, buffer_now=True)
2167
 
            with open(log_file_path, 'rb') as log_file:
2168
 
                log_file_bytes = log_file.read()
2169
 
            detail_content = content.Content(content.ContentType("text",
2170
 
                "plain", {"charset": "utf8"}), lambda: [log_file_bytes])
2171
 
            self.addDetail("start_bzr_subprocess-log-%d" % (count,),
2172
 
                detail_content)
2173
 
 
2174
1821
    def _popen(self, *args, **kwargs):
2175
1822
        """Place a call to Popen.
2176
1823
 
2177
1824
        Allows tests to override this method to intercept the calls made to
2178
1825
        Popen for introspection.
2179
1826
        """
2180
 
        return subprocess.Popen(*args, **kwargs)
2181
 
 
2182
 
    def get_source_path(self):
2183
 
        """Return the path of the directory containing bzrlib."""
2184
 
        return os.path.dirname(os.path.dirname(bzrlib.__file__))
 
1827
        return Popen(*args, **kwargs)
2185
1828
 
2186
1829
    def get_bzr_path(self):
2187
1830
        """Return the path of the 'bzr' executable for this test suite."""
2188
 
        bzr_path = os.path.join(self.get_source_path(), "bzr")
 
1831
        bzr_path = os.path.dirname(os.path.dirname(bzrlib.__file__))+'/bzr'
2189
1832
        if not os.path.isfile(bzr_path):
2190
1833
            # We are probably installed. Assume sys.argv is the right file
2191
1834
            bzr_path = sys.argv[0]
2213
1856
        if retcode is not None and retcode != process.returncode:
2214
1857
            if process_args is None:
2215
1858
                process_args = "(unknown args)"
2216
 
            trace.mutter('Output of bzr %s:\n%s', process_args, out)
2217
 
            trace.mutter('Error for bzr %s:\n%s', process_args, err)
 
1859
            mutter('Output of bzr %s:\n%s', process_args, out)
 
1860
            mutter('Error for bzr %s:\n%s', process_args, err)
2218
1861
            self.fail('Command bzr %s failed with retcode %s != %s'
2219
1862
                      % (process_args, retcode, process.returncode))
2220
1863
        return [out, err]
2221
1864
 
2222
 
    def check_tree_shape(self, tree, shape):
2223
 
        """Compare a tree to a list of expected names.
 
1865
    def check_inventory_shape(self, inv, shape):
 
1866
        """Compare an inventory to a list of expected names.
2224
1867
 
2225
1868
        Fail if they are not precisely equal.
2226
1869
        """
2227
1870
        extras = []
2228
1871
        shape = list(shape)             # copy
2229
 
        for path, ie in tree.iter_entries_by_dir():
 
1872
        for path, ie in inv.entries():
2230
1873
            name = path.replace('\\', '/')
2231
1874
            if ie.kind == 'directory':
2232
1875
                name = name + '/'
2233
 
            if name == "/":
2234
 
                pass # ignore root entry
2235
 
            elif name in shape:
 
1876
            if name in shape:
2236
1877
                shape.remove(name)
2237
1878
            else:
2238
1879
                extras.append(name)
2279
1920
 
2280
1921
        Tests that expect to provoke LockContention errors should call this.
2281
1922
        """
2282
 
        self.overrideAttr(lockdir, '_DEFAULT_TIMEOUT_SECONDS', 0)
 
1923
        orig_timeout = bzrlib.lockdir._DEFAULT_TIMEOUT_SECONDS
 
1924
        def resetTimeout():
 
1925
            bzrlib.lockdir._DEFAULT_TIMEOUT_SECONDS = orig_timeout
 
1926
        self.addCleanup(resetTimeout)
 
1927
        bzrlib.lockdir._DEFAULT_TIMEOUT_SECONDS = 0
2283
1928
 
2284
1929
    def make_utf8_encoded_stringio(self, encoding_type=None):
2285
1930
        """Return a StringIOWrapper instance, that will encode Unicode
2293
1938
        sio.encoding = output_encoding
2294
1939
        return sio
2295
1940
 
2296
 
    def disable_verb(self, verb):
2297
 
        """Disable a smart server verb for one test."""
2298
 
        from bzrlib.smart import request
2299
 
        request_handlers = request.request_handlers
2300
 
        orig_method = request_handlers.get(verb)
2301
 
        request_handlers.remove(verb)
2302
 
        self.addCleanup(request_handlers.register, verb, orig_method)
2303
 
 
2304
1941
 
2305
1942
class CapturedCall(object):
2306
1943
    """A helper for capturing smart server calls for easy debug analysis."""
2328
1965
class TestCaseWithMemoryTransport(TestCase):
2329
1966
    """Common test class for tests that do not need disk resources.
2330
1967
 
2331
 
    Tests that need disk resources should derive from TestCaseInTempDir
2332
 
    orTestCaseWithTransport.
 
1968
    Tests that need disk resources should derive from TestCaseWithTransport.
2333
1969
 
2334
1970
    TestCaseWithMemoryTransport sets the TEST_ROOT variable for all bzr tests.
2335
1971
 
2336
 
    For TestCaseWithMemoryTransport the ``test_home_dir`` is set to the name of
 
1972
    For TestCaseWithMemoryTransport the test_home_dir is set to the name of
2337
1973
    a directory which does not exist. This serves to help ensure test isolation
2338
 
    is preserved. ``test_dir`` is set to the TEST_ROOT, as is cwd, because they
2339
 
    must exist. However, TestCaseWithMemoryTransport does not offer local file
2340
 
    defaults for the transport in tests, nor does it obey the command line
 
1974
    is preserved. test_dir is set to the TEST_ROOT, as is cwd, because they
 
1975
    must exist. However, TestCaseWithMemoryTransport does not offer local
 
1976
    file defaults for the transport in tests, nor does it obey the command line
2341
1977
    override, so tests that accidentally write to the common directory should
2342
1978
    be rare.
2343
1979
 
2344
 
    :cvar TEST_ROOT: Directory containing all temporary directories, plus a
2345
 
        ``.bzr`` directory that stops us ascending higher into the filesystem.
 
1980
    :cvar TEST_ROOT: Directory containing all temporary directories, plus
 
1981
    a .bzr directory that stops us ascending higher into the filesystem.
2346
1982
    """
2347
1983
 
2348
1984
    TEST_ROOT = None
2366
2002
 
2367
2003
        :param relpath: a path relative to the base url.
2368
2004
        """
2369
 
        t = _mod_transport.get_transport(self.get_url(relpath))
 
2005
        t = get_transport(self.get_url(relpath))
2370
2006
        self.assertFalse(t.is_readonly())
2371
2007
        return t
2372
2008
 
2378
2014
 
2379
2015
        :param relpath: a path relative to the base url.
2380
2016
        """
2381
 
        t = _mod_transport.get_transport(self.get_readonly_url(relpath))
 
2017
        t = get_transport(self.get_readonly_url(relpath))
2382
2018
        self.assertTrue(t.is_readonly())
2383
2019
        return t
2384
2020
 
2397
2033
        if self.__readonly_server is None:
2398
2034
            if self.transport_readonly_server is None:
2399
2035
                # readonly decorator requested
2400
 
                self.__readonly_server = test_server.ReadonlyServer()
 
2036
                # bring up the server
 
2037
                self.__readonly_server = ReadonlyServer()
 
2038
                self.__readonly_server.setUp(self.get_vfs_only_server())
2401
2039
            else:
2402
 
                # explicit readonly transport.
2403
2040
                self.__readonly_server = self.create_transport_readonly_server()
2404
 
            self.start_server(self.__readonly_server,
2405
 
                self.get_vfs_only_server())
 
2041
                self.__readonly_server.setUp(self.get_vfs_only_server())
 
2042
            self.addCleanup(self.__readonly_server.tearDown)
2406
2043
        return self.__readonly_server
2407
2044
 
2408
2045
    def get_readonly_url(self, relpath=None):
2426
2063
        is no means to override it.
2427
2064
        """
2428
2065
        if self.__vfs_server is None:
2429
 
            self.__vfs_server = memory.MemoryServer()
2430
 
            self.start_server(self.__vfs_server)
 
2066
            self.__vfs_server = MemoryServer()
 
2067
            self.__vfs_server.setUp()
 
2068
            self.addCleanup(self.__vfs_server.tearDown)
2431
2069
        return self.__vfs_server
2432
2070
 
2433
2071
    def get_server(self):
2440
2078
        then the self.get_vfs_server is returned.
2441
2079
        """
2442
2080
        if self.__server is None:
2443
 
            if (self.transport_server is None or self.transport_server is
2444
 
                self.vfs_transport_factory):
2445
 
                self.__server = self.get_vfs_only_server()
 
2081
            if self.transport_server is None or self.transport_server is self.vfs_transport_factory:
 
2082
                return self.get_vfs_only_server()
2446
2083
            else:
2447
2084
                # bring up a decorated means of access to the vfs only server.
2448
2085
                self.__server = self.transport_server()
2449
 
                self.start_server(self.__server, self.get_vfs_only_server())
 
2086
                try:
 
2087
                    self.__server.setUp(self.get_vfs_only_server())
 
2088
                except TypeError, e:
 
2089
                    # This should never happen; the try:Except here is to assist
 
2090
                    # developers having to update code rather than seeing an
 
2091
                    # uninformative TypeError.
 
2092
                    raise Exception, "Old server API in use: %s, %s" % (self.__server, e)
 
2093
            self.addCleanup(self.__server.tearDown)
2450
2094
        return self.__server
2451
2095
 
2452
2096
    def _adjust_url(self, base, relpath):
2514
2158
        propagating. This method ensures than a test did not leaked.
2515
2159
        """
2516
2160
        root = TestCaseWithMemoryTransport.TEST_ROOT
2517
 
        self.permit_url(_mod_transport.get_transport(root).base)
2518
2161
        wt = workingtree.WorkingTree.open(root)
2519
2162
        last_rev = wt.last_revision()
2520
2163
        if last_rev != 'null:':
2522
2165
            # recreate a new one or all the followng tests will fail.
2523
2166
            # If you need to inspect its content uncomment the following line
2524
2167
            # import pdb; pdb.set_trace()
2525
 
            _rmtree_temp_dir(root + '/.bzr', test_id=self.id())
 
2168
            _rmtree_temp_dir(root + '/.bzr')
2526
2169
            self._create_safety_net()
2527
2170
            raise AssertionError('%s/.bzr should not be modified' % root)
2528
2171
 
2529
2172
    def _make_test_root(self):
2530
2173
        if TestCaseWithMemoryTransport.TEST_ROOT is None:
2531
 
            # Watch out for tricky test dir (on OSX /tmp -> /private/tmp)
2532
 
            root = osutils.realpath(osutils.mkdtemp(prefix='testbzr-',
2533
 
                                                    suffix='.tmp'))
 
2174
            root = osutils.mkdtemp(prefix='testbzr-', suffix='.tmp')
2534
2175
            TestCaseWithMemoryTransport.TEST_ROOT = root
2535
2176
 
2536
2177
            self._create_safety_net()
2539
2180
            # specifically told when all tests are finished.  This will do.
2540
2181
            atexit.register(_rmtree_temp_dir, root)
2541
2182
 
2542
 
        self.permit_dir(TestCaseWithMemoryTransport.TEST_ROOT)
2543
2183
        self.addCleanup(self._check_safety_net)
2544
2184
 
2545
2185
    def makeAndChdirToTestDir(self):
2553
2193
        os.chdir(TestCaseWithMemoryTransport.TEST_ROOT)
2554
2194
        self.test_dir = TestCaseWithMemoryTransport.TEST_ROOT
2555
2195
        self.test_home_dir = self.test_dir + "/MemoryTransportMissingHomeDir"
2556
 
        self.permit_dir(self.test_dir)
2557
2196
 
2558
2197
    def make_branch(self, relpath, format=None):
2559
2198
        """Create a branch on the transport at relpath."""
2565
2204
            # might be a relative or absolute path
2566
2205
            maybe_a_url = self.get_url(relpath)
2567
2206
            segments = maybe_a_url.rsplit('/', 1)
2568
 
            t = _mod_transport.get_transport(maybe_a_url)
 
2207
            t = get_transport(maybe_a_url)
2569
2208
            if len(segments) > 1 and segments[-1] not in ('', '.'):
2570
2209
                t.ensure_base()
2571
2210
            if format is None:
2588
2227
        made_control = self.make_bzrdir(relpath, format=format)
2589
2228
        return made_control.create_repository(shared=shared)
2590
2229
 
2591
 
    def make_smart_server(self, path, backing_server=None):
2592
 
        if backing_server is None:
2593
 
            backing_server = self.get_server()
2594
 
        smart_server = test_server.SmartTCPServer_for_testing()
2595
 
        self.start_server(smart_server, backing_server)
2596
 
        remote_transport = _mod_transport.get_transport(smart_server.get_url()
2597
 
                                                   ).clone(path)
 
2230
    def make_smart_server(self, path):
 
2231
        smart_server = server.SmartTCPServer_for_testing()
 
2232
        smart_server.setUp(self.get_server())
 
2233
        remote_transport = get_transport(smart_server.get_url()).clone(path)
 
2234
        self.addCleanup(smart_server.tearDown)
2598
2235
        return remote_transport
2599
2236
 
2600
2237
    def make_branch_and_memory_tree(self, relpath, format=None):
2607
2244
        return branchbuilder.BranchBuilder(branch=branch)
2608
2245
 
2609
2246
    def overrideEnvironmentForTesting(self):
2610
 
        test_home_dir = self.test_home_dir
2611
 
        if isinstance(test_home_dir, unicode):
2612
 
            test_home_dir = test_home_dir.encode(sys.getfilesystemencoding())
2613
 
        self.overrideEnv('HOME', test_home_dir)
2614
 
        self.overrideEnv('BZR_HOME', test_home_dir)
 
2247
        os.environ['HOME'] = self.test_home_dir
 
2248
        os.environ['BZR_HOME'] = self.test_home_dir
2615
2249
 
2616
2250
    def setUp(self):
2617
2251
        super(TestCaseWithMemoryTransport, self).setUp()
2618
 
        # Ensure that ConnectedTransport doesn't leak sockets
2619
 
        def get_transport_with_cleanup(*args, **kwargs):
2620
 
            t = orig_get_transport(*args, **kwargs)
2621
 
            if isinstance(t, _mod_transport.ConnectedTransport):
2622
 
                self.addCleanup(t.disconnect)
2623
 
            return t
2624
 
 
2625
 
        orig_get_transport = self.overrideAttr(_mod_transport, 'get_transport',
2626
 
                                               get_transport_with_cleanup)
2627
2252
        self._make_test_root()
2628
 
        self.addCleanup(os.chdir, os.getcwdu())
 
2253
        _currentdir = os.getcwdu()
 
2254
        def _leaveDirectory():
 
2255
            os.chdir(_currentdir)
 
2256
        self.addCleanup(_leaveDirectory)
2629
2257
        self.makeAndChdirToTestDir()
2630
2258
        self.overrideEnvironmentForTesting()
2631
2259
        self.__readonly_server = None
2634
2262
 
2635
2263
    def setup_smart_server_with_call_log(self):
2636
2264
        """Sets up a smart server as the transport server with a call log."""
2637
 
        self.transport_server = test_server.SmartTCPServer_for_testing
 
2265
        self.transport_server = server.SmartTCPServer_for_testing
2638
2266
        self.hpss_calls = []
2639
2267
        import traceback
2640
2268
        # Skip the current stack down to the caller of
2672
2300
 
2673
2301
    OVERRIDE_PYTHON = 'python'
2674
2302
 
2675
 
    def setUp(self):
2676
 
        super(TestCaseInTempDir, self).setUp()
2677
 
        # Remove the protection set in isolated_environ, we have a proper
2678
 
        # access to disk resources now.
2679
 
        self.overrideEnv('BZR_LOG', None)
2680
 
 
2681
2303
    def check_file_contents(self, filename, expect):
2682
2304
        self.log("check contents of file %s" % filename)
2683
 
        f = file(filename)
2684
 
        try:
2685
 
            contents = f.read()
2686
 
        finally:
2687
 
            f.close()
 
2305
        contents = file(filename, 'r').read()
2688
2306
        if contents != expect:
2689
2307
            self.log("expected: %r" % expect)
2690
2308
            self.log("actually: %r" % contents)
2692
2310
 
2693
2311
    def _getTestDirPrefix(self):
2694
2312
        # create a directory within the top level test directory
2695
 
        if sys.platform in ('win32', 'cygwin'):
 
2313
        if sys.platform == 'win32':
2696
2314
            name_prefix = re.sub('[<>*=+",:;_/\\-]', '_', self.id())
2697
2315
            # windows is likely to have path-length limits so use a short name
2698
2316
            name_prefix = name_prefix[-30:]
2713
2331
            if os.path.exists(name):
2714
2332
                name = name_prefix + '_' + str(i)
2715
2333
            else:
2716
 
                # now create test and home directories within this dir
2717
 
                self.test_base_dir = name
2718
 
                self.addCleanup(self.deleteTestDir)
2719
 
                os.mkdir(self.test_base_dir)
 
2334
                os.mkdir(name)
2720
2335
                break
2721
 
        self.permit_dir(self.test_base_dir)
2722
 
        # 'sprouting' and 'init' of a branch both walk up the tree to find
2723
 
        # stacking policy to honour; create a bzr dir with an unshared
2724
 
        # repository (but not a branch - our code would be trying to escape
2725
 
        # then!) to stop them, and permit it to be read.
2726
 
        # control = bzrdir.BzrDir.create(self.test_base_dir)
2727
 
        # control.create_repository()
 
2336
        # now create test and home directories within this dir
 
2337
        self.test_base_dir = name
2728
2338
        self.test_home_dir = self.test_base_dir + '/home'
2729
2339
        os.mkdir(self.test_home_dir)
2730
2340
        self.test_dir = self.test_base_dir + '/work'
2736
2346
            f.write(self.id())
2737
2347
        finally:
2738
2348
            f.close()
 
2349
        self.addCleanup(self.deleteTestDir)
2739
2350
 
2740
2351
    def deleteTestDir(self):
2741
2352
        os.chdir(TestCaseWithMemoryTransport.TEST_ROOT)
2742
 
        _rmtree_temp_dir(self.test_base_dir, test_id=self.id())
 
2353
        _rmtree_temp_dir(self.test_base_dir)
2743
2354
 
2744
2355
    def build_tree(self, shape, line_endings='binary', transport=None):
2745
2356
        """Build a test tree according to a pattern.
2764
2375
                "a list or a tuple. Got %r instead" % (shape,))
2765
2376
        # It's OK to just create them using forward slashes on windows.
2766
2377
        if transport is None or transport.is_readonly():
2767
 
            transport = _mod_transport.get_transport(".")
 
2378
            transport = get_transport(".")
2768
2379
        for name in shape:
2769
2380
            self.assertIsInstance(name, basestring)
2770
2381
            if name[-1] == '/':
2780
2391
                content = "contents of %s%s" % (name.encode('utf-8'), end)
2781
2392
                transport.put_bytes_non_atomic(urlutils.escape(name), content)
2782
2393
 
2783
 
    build_tree_contents = staticmethod(treeshape.build_tree_contents)
 
2394
    def build_tree_contents(self, shape):
 
2395
        build_tree_contents(shape)
2784
2396
 
2785
2397
    def assertInWorkingTree(self, path, root_path='.', tree=None):
2786
2398
        """Assert whether path or paths are in the WorkingTree"""
2826
2438
        """
2827
2439
        if self.__vfs_server is None:
2828
2440
            self.__vfs_server = self.vfs_transport_factory()
2829
 
            self.start_server(self.__vfs_server)
 
2441
            self.__vfs_server.setUp()
 
2442
            self.addCleanup(self.__vfs_server.tearDown)
2830
2443
        return self.__vfs_server
2831
2444
 
2832
2445
    def make_branch_and_tree(self, relpath, format=None):
2839
2452
        repository will also be accessed locally. Otherwise a lightweight
2840
2453
        checkout is created and returned.
2841
2454
 
2842
 
        We do this because we can't physically create a tree in the local
2843
 
        path, with a branch reference to the transport_factory url, and
2844
 
        a branch + repository in the vfs_transport, unless the vfs_transport
2845
 
        namespace is distinct from the local disk - the two branch objects
2846
 
        would collide. While we could construct a tree with its branch object
2847
 
        pointing at the transport_factory transport in memory, reopening it
2848
 
        would behaving unexpectedly, and has in the past caused testing bugs
2849
 
        when we tried to do it that way.
2850
 
 
2851
2455
        :param format: The BzrDirFormat.
2852
2456
        :returns: the WorkingTree.
2853
2457
        """
2862
2466
            # We can only make working trees locally at the moment.  If the
2863
2467
            # transport can't support them, then we keep the non-disk-backed
2864
2468
            # branch and create a local checkout.
2865
 
            if self.vfs_transport_factory is test_server.LocalURLServer:
 
2469
            if self.vfs_transport_factory is LocalURLServer:
2866
2470
                # the branch is colocated on disk, we cannot create a checkout.
2867
2471
                # hopefully callers will expect this.
2868
2472
                local_controldir= bzrdir.BzrDir.open(self.get_vfs_only_url(relpath))
2905
2509
        super(TestCaseWithTransport, self).setUp()
2906
2510
        self.__vfs_server = None
2907
2511
 
2908
 
    def disable_missing_extensions_warning(self):
2909
 
        """Some tests expect a precise stderr content.
2910
 
 
2911
 
        There is no point in forcing them to duplicate the extension related
2912
 
        warning.
2913
 
        """
2914
 
        config.GlobalConfig().set_user_option('ignore_missing_extensions', True)
2915
 
 
2916
2512
 
2917
2513
class ChrootedTestCase(TestCaseWithTransport):
2918
2514
    """A support class that provides readonly urls outside the local namespace.
2927
2523
    """
2928
2524
 
2929
2525
    def setUp(self):
2930
 
        from bzrlib.tests import http_server
2931
2526
        super(ChrootedTestCase, self).setUp()
2932
 
        if not self.vfs_transport_factory == memory.MemoryServer:
2933
 
            self.transport_readonly_server = http_server.HttpServer
 
2527
        if not self.vfs_transport_factory == MemoryServer:
 
2528
            self.transport_readonly_server = HttpServer
2934
2529
 
2935
2530
 
2936
2531
def condition_id_re(pattern):
2939
2534
    :param pattern: A regular expression string.
2940
2535
    :return: A callable that returns True if the re matches.
2941
2536
    """
2942
 
    filter_re = re.compile(pattern, 0)
 
2537
    filter_re = osutils.re_compile_checked(pattern, 0,
 
2538
        'test filter')
2943
2539
    def condition(test):
2944
2540
        test_id = test.id()
2945
2541
        return filter_re.search(test_id)
3132
2728
              strict=False,
3133
2729
              runner_class=None,
3134
2730
              suite_decorators=None,
3135
 
              stream=None,
3136
 
              result_decorators=None,
3137
 
              ):
 
2731
              stream=None):
3138
2732
    """Run a test suite for bzr selftest.
3139
2733
 
3140
2734
    :param runner_class: The class of runner to use. Must support the
3155
2749
                            descriptions=0,
3156
2750
                            verbosity=verbosity,
3157
2751
                            bench_history=bench_history,
 
2752
                            list_only=list_only,
3158
2753
                            strict=strict,
3159
 
                            result_decorators=result_decorators,
3160
2754
                            )
3161
2755
    runner.stop_on_failure=stop_on_failure
3162
2756
    # built in decorator factories:
3170
2764
        decorators.append(filter_tests(pattern))
3171
2765
    if suite_decorators:
3172
2766
        decorators.extend(suite_decorators)
3173
 
    # tell the result object how many tests will be running: (except if
3174
 
    # --parallel=fork is being used. Robert said he will provide a better
3175
 
    # progress design later -- vila 20090817)
3176
 
    if fork_decorator not in decorators:
3177
 
        decorators.append(CountingDecorator)
 
2767
    # tell the result object how many tests will be running:
 
2768
    decorators.append(CountingDecorator)
3178
2769
    for decorator in decorators:
3179
2770
        suite = decorator(suite)
 
2771
    result = runner.run(suite)
3180
2772
    if list_only:
3181
 
        # Done after test suite decoration to allow randomisation etc
3182
 
        # to take effect, though that is of marginal benefit.
3183
 
        if verbosity >= 2:
3184
 
            stream.write("Listing tests only ...\n")
3185
 
        for t in iter_suite_tests(suite):
3186
 
            stream.write("%s\n" % (t.id()))
3187
2773
        return True
3188
 
    result = runner.run(suite)
 
2774
    result.done()
3189
2775
    if strict:
3190
2776
        return result.wasStrictlySuccessful()
3191
2777
    else:
3197
2783
 
3198
2784
 
3199
2785
def fork_decorator(suite):
3200
 
    if getattr(os, "fork", None) is None:
3201
 
        raise errors.BzrCommandError("platform does not support fork,"
3202
 
            " try --parallel=subprocess instead.")
3203
2786
    concurrency = osutils.local_concurrency()
3204
2787
    if concurrency == 1:
3205
2788
        return suite
3260
2843
    return suite
3261
2844
 
3262
2845
 
3263
 
class TestDecorator(TestUtil.TestSuite):
 
2846
class TestDecorator(TestSuite):
3264
2847
    """A decorator for TestCase/TestSuite objects.
3265
2848
    
3266
2849
    Usually, subclasses should override __iter__(used when flattening test
3269
2852
    """
3270
2853
 
3271
2854
    def __init__(self, suite):
3272
 
        TestUtil.TestSuite.__init__(self)
 
2855
        TestSuite.__init__(self)
3273
2856
        self.addTest(suite)
3274
2857
 
3275
2858
    def countTestCases(self):
3351
2934
        if self.randomised:
3352
2935
            return iter(self._tests)
3353
2936
        self.randomised = True
3354
 
        self.stream.write("Randomizing test order using seed %s\n\n" %
 
2937
        self.stream.writeln("Randomizing test order using seed %s\n" %
3355
2938
            (self.actual_seed()))
3356
2939
        # Initialise the random number generator.
3357
2940
        random.seed(self.actual_seed())
3394
2977
 
3395
2978
def partition_tests(suite, count):
3396
2979
    """Partition suite into count lists of tests."""
3397
 
    # This just assigns tests in a round-robin fashion.  On one hand this
3398
 
    # splits up blocks of related tests that might run faster if they shared
3399
 
    # resources, but on the other it avoids assigning blocks of slow tests to
3400
 
    # just one partition.  So the slowest partition shouldn't be much slower
3401
 
    # than the fastest.
3402
 
    partitions = [list() for i in range(count)]
3403
 
    tests = iter_suite_tests(suite)
3404
 
    for partition, test in itertools.izip(itertools.cycle(partitions), tests):
3405
 
        partition.append(test)
3406
 
    return partitions
3407
 
 
3408
 
 
3409
 
def workaround_zealous_crypto_random():
3410
 
    """Crypto.Random want to help us being secure, but we don't care here.
3411
 
 
3412
 
    This workaround some test failure related to the sftp server. Once paramiko
3413
 
    stop using the controversial API in Crypto.Random, we may get rid of it.
3414
 
    """
3415
 
    try:
3416
 
        from Crypto.Random import atfork
3417
 
        atfork()
3418
 
    except ImportError:
3419
 
        pass
 
2980
    result = []
 
2981
    tests = list(iter_suite_tests(suite))
 
2982
    tests_per_process = int(math.ceil(float(len(tests)) / count))
 
2983
    for block in range(count):
 
2984
        low_test = block * tests_per_process
 
2985
        high_test = low_test + tests_per_process
 
2986
        process_tests = tests[low_test:high_test]
 
2987
        result.append(process_tests)
 
2988
    return result
3420
2989
 
3421
2990
 
3422
2991
def fork_for_tests(suite):
3428
2997
    concurrency = osutils.local_concurrency()
3429
2998
    result = []
3430
2999
    from subunit import TestProtocolClient, ProtocolTestCase
3431
 
    from subunit.test_results import AutoTimingTestResultDecorator
 
3000
    try:
 
3001
        from subunit.test_results import AutoTimingTestResultDecorator
 
3002
    except ImportError:
 
3003
        AutoTimingTestResultDecorator = lambda x:x
3432
3004
    class TestInOtherProcess(ProtocolTestCase):
3433
3005
        # Should be in subunit, I think. RBC.
3434
3006
        def __init__(self, stream, pid):
3439
3011
            try:
3440
3012
                ProtocolTestCase.run(self, result)
3441
3013
            finally:
3442
 
                os.waitpid(self.pid, 0)
 
3014
                os.waitpid(self.pid, os.WNOHANG)
3443
3015
 
3444
3016
    test_blocks = partition_tests(suite, concurrency)
3445
3017
    for process_tests in test_blocks:
3446
 
        process_suite = TestUtil.TestSuite()
 
3018
        process_suite = TestSuite()
3447
3019
        process_suite.addTests(process_tests)
3448
3020
        c2pread, c2pwrite = os.pipe()
3449
3021
        pid = os.fork()
3450
3022
        if pid == 0:
3451
 
            workaround_zealous_crypto_random()
3452
3023
            try:
3453
3024
                os.close(c2pread)
3454
3025
                # Leave stderr and stdout open so we can see test noise
3501
3072
        if not os.path.isfile(bzr_path):
3502
3073
            # We are probably installed. Assume sys.argv is the right file
3503
3074
            bzr_path = sys.argv[0]
3504
 
        bzr_path = [bzr_path]
3505
 
        if sys.platform == "win32":
3506
 
            # if we're on windows, we can't execute the bzr script directly
3507
 
            bzr_path = [sys.executable] + bzr_path
3508
3075
        fd, test_list_file_name = tempfile.mkstemp()
3509
3076
        test_list_file = os.fdopen(fd, 'wb', 1)
3510
3077
        for test in process_tests:
3511
3078
            test_list_file.write(test.id() + '\n')
3512
3079
        test_list_file.close()
3513
3080
        try:
3514
 
            argv = bzr_path + ['selftest', '--load-list', test_list_file_name,
 
3081
            argv = [bzr_path, 'selftest', '--load-list', test_list_file_name,
3515
3082
                '--subunit']
3516
3083
            if '--no-plugins' in sys.argv:
3517
3084
                argv.append('--no-plugins')
3518
 
            # stderr=subprocess.STDOUT would be ideal, but until we prevent
3519
 
            # noise on stderr it can interrupt the subunit protocol.
3520
 
            process = subprocess.Popen(argv, stdin=subprocess.PIPE,
3521
 
                                      stdout=subprocess.PIPE,
3522
 
                                      stderr=subprocess.PIPE,
3523
 
                                      bufsize=1)
 
3085
            # stderr=STDOUT would be ideal, but until we prevent noise on
 
3086
            # stderr it can interrupt the subunit protocol.
 
3087
            process = Popen(argv, stdin=PIPE, stdout=PIPE, stderr=PIPE,
 
3088
                bufsize=1)
3524
3089
            test = TestInSubprocess(process, test_list_file_name)
3525
3090
            result.append(test)
3526
3091
        except:
3529
3094
    return result
3530
3095
 
3531
3096
 
3532
 
class ProfileResult(testtools.ExtendedToOriginalDecorator):
3533
 
    """Generate profiling data for all activity between start and success.
3534
 
    
3535
 
    The profile data is appended to the test's _benchcalls attribute and can
3536
 
    be accessed by the forwarded-to TestResult.
 
3097
class BZRTransformingResult(unittest.TestResult):
3537
3098
 
3538
 
    While it might be cleaner do accumulate this in stopTest, addSuccess is
3539
 
    where our existing output support for lsprof is, and this class aims to
3540
 
    fit in with that: while it could be moved it's not necessary to accomplish
3541
 
    test profiling, nor would it be dramatically cleaner.
3542
 
    """
 
3099
    def __init__(self, target):
 
3100
        unittest.TestResult.__init__(self)
 
3101
        self.result = target
3543
3102
 
3544
3103
    def startTest(self, test):
3545
 
        self.profiler = bzrlib.lsprof.BzrProfiler()
3546
 
        # Prevent deadlocks in tests that use lsprof: those tests will
3547
 
        # unavoidably fail.
3548
 
        bzrlib.lsprof.BzrProfiler.profiler_block = 0
3549
 
        self.profiler.start()
3550
 
        testtools.ExtendedToOriginalDecorator.startTest(self, test)
 
3104
        self.result.startTest(test)
 
3105
 
 
3106
    def stopTest(self, test):
 
3107
        self.result.stopTest(test)
 
3108
 
 
3109
    def addError(self, test, err):
 
3110
        feature = self._error_looks_like('UnavailableFeature: ', err)
 
3111
        if feature is not None:
 
3112
            self.result.addNotSupported(test, feature)
 
3113
        else:
 
3114
            self.result.addError(test, err)
 
3115
 
 
3116
    def addFailure(self, test, err):
 
3117
        known = self._error_looks_like('KnownFailure: ', err)
 
3118
        if known is not None:
 
3119
            self.result._addKnownFailure(test, [KnownFailure,
 
3120
                                                KnownFailure(known), None])
 
3121
        else:
 
3122
            self.result.addFailure(test, err)
 
3123
 
 
3124
    def addSkip(self, test, reason):
 
3125
        self.result.addSkip(test, reason)
3551
3126
 
3552
3127
    def addSuccess(self, test):
3553
 
        stats = self.profiler.stop()
3554
 
        try:
3555
 
            calls = test._benchcalls
3556
 
        except AttributeError:
3557
 
            test._benchcalls = []
3558
 
            calls = test._benchcalls
3559
 
        calls.append(((test.id(), "", ""), stats))
3560
 
        testtools.ExtendedToOriginalDecorator.addSuccess(self, test)
 
3128
        self.result.addSuccess(test)
3561
3129
 
3562
 
    def stopTest(self, test):
3563
 
        testtools.ExtendedToOriginalDecorator.stopTest(self, test)
3564
 
        self.profiler = None
 
3130
    def _error_looks_like(self, prefix, err):
 
3131
        """Deserialize exception and returns the stringify value."""
 
3132
        import subunit
 
3133
        value = None
 
3134
        typ, exc, _ = err
 
3135
        if isinstance(exc, subunit.RemoteException):
 
3136
            # stringify the exception gives access to the remote traceback
 
3137
            # We search the last line for 'prefix'
 
3138
            lines = str(exc).split('\n')
 
3139
            while lines and not lines[-1]:
 
3140
                lines.pop(-1)
 
3141
            if lines:
 
3142
                if lines[-1].startswith(prefix):
 
3143
                    value = lines[-1][len(prefix):]
 
3144
        return value
3565
3145
 
3566
3146
 
3567
3147
# Controlled by "bzr selftest -E=..." option
3568
 
# Currently supported:
3569
 
#   -Eallow_debug           Will no longer clear debug.debug_flags() so it
3570
 
#                           preserves any flags supplied at the command line.
3571
 
#   -Edisable_lock_checks   Turns errors in mismatched locks into simple prints
3572
 
#                           rather than failing tests. And no longer raise
3573
 
#                           LockContention when fctnl locks are not being used
3574
 
#                           with proper exclusion rules.
3575
 
#   -Ethreads               Will display thread ident at creation/join time to
3576
 
#                           help track thread leaks
3577
 
 
3578
 
#   -Econfig_stats          Will collect statistics using addDetail
3579
3148
selftest_debug_flags = set()
3580
3149
 
3581
3150
 
3594
3163
             starting_with=None,
3595
3164
             runner_class=None,
3596
3165
             suite_decorators=None,
3597
 
             stream=None,
3598
 
             lsprof_tests=False,
3599
3166
             ):
3600
3167
    """Run the whole test suite under the enhanced runner"""
3601
3168
    # XXX: Very ugly way to do this...
3618
3185
            keep_only = None
3619
3186
        else:
3620
3187
            keep_only = load_test_id_list(load_list)
3621
 
        if starting_with:
3622
 
            starting_with = [test_prefix_alias_registry.resolve_alias(start)
3623
 
                             for start in starting_with]
3624
3188
        if test_suite_factory is None:
3625
 
            # Reduce loading time by loading modules based on the starting_with
3626
 
            # patterns.
3627
3189
            suite = test_suite(keep_only, starting_with)
3628
3190
        else:
3629
3191
            suite = test_suite_factory()
3630
 
        if starting_with:
3631
 
            # But always filter as requested.
3632
 
            suite = filter_suite_by_id_startswith(suite, starting_with)
3633
 
        result_decorators = []
3634
 
        if lsprof_tests:
3635
 
            result_decorators.append(ProfileResult)
3636
3192
        return run_suite(suite, 'testbzr', verbose=verbose, pattern=pattern,
3637
3193
                     stop_on_failure=stop_on_failure,
3638
3194
                     transport=transport,
3645
3201
                     strict=strict,
3646
3202
                     runner_class=runner_class,
3647
3203
                     suite_decorators=suite_decorators,
3648
 
                     stream=stream,
3649
 
                     result_decorators=result_decorators,
3650
3204
                     )
3651
3205
    finally:
3652
3206
        default_transport = old_transport
3775
3329
                key, obj, help=help, info=info, override_existing=False)
3776
3330
        except KeyError:
3777
3331
            actual = self.get(key)
3778
 
            trace.note(
3779
 
                'Test prefix alias %s is already used for %s, ignoring %s'
3780
 
                % (key, actual, obj))
 
3332
            note('Test prefix alias %s is already used for %s, ignoring %s'
 
3333
                 % (key, actual, obj))
3781
3334
 
3782
3335
    def resolve_alias(self, id_start):
3783
3336
        """Replace the alias by the prefix in the given string.
3801
3354
# appear prefixed ('bzrlib.' is "replaced" by 'bzrlib.').
3802
3355
test_prefix_alias_registry.register('bzrlib', 'bzrlib')
3803
3356
 
3804
 
# Obvious highest levels prefixes, feel free to add your own via a plugin
 
3357
# Obvious higest levels prefixes, feel free to add your own via a plugin
3805
3358
test_prefix_alias_registry.register('bd', 'bzrlib.doc')
3806
3359
test_prefix_alias_registry.register('bu', 'bzrlib.utils')
3807
3360
test_prefix_alias_registry.register('bt', 'bzrlib.tests')
3809
3362
test_prefix_alias_registry.register('bp', 'bzrlib.plugins')
3810
3363
 
3811
3364
 
3812
 
def _test_suite_testmod_names():
3813
 
    """Return the standard list of test module names to test."""
3814
 
    return [
3815
 
        'bzrlib.doc',
3816
 
        'bzrlib.tests.blackbox',
3817
 
        'bzrlib.tests.commands',
3818
 
        'bzrlib.tests.doc_generate',
3819
 
        'bzrlib.tests.per_branch',
3820
 
        'bzrlib.tests.per_bzrdir',
3821
 
        'bzrlib.tests.per_controldir',
3822
 
        'bzrlib.tests.per_controldir_colo',
3823
 
        'bzrlib.tests.per_foreign_vcs',
3824
 
        'bzrlib.tests.per_interrepository',
3825
 
        'bzrlib.tests.per_intertree',
3826
 
        'bzrlib.tests.per_inventory',
3827
 
        'bzrlib.tests.per_interbranch',
3828
 
        'bzrlib.tests.per_lock',
3829
 
        'bzrlib.tests.per_merger',
3830
 
        'bzrlib.tests.per_transport',
3831
 
        'bzrlib.tests.per_tree',
3832
 
        'bzrlib.tests.per_pack_repository',
3833
 
        'bzrlib.tests.per_repository',
3834
 
        'bzrlib.tests.per_repository_chk',
3835
 
        'bzrlib.tests.per_repository_reference',
3836
 
        'bzrlib.tests.per_repository_vf',
3837
 
        'bzrlib.tests.per_uifactory',
3838
 
        'bzrlib.tests.per_versionedfile',
3839
 
        'bzrlib.tests.per_workingtree',
3840
 
        'bzrlib.tests.test__annotator',
3841
 
        'bzrlib.tests.test__bencode',
3842
 
        'bzrlib.tests.test__btree_serializer',
3843
 
        'bzrlib.tests.test__chk_map',
3844
 
        'bzrlib.tests.test__dirstate_helpers',
3845
 
        'bzrlib.tests.test__groupcompress',
3846
 
        'bzrlib.tests.test__known_graph',
3847
 
        'bzrlib.tests.test__rio',
3848
 
        'bzrlib.tests.test__simple_set',
3849
 
        'bzrlib.tests.test__static_tuple',
3850
 
        'bzrlib.tests.test__walkdirs_win32',
3851
 
        'bzrlib.tests.test_ancestry',
3852
 
        'bzrlib.tests.test_annotate',
3853
 
        'bzrlib.tests.test_api',
3854
 
        'bzrlib.tests.test_atomicfile',
3855
 
        'bzrlib.tests.test_bad_files',
3856
 
        'bzrlib.tests.test_bisect_multi',
3857
 
        'bzrlib.tests.test_branch',
3858
 
        'bzrlib.tests.test_branchbuilder',
3859
 
        'bzrlib.tests.test_btree_index',
3860
 
        'bzrlib.tests.test_bugtracker',
3861
 
        'bzrlib.tests.test_bundle',
3862
 
        'bzrlib.tests.test_bzrdir',
3863
 
        'bzrlib.tests.test__chunks_to_lines',
3864
 
        'bzrlib.tests.test_cache_utf8',
3865
 
        'bzrlib.tests.test_chk_map',
3866
 
        'bzrlib.tests.test_chk_serializer',
3867
 
        'bzrlib.tests.test_chunk_writer',
3868
 
        'bzrlib.tests.test_clean_tree',
3869
 
        'bzrlib.tests.test_cleanup',
3870
 
        'bzrlib.tests.test_cmdline',
3871
 
        'bzrlib.tests.test_commands',
3872
 
        'bzrlib.tests.test_commit',
3873
 
        'bzrlib.tests.test_commit_merge',
3874
 
        'bzrlib.tests.test_config',
3875
 
        'bzrlib.tests.test_conflicts',
3876
 
        'bzrlib.tests.test_controldir',
3877
 
        'bzrlib.tests.test_counted_lock',
3878
 
        'bzrlib.tests.test_crash',
3879
 
        'bzrlib.tests.test_decorators',
3880
 
        'bzrlib.tests.test_delta',
3881
 
        'bzrlib.tests.test_debug',
3882
 
        'bzrlib.tests.test_diff',
3883
 
        'bzrlib.tests.test_directory_service',
3884
 
        'bzrlib.tests.test_dirstate',
3885
 
        'bzrlib.tests.test_email_message',
3886
 
        'bzrlib.tests.test_eol_filters',
3887
 
        'bzrlib.tests.test_errors',
3888
 
        'bzrlib.tests.test_export',
3889
 
        'bzrlib.tests.test_export_pot',
3890
 
        'bzrlib.tests.test_extract',
3891
 
        'bzrlib.tests.test_fetch',
3892
 
        'bzrlib.tests.test_fixtures',
3893
 
        'bzrlib.tests.test_fifo_cache',
3894
 
        'bzrlib.tests.test_filters',
3895
 
        'bzrlib.tests.test_ftp_transport',
3896
 
        'bzrlib.tests.test_foreign',
3897
 
        'bzrlib.tests.test_generate_docs',
3898
 
        'bzrlib.tests.test_generate_ids',
3899
 
        'bzrlib.tests.test_globbing',
3900
 
        'bzrlib.tests.test_gpg',
3901
 
        'bzrlib.tests.test_graph',
3902
 
        'bzrlib.tests.test_groupcompress',
3903
 
        'bzrlib.tests.test_hashcache',
3904
 
        'bzrlib.tests.test_help',
3905
 
        'bzrlib.tests.test_hooks',
3906
 
        'bzrlib.tests.test_http',
3907
 
        'bzrlib.tests.test_http_response',
3908
 
        'bzrlib.tests.test_https_ca_bundle',
3909
 
        'bzrlib.tests.test_i18n',
3910
 
        'bzrlib.tests.test_identitymap',
3911
 
        'bzrlib.tests.test_ignores',
3912
 
        'bzrlib.tests.test_index',
3913
 
        'bzrlib.tests.test_import_tariff',
3914
 
        'bzrlib.tests.test_info',
3915
 
        'bzrlib.tests.test_inv',
3916
 
        'bzrlib.tests.test_inventory_delta',
3917
 
        'bzrlib.tests.test_knit',
3918
 
        'bzrlib.tests.test_lazy_import',
3919
 
        'bzrlib.tests.test_lazy_regex',
3920
 
        'bzrlib.tests.test_library_state',
3921
 
        'bzrlib.tests.test_lock',
3922
 
        'bzrlib.tests.test_lockable_files',
3923
 
        'bzrlib.tests.test_lockdir',
3924
 
        'bzrlib.tests.test_log',
3925
 
        'bzrlib.tests.test_lru_cache',
3926
 
        'bzrlib.tests.test_lsprof',
3927
 
        'bzrlib.tests.test_mail_client',
3928
 
        'bzrlib.tests.test_matchers',
3929
 
        'bzrlib.tests.test_memorytree',
3930
 
        'bzrlib.tests.test_merge',
3931
 
        'bzrlib.tests.test_merge3',
3932
 
        'bzrlib.tests.test_merge_core',
3933
 
        'bzrlib.tests.test_merge_directive',
3934
 
        'bzrlib.tests.test_mergetools',
3935
 
        'bzrlib.tests.test_missing',
3936
 
        'bzrlib.tests.test_msgeditor',
3937
 
        'bzrlib.tests.test_multiparent',
3938
 
        'bzrlib.tests.test_mutabletree',
3939
 
        'bzrlib.tests.test_nonascii',
3940
 
        'bzrlib.tests.test_options',
3941
 
        'bzrlib.tests.test_osutils',
3942
 
        'bzrlib.tests.test_osutils_encodings',
3943
 
        'bzrlib.tests.test_pack',
3944
 
        'bzrlib.tests.test_patch',
3945
 
        'bzrlib.tests.test_patches',
3946
 
        'bzrlib.tests.test_permissions',
3947
 
        'bzrlib.tests.test_plugins',
3948
 
        'bzrlib.tests.test_progress',
3949
 
        'bzrlib.tests.test_pyutils',
3950
 
        'bzrlib.tests.test_read_bundle',
3951
 
        'bzrlib.tests.test_reconcile',
3952
 
        'bzrlib.tests.test_reconfigure',
3953
 
        'bzrlib.tests.test_registry',
3954
 
        'bzrlib.tests.test_remote',
3955
 
        'bzrlib.tests.test_rename_map',
3956
 
        'bzrlib.tests.test_repository',
3957
 
        'bzrlib.tests.test_revert',
3958
 
        'bzrlib.tests.test_revision',
3959
 
        'bzrlib.tests.test_revisionspec',
3960
 
        'bzrlib.tests.test_revisiontree',
3961
 
        'bzrlib.tests.test_rio',
3962
 
        'bzrlib.tests.test_rules',
3963
 
        'bzrlib.tests.test_sampler',
3964
 
        'bzrlib.tests.test_scenarios',
3965
 
        'bzrlib.tests.test_script',
3966
 
        'bzrlib.tests.test_selftest',
3967
 
        'bzrlib.tests.test_serializer',
3968
 
        'bzrlib.tests.test_setup',
3969
 
        'bzrlib.tests.test_sftp_transport',
3970
 
        'bzrlib.tests.test_shelf',
3971
 
        'bzrlib.tests.test_shelf_ui',
3972
 
        'bzrlib.tests.test_smart',
3973
 
        'bzrlib.tests.test_smart_add',
3974
 
        'bzrlib.tests.test_smart_request',
3975
 
        'bzrlib.tests.test_smart_transport',
3976
 
        'bzrlib.tests.test_smtp_connection',
3977
 
        'bzrlib.tests.test_source',
3978
 
        'bzrlib.tests.test_ssh_transport',
3979
 
        'bzrlib.tests.test_status',
3980
 
        'bzrlib.tests.test_store',
3981
 
        'bzrlib.tests.test_strace',
3982
 
        'bzrlib.tests.test_subsume',
3983
 
        'bzrlib.tests.test_switch',
3984
 
        'bzrlib.tests.test_symbol_versioning',
3985
 
        'bzrlib.tests.test_tag',
3986
 
        'bzrlib.tests.test_test_server',
3987
 
        'bzrlib.tests.test_testament',
3988
 
        'bzrlib.tests.test_textfile',
3989
 
        'bzrlib.tests.test_textmerge',
3990
 
        'bzrlib.tests.test_cethread',
3991
 
        'bzrlib.tests.test_timestamp',
3992
 
        'bzrlib.tests.test_trace',
3993
 
        'bzrlib.tests.test_transactions',
3994
 
        'bzrlib.tests.test_transform',
3995
 
        'bzrlib.tests.test_transport',
3996
 
        'bzrlib.tests.test_transport_log',
3997
 
        'bzrlib.tests.test_tree',
3998
 
        'bzrlib.tests.test_treebuilder',
3999
 
        'bzrlib.tests.test_treeshape',
4000
 
        'bzrlib.tests.test_tsort',
4001
 
        'bzrlib.tests.test_tuned_gzip',
4002
 
        'bzrlib.tests.test_ui',
4003
 
        'bzrlib.tests.test_uncommit',
4004
 
        'bzrlib.tests.test_upgrade',
4005
 
        'bzrlib.tests.test_upgrade_stacked',
4006
 
        'bzrlib.tests.test_urlutils',
4007
 
        'bzrlib.tests.test_utextwrap',
4008
 
        'bzrlib.tests.test_version',
4009
 
        'bzrlib.tests.test_version_info',
4010
 
        'bzrlib.tests.test_versionedfile',
4011
 
        'bzrlib.tests.test_weave',
4012
 
        'bzrlib.tests.test_whitebox',
4013
 
        'bzrlib.tests.test_win32utils',
4014
 
        'bzrlib.tests.test_workingtree',
4015
 
        'bzrlib.tests.test_workingtree_4',
4016
 
        'bzrlib.tests.test_wsgi',
4017
 
        'bzrlib.tests.test_xml',
4018
 
        ]
4019
 
 
4020
 
 
4021
 
def _test_suite_modules_to_doctest():
4022
 
    """Return the list of modules to doctest."""
4023
 
    if __doc__ is None:
4024
 
        # GZ 2009-03-31: No docstrings with -OO so there's nothing to doctest
4025
 
        return []
4026
 
    return [
4027
 
        'bzrlib',
4028
 
        'bzrlib.branchbuilder',
4029
 
        'bzrlib.decorators',
4030
 
        'bzrlib.inventory',
4031
 
        'bzrlib.iterablefile',
4032
 
        'bzrlib.lockdir',
4033
 
        'bzrlib.merge3',
4034
 
        'bzrlib.option',
4035
 
        'bzrlib.pyutils',
4036
 
        'bzrlib.symbol_versioning',
4037
 
        'bzrlib.tests',
4038
 
        'bzrlib.tests.fixtures',
4039
 
        'bzrlib.timestamp',
4040
 
        'bzrlib.transport.http',
4041
 
        'bzrlib.version_info_formats.format_custom',
4042
 
        ]
4043
 
 
4044
 
 
4045
3365
def test_suite(keep_only=None, starting_with=None):
4046
3366
    """Build and return TestSuite for the whole of bzrlib.
4047
3367
 
4053
3373
    This function can be replaced if you need to change the default test
4054
3374
    suite on a global basis, but it is not encouraged.
4055
3375
    """
 
3376
    testmod_names = [
 
3377
                   'bzrlib.doc',
 
3378
                   'bzrlib.tests.blackbox',
 
3379
                   'bzrlib.tests.commands',
 
3380
                   'bzrlib.tests.per_branch',
 
3381
                   'bzrlib.tests.per_bzrdir',
 
3382
                   'bzrlib.tests.per_interrepository',
 
3383
                   'bzrlib.tests.per_intertree',
 
3384
                   'bzrlib.tests.per_inventory',
 
3385
                   'bzrlib.tests.per_interbranch',
 
3386
                   'bzrlib.tests.per_lock',
 
3387
                   'bzrlib.tests.per_transport',
 
3388
                   'bzrlib.tests.per_tree',
 
3389
                   'bzrlib.tests.per_repository',
 
3390
                   'bzrlib.tests.per_repository_chk',
 
3391
                   'bzrlib.tests.per_repository_reference',
 
3392
                   'bzrlib.tests.per_workingtree',
 
3393
                   'bzrlib.tests.test__annotator',
 
3394
                   'bzrlib.tests.test__chk_map',
 
3395
                   'bzrlib.tests.test__dirstate_helpers',
 
3396
                   'bzrlib.tests.test__groupcompress',
 
3397
                   'bzrlib.tests.test__known_graph',
 
3398
                   'bzrlib.tests.test__rio',
 
3399
                   'bzrlib.tests.test__walkdirs_win32',
 
3400
                   'bzrlib.tests.test_ancestry',
 
3401
                   'bzrlib.tests.test_annotate',
 
3402
                   'bzrlib.tests.test_api',
 
3403
                   'bzrlib.tests.test_atomicfile',
 
3404
                   'bzrlib.tests.test_bad_files',
 
3405
                   'bzrlib.tests.test_bencode',
 
3406
                   'bzrlib.tests.test_bisect_multi',
 
3407
                   'bzrlib.tests.test_branch',
 
3408
                   'bzrlib.tests.test_branchbuilder',
 
3409
                   'bzrlib.tests.test_btree_index',
 
3410
                   'bzrlib.tests.test_bugtracker',
 
3411
                   'bzrlib.tests.test_bundle',
 
3412
                   'bzrlib.tests.test_bzrdir',
 
3413
                   'bzrlib.tests.test__chunks_to_lines',
 
3414
                   'bzrlib.tests.test_cache_utf8',
 
3415
                   'bzrlib.tests.test_chk_map',
 
3416
                   'bzrlib.tests.test_chk_serializer',
 
3417
                   'bzrlib.tests.test_chunk_writer',
 
3418
                   'bzrlib.tests.test_clean_tree',
 
3419
                   'bzrlib.tests.test_commands',
 
3420
                   'bzrlib.tests.test_commit',
 
3421
                   'bzrlib.tests.test_commit_merge',
 
3422
                   'bzrlib.tests.test_config',
 
3423
                   'bzrlib.tests.test_conflicts',
 
3424
                   'bzrlib.tests.test_counted_lock',
 
3425
                   'bzrlib.tests.test_decorators',
 
3426
                   'bzrlib.tests.test_delta',
 
3427
                   'bzrlib.tests.test_debug',
 
3428
                   'bzrlib.tests.test_deprecated_graph',
 
3429
                   'bzrlib.tests.test_diff',
 
3430
                   'bzrlib.tests.test_directory_service',
 
3431
                   'bzrlib.tests.test_dirstate',
 
3432
                   'bzrlib.tests.test_email_message',
 
3433
                   'bzrlib.tests.test_eol_filters',
 
3434
                   'bzrlib.tests.test_errors',
 
3435
                   'bzrlib.tests.test_export',
 
3436
                   'bzrlib.tests.test_extract',
 
3437
                   'bzrlib.tests.test_fetch',
 
3438
                   'bzrlib.tests.test_fifo_cache',
 
3439
                   'bzrlib.tests.test_filters',
 
3440
                   'bzrlib.tests.test_ftp_transport',
 
3441
                   'bzrlib.tests.test_foreign',
 
3442
                   'bzrlib.tests.test_generate_docs',
 
3443
                   'bzrlib.tests.test_generate_ids',
 
3444
                   'bzrlib.tests.test_globbing',
 
3445
                   'bzrlib.tests.test_gpg',
 
3446
                   'bzrlib.tests.test_graph',
 
3447
                   'bzrlib.tests.test_groupcompress',
 
3448
                   'bzrlib.tests.test_hashcache',
 
3449
                   'bzrlib.tests.test_help',
 
3450
                   'bzrlib.tests.test_hooks',
 
3451
                   'bzrlib.tests.test_http',
 
3452
                   'bzrlib.tests.test_http_response',
 
3453
                   'bzrlib.tests.test_https_ca_bundle',
 
3454
                   'bzrlib.tests.test_identitymap',
 
3455
                   'bzrlib.tests.test_ignores',
 
3456
                   'bzrlib.tests.test_index',
 
3457
                   'bzrlib.tests.test_info',
 
3458
                   'bzrlib.tests.test_inv',
 
3459
                   'bzrlib.tests.test_inventory_delta',
 
3460
                   'bzrlib.tests.test_knit',
 
3461
                   'bzrlib.tests.test_lazy_import',
 
3462
                   'bzrlib.tests.test_lazy_regex',
 
3463
                   'bzrlib.tests.test_lockable_files',
 
3464
                   'bzrlib.tests.test_lockdir',
 
3465
                   'bzrlib.tests.test_log',
 
3466
                   'bzrlib.tests.test_lru_cache',
 
3467
                   'bzrlib.tests.test_lsprof',
 
3468
                   'bzrlib.tests.test_mail_client',
 
3469
                   'bzrlib.tests.test_memorytree',
 
3470
                   'bzrlib.tests.test_merge',
 
3471
                   'bzrlib.tests.test_merge3',
 
3472
                   'bzrlib.tests.test_merge_core',
 
3473
                   'bzrlib.tests.test_merge_directive',
 
3474
                   'bzrlib.tests.test_missing',
 
3475
                   'bzrlib.tests.test_msgeditor',
 
3476
                   'bzrlib.tests.test_multiparent',
 
3477
                   'bzrlib.tests.test_mutabletree',
 
3478
                   'bzrlib.tests.test_nonascii',
 
3479
                   'bzrlib.tests.test_options',
 
3480
                   'bzrlib.tests.test_osutils',
 
3481
                   'bzrlib.tests.test_osutils_encodings',
 
3482
                   'bzrlib.tests.test_pack',
 
3483
                   'bzrlib.tests.test_pack_repository',
 
3484
                   'bzrlib.tests.test_patch',
 
3485
                   'bzrlib.tests.test_patches',
 
3486
                   'bzrlib.tests.test_permissions',
 
3487
                   'bzrlib.tests.test_plugins',
 
3488
                   'bzrlib.tests.test_progress',
 
3489
                   'bzrlib.tests.test_read_bundle',
 
3490
                   'bzrlib.tests.test_reconcile',
 
3491
                   'bzrlib.tests.test_reconfigure',
 
3492
                   'bzrlib.tests.test_registry',
 
3493
                   'bzrlib.tests.test_remote',
 
3494
                   'bzrlib.tests.test_rename_map',
 
3495
                   'bzrlib.tests.test_repository',
 
3496
                   'bzrlib.tests.test_revert',
 
3497
                   'bzrlib.tests.test_revision',
 
3498
                   'bzrlib.tests.test_revisionspec',
 
3499
                   'bzrlib.tests.test_revisiontree',
 
3500
                   'bzrlib.tests.test_rio',
 
3501
                   'bzrlib.tests.test_rules',
 
3502
                   'bzrlib.tests.test_sampler',
 
3503
                   'bzrlib.tests.test_selftest',
 
3504
                   'bzrlib.tests.test_serializer',
 
3505
                   'bzrlib.tests.test_setup',
 
3506
                   'bzrlib.tests.test_sftp_transport',
 
3507
                   'bzrlib.tests.test_shelf',
 
3508
                   'bzrlib.tests.test_shelf_ui',
 
3509
                   'bzrlib.tests.test_smart',
 
3510
                   'bzrlib.tests.test_smart_add',
 
3511
                   'bzrlib.tests.test_smart_request',
 
3512
                   'bzrlib.tests.test_smart_transport',
 
3513
                   'bzrlib.tests.test_smtp_connection',
 
3514
                   'bzrlib.tests.test_source',
 
3515
                   'bzrlib.tests.test_ssh_transport',
 
3516
                   'bzrlib.tests.test_status',
 
3517
                   'bzrlib.tests.test_store',
 
3518
                   'bzrlib.tests.test_strace',
 
3519
                   'bzrlib.tests.test_subsume',
 
3520
                   'bzrlib.tests.test_switch',
 
3521
                   'bzrlib.tests.test_symbol_versioning',
 
3522
                   'bzrlib.tests.test_tag',
 
3523
                   'bzrlib.tests.test_testament',
 
3524
                   'bzrlib.tests.test_textfile',
 
3525
                   'bzrlib.tests.test_textmerge',
 
3526
                   'bzrlib.tests.test_timestamp',
 
3527
                   'bzrlib.tests.test_trace',
 
3528
                   'bzrlib.tests.test_transactions',
 
3529
                   'bzrlib.tests.test_transform',
 
3530
                   'bzrlib.tests.test_transport',
 
3531
                   'bzrlib.tests.test_transport_log',
 
3532
                   'bzrlib.tests.test_tree',
 
3533
                   'bzrlib.tests.test_treebuilder',
 
3534
                   'bzrlib.tests.test_tsort',
 
3535
                   'bzrlib.tests.test_tuned_gzip',
 
3536
                   'bzrlib.tests.test_ui',
 
3537
                   'bzrlib.tests.test_uncommit',
 
3538
                   'bzrlib.tests.test_upgrade',
 
3539
                   'bzrlib.tests.test_upgrade_stacked',
 
3540
                   'bzrlib.tests.test_urlutils',
 
3541
                   'bzrlib.tests.test_version',
 
3542
                   'bzrlib.tests.test_version_info',
 
3543
                   'bzrlib.tests.test_versionedfile',
 
3544
                   'bzrlib.tests.test_weave',
 
3545
                   'bzrlib.tests.test_whitebox',
 
3546
                   'bzrlib.tests.test_win32utils',
 
3547
                   'bzrlib.tests.test_workingtree',
 
3548
                   'bzrlib.tests.test_workingtree_4',
 
3549
                   'bzrlib.tests.test_wsgi',
 
3550
                   'bzrlib.tests.test_xml',
 
3551
                   ]
4056
3552
 
4057
3553
    loader = TestUtil.TestLoader()
4058
3554
 
4059
3555
    if keep_only is not None:
4060
3556
        id_filter = TestIdList(keep_only)
4061
3557
    if starting_with:
 
3558
        starting_with = [test_prefix_alias_registry.resolve_alias(start)
 
3559
                         for start in starting_with]
4062
3560
        # We take precedence over keep_only because *at loading time* using
4063
3561
        # both options means we will load less tests for the same final result.
4064
3562
        def interesting_module(name):
4087
3585
    suite = loader.suiteClass()
4088
3586
 
4089
3587
    # modules building their suite with loadTestsFromModuleNames
4090
 
    suite.addTest(loader.loadTestsFromModuleNames(_test_suite_testmod_names()))
4091
 
 
4092
 
    for mod in _test_suite_modules_to_doctest():
 
3588
    suite.addTest(loader.loadTestsFromModuleNames(testmod_names))
 
3589
 
 
3590
    modules_to_doctest = [
 
3591
        'bzrlib',
 
3592
        'bzrlib.branchbuilder',
 
3593
        'bzrlib.export',
 
3594
        'bzrlib.inventory',
 
3595
        'bzrlib.iterablefile',
 
3596
        'bzrlib.lockdir',
 
3597
        'bzrlib.merge3',
 
3598
        'bzrlib.option',
 
3599
        'bzrlib.symbol_versioning',
 
3600
        'bzrlib.tests',
 
3601
        'bzrlib.timestamp',
 
3602
        'bzrlib.version_info_formats.format_custom',
 
3603
        ]
 
3604
 
 
3605
    for mod in modules_to_doctest:
4093
3606
        if not interesting_module(mod):
4094
3607
            # No tests to keep here, move along
4095
3608
            continue
4096
3609
        try:
4097
3610
            # note that this really does mean "report only" -- doctest
4098
3611
            # still runs the rest of the examples
4099
 
            doc_suite = IsolatedDocTestSuite(
4100
 
                mod, optionflags=doctest.REPORT_ONLY_FIRST_FAILURE)
 
3612
            doc_suite = doctest.DocTestSuite(mod,
 
3613
                optionflags=doctest.REPORT_ONLY_FIRST_FAILURE)
4101
3614
        except ValueError, e:
4102
3615
            print '**failed to get doctest for: %s\n%s' % (mod, e)
4103
3616
            raise
4106
3619
        suite.addTest(doc_suite)
4107
3620
 
4108
3621
    default_encoding = sys.getdefaultencoding()
4109
 
    for name, plugin in _mod_plugin.plugins().items():
 
3622
    for name, plugin in bzrlib.plugin.plugins().items():
4110
3623
        if not interesting_module(plugin.module.__name__):
4111
3624
            continue
4112
3625
        plugin_suite = plugin.test_suite()
4118
3631
        if plugin_suite is not None:
4119
3632
            suite.addTest(plugin_suite)
4120
3633
        if default_encoding != sys.getdefaultencoding():
4121
 
            trace.warning(
 
3634
            bzrlib.trace.warning(
4122
3635
                'Plugin "%s" tried to reset default encoding to: %s', name,
4123
3636
                sys.getdefaultencoding())
4124
3637
            reload(sys)
4125
3638
            sys.setdefaultencoding(default_encoding)
4126
3639
 
 
3640
    if starting_with:
 
3641
        suite = filter_suite_by_id_startswith(suite, starting_with)
 
3642
 
4127
3643
    if keep_only is not None:
4128
3644
        # Now that the referred modules have loaded their tests, keep only the
4129
3645
        # requested ones.
4139
3655
            # Some tests mentioned in the list are not in the test suite. The
4140
3656
            # list may be out of date, report to the tester.
4141
3657
            for id in not_found:
4142
 
                trace.warning('"%s" not found in the test suite', id)
 
3658
                bzrlib.trace.warning('"%s" not found in the test suite', id)
4143
3659
        for id in duplicates:
4144
 
            trace.warning('"%s" is used as an id by several tests', id)
 
3660
            bzrlib.trace.warning('"%s" is used as an id by several tests', id)
4145
3661
 
4146
3662
    return suite
4147
3663
 
4148
3664
 
4149
 
def multiply_scenarios(*scenarios):
4150
 
    """Multiply two or more iterables of scenarios.
4151
 
 
4152
 
    It is safe to pass scenario generators or iterators.
4153
 
 
4154
 
    :returns: A list of compound scenarios: the cross-product of all 
4155
 
        scenarios, with the names concatenated and the parameters
4156
 
        merged together.
4157
 
    """
4158
 
    return reduce(_multiply_two_scenarios, map(list, scenarios))
4159
 
 
4160
 
 
4161
 
def _multiply_two_scenarios(scenarios_left, scenarios_right):
 
3665
def multiply_scenarios(scenarios_left, scenarios_right):
4162
3666
    """Multiply two sets of scenarios.
4163
3667
 
4164
3668
    :returns: the cartesian product of the two sets of scenarios, that is
4195
3699
    ...     bzrlib.tests.test_sampler.DemoTest('test_nothing'),
4196
3700
    ...     [('one', dict(param=1)),
4197
3701
    ...      ('two', dict(param=2))],
4198
 
    ...     TestUtil.TestSuite())
 
3702
    ...     TestSuite())
4199
3703
    >>> tests = list(iter_suite_tests(r))
4200
3704
    >>> len(tests)
4201
3705
    2
4248
3752
    :param new_id: The id to assign to it.
4249
3753
    :return: The new test.
4250
3754
    """
4251
 
    new_test = copy.copy(test)
 
3755
    from copy import deepcopy
 
3756
    new_test = deepcopy(test)
4252
3757
    new_test.id = lambda: new_id
4253
 
    # XXX: Workaround <https://bugs.launchpad.net/testtools/+bug/637725>, which
4254
 
    # causes cloned tests to share the 'details' dict.  This makes it hard to
4255
 
    # read the test output for parameterized tests, because tracebacks will be
4256
 
    # associated with irrelevant tests.
4257
 
    try:
4258
 
        details = new_test._TestCase__details
4259
 
    except AttributeError:
4260
 
        # must be a different version of testtools than expected.  Do nothing.
4261
 
        pass
4262
 
    else:
4263
 
        # Reset the '__details' dict.
4264
 
        new_test._TestCase__details = {}
4265
3758
    return new_test
4266
3759
 
4267
3760
 
4268
 
def permute_tests_for_extension(standard_tests, loader, py_module_name,
4269
 
                                ext_module_name):
4270
 
    """Helper for permutating tests against an extension module.
4271
 
 
4272
 
    This is meant to be used inside a modules 'load_tests()' function. It will
4273
 
    create 2 scenarios, and cause all tests in the 'standard_tests' to be run
4274
 
    against both implementations. Setting 'test.module' to the appropriate
4275
 
    module. See bzrlib.tests.test__chk_map.load_tests as an example.
4276
 
 
4277
 
    :param standard_tests: A test suite to permute
4278
 
    :param loader: A TestLoader
4279
 
    :param py_module_name: The python path to a python module that can always
4280
 
        be loaded, and will be considered the 'python' implementation. (eg
4281
 
        'bzrlib._chk_map_py')
4282
 
    :param ext_module_name: The python path to an extension module. If the
4283
 
        module cannot be loaded, a single test will be added, which notes that
4284
 
        the module is not available. If it can be loaded, all standard_tests
4285
 
        will be run against that module.
4286
 
    :return: (suite, feature) suite is a test-suite that has all the permuted
4287
 
        tests. feature is the Feature object that can be used to determine if
4288
 
        the module is available.
4289
 
    """
4290
 
 
4291
 
    py_module = pyutils.get_named_object(py_module_name)
4292
 
    scenarios = [
4293
 
        ('python', {'module': py_module}),
4294
 
    ]
4295
 
    suite = loader.suiteClass()
4296
 
    feature = ModuleAvailableFeature(ext_module_name)
4297
 
    if feature.available():
4298
 
        scenarios.append(('C', {'module': feature.module}))
4299
 
    else:
4300
 
        # the compiled module isn't available, so we add a failing test
4301
 
        class FailWithoutFeature(TestCase):
4302
 
            def test_fail(self):
4303
 
                self.requireFeature(feature)
4304
 
        suite.addTest(loader.loadTestsFromTestCase(FailWithoutFeature))
4305
 
    result = multiply_tests(standard_tests, scenarios, suite)
4306
 
    return result, feature
4307
 
 
4308
 
 
4309
 
def _rmtree_temp_dir(dirname, test_id=None):
 
3761
def _rmtree_temp_dir(dirname):
4310
3762
    # If LANG=C we probably have created some bogus paths
4311
3763
    # which rmtree(unicode) will fail to delete
4312
3764
    # so make sure we are using rmtree(str) to delete everything
4321
3773
    try:
4322
3774
        osutils.rmtree(dirname)
4323
3775
    except OSError, e:
4324
 
        # We don't want to fail here because some useful display will be lost
4325
 
        # otherwise. Polluting the tmp dir is bad, but not giving all the
4326
 
        # possible info to the test runner is even worse.
4327
 
        if test_id != None:
4328
 
            ui.ui_factory.clear_term()
4329
 
            sys.stderr.write('\nWhile running: %s\n' % (test_id,))
4330
 
        # Ugly, but the last thing we want here is fail, so bear with it.
4331
 
        printable_e = str(e).decode(osutils.get_user_encoding(), 'replace'
4332
 
                                    ).encode('ascii', 'replace')
4333
 
        sys.stderr.write('Unable to remove testing dir %s\n%s'
4334
 
                         % (os.path.basename(dirname), printable_e))
 
3776
        if sys.platform == 'win32' and e.errno == errno.EACCES:
 
3777
            sys.stderr.write('Permission denied: '
 
3778
                             'unable to remove testing dir '
 
3779
                             '%s\n%s'
 
3780
                             % (os.path.basename(dirname), e))
 
3781
        else:
 
3782
            raise
4335
3783
 
4336
3784
 
4337
3785
class Feature(object):
4419
3867
UnicodeFilenameFeature = _UnicodeFilenameFeature()
4420
3868
 
4421
3869
 
4422
 
class _CompatabilityThunkFeature(Feature):
4423
 
    """This feature is just a thunk to another feature.
4424
 
 
4425
 
    It issues a deprecation warning if it is accessed, to let you know that you
4426
 
    should really use a different feature.
4427
 
    """
4428
 
 
4429
 
    def __init__(self, dep_version, module, name,
4430
 
                 replacement_name, replacement_module=None):
4431
 
        super(_CompatabilityThunkFeature, self).__init__()
4432
 
        self._module = module
4433
 
        if replacement_module is None:
4434
 
            replacement_module = module
4435
 
        self._replacement_module = replacement_module
4436
 
        self._name = name
4437
 
        self._replacement_name = replacement_name
4438
 
        self._dep_version = dep_version
4439
 
        self._feature = None
4440
 
 
4441
 
    def _ensure(self):
4442
 
        if self._feature is None:
4443
 
            depr_msg = self._dep_version % ('%s.%s'
4444
 
                                            % (self._module, self._name))
4445
 
            use_msg = ' Use %s.%s instead.' % (self._replacement_module,
4446
 
                                               self._replacement_name)
4447
 
            symbol_versioning.warn(depr_msg + use_msg, DeprecationWarning)
4448
 
            # Import the new feature and use it as a replacement for the
4449
 
            # deprecated one.
4450
 
            self._feature = pyutils.get_named_object(
4451
 
                self._replacement_module, self._replacement_name)
4452
 
 
4453
 
    def _probe(self):
4454
 
        self._ensure()
4455
 
        return self._feature._probe()
4456
 
 
4457
 
 
4458
 
class ModuleAvailableFeature(Feature):
4459
 
    """This is a feature than describes a module we want to be available.
4460
 
 
4461
 
    Declare the name of the module in __init__(), and then after probing, the
4462
 
    module will be available as 'self.module'.
4463
 
 
4464
 
    :ivar module: The module if it is available, else None.
4465
 
    """
4466
 
 
4467
 
    def __init__(self, module_name):
4468
 
        super(ModuleAvailableFeature, self).__init__()
4469
 
        self.module_name = module_name
4470
 
 
4471
 
    def _probe(self):
4472
 
        try:
4473
 
            self._module = __import__(self.module_name, {}, {}, [''])
4474
 
            return True
4475
 
        except ImportError:
4476
 
            return False
4477
 
 
4478
 
    @property
4479
 
    def module(self):
4480
 
        if self.available(): # Make sure the probe has been done
4481
 
            return self._module
4482
 
        return None
4483
 
 
4484
 
    def feature_name(self):
4485
 
        return self.module_name
4486
 
 
4487
 
 
4488
3870
def probe_unicode_in_user_encoding():
4489
3871
    """Try to encode several unicode strings to use in unicode-aware tests.
4490
3872
    Return first successfull match.
4559
3941
UnicodeFilename = _UnicodeFilename()
4560
3942
 
4561
3943
 
4562
 
class _ByteStringNamedFilesystem(Feature):
4563
 
    """Is the filesystem based on bytes?"""
4564
 
 
4565
 
    def _probe(self):
4566
 
        if os.name == "posix":
4567
 
            return True
4568
 
        return False
4569
 
 
4570
 
ByteStringNamedFilesystem = _ByteStringNamedFilesystem()
4571
 
 
4572
 
 
4573
3944
class _UTF8Filesystem(Feature):
4574
3945
    """Is the filesystem UTF-8?"""
4575
3946
 
4581
3952
UTF8Filesystem = _UTF8Filesystem()
4582
3953
 
4583
3954
 
4584
 
class _BreakinFeature(Feature):
4585
 
    """Does this platform support the breakin feature?"""
4586
 
 
4587
 
    def _probe(self):
4588
 
        from bzrlib import breakin
4589
 
        if breakin.determine_signal() is None:
4590
 
            return False
4591
 
        if sys.platform == 'win32':
4592
 
            # Windows doesn't have os.kill, and we catch the SIGBREAK signal.
4593
 
            # We trigger SIGBREAK via a Console api so we need ctypes to
4594
 
            # access the function
4595
 
            try:
4596
 
                import ctypes
4597
 
            except OSError:
4598
 
                return False
4599
 
        return True
4600
 
 
4601
 
    def feature_name(self):
4602
 
        return "SIGQUIT or SIGBREAK w/ctypes on win32"
4603
 
 
4604
 
 
4605
 
BreakinFeature = _BreakinFeature()
4606
 
 
4607
 
 
4608
3955
class _CaseInsCasePresFilenameFeature(Feature):
4609
3956
    """Is the file-system case insensitive, but case-preserving?"""
4610
3957
 
4660
4007
CaseInsensitiveFilesystemFeature = _CaseInsensitiveFilesystemFeature()
4661
4008
 
4662
4009
 
4663
 
class _CaseSensitiveFilesystemFeature(Feature):
 
4010
class _SubUnitFeature(Feature):
 
4011
    """Check if subunit is available."""
4664
4012
 
4665
4013
    def _probe(self):
4666
 
        if CaseInsCasePresFilenameFeature.available():
4667
 
            return False
4668
 
        elif CaseInsensitiveFilesystemFeature.available():
4669
 
            return False
4670
 
        else:
 
4014
        try:
 
4015
            import subunit
4671
4016
            return True
 
4017
        except ImportError:
 
4018
            return False
4672
4019
 
4673
4020
    def feature_name(self):
4674
 
        return 'case-sensitive filesystem'
4675
 
 
4676
 
# new coding style is for feature instances to be lowercase
4677
 
case_sensitive_filesystem_feature = _CaseSensitiveFilesystemFeature()
4678
 
 
4679
 
 
 
4021
        return 'subunit'
 
4022
 
 
4023
SubUnitFeature = _SubUnitFeature()
4680
4024
# Only define SubUnitBzrRunner if subunit is available.
4681
4025
try:
4682
4026
    from subunit import TestProtocolClient
4683
 
    from subunit.test_results import AutoTimingTestResultDecorator
4684
 
    class SubUnitBzrProtocolClient(TestProtocolClient):
4685
 
 
4686
 
        def addSuccess(self, test, details=None):
4687
 
            # The subunit client always includes the details in the subunit
4688
 
            # stream, but we don't want to include it in ours.
4689
 
            if details is not None and 'log' in details:
4690
 
                del details['log']
4691
 
            return super(SubUnitBzrProtocolClient, self).addSuccess(
4692
 
                test, details)
4693
 
 
 
4027
    try:
 
4028
        from subunit.test_results import AutoTimingTestResultDecorator
 
4029
    except ImportError:
 
4030
        AutoTimingTestResultDecorator = lambda x:x
4694
4031
    class SubUnitBzrRunner(TextTestRunner):
4695
4032
        def run(self, test):
4696
4033
            result = AutoTimingTestResultDecorator(
4697
 
                SubUnitBzrProtocolClient(self.stream))
 
4034
                TestProtocolClient(self.stream))
4698
4035
            test.run(result)
4699
4036
            return result
4700
4037
except ImportError:
4701
4038
    pass
4702
 
 
4703
 
class _PosixPermissionsFeature(Feature):
4704
 
 
4705
 
    def _probe(self):
4706
 
        def has_perms():
4707
 
            # create temporary file and check if specified perms are maintained.
4708
 
            import tempfile
4709
 
 
4710
 
            write_perms = stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR
4711
 
            f = tempfile.mkstemp(prefix='bzr_perms_chk_')
4712
 
            fd, name = f
4713
 
            os.close(fd)
4714
 
            os.chmod(name, write_perms)
4715
 
 
4716
 
            read_perms = os.stat(name).st_mode & 0777
4717
 
            os.unlink(name)
4718
 
            return (write_perms == read_perms)
4719
 
 
4720
 
        return (os.name == 'posix') and has_perms()
4721
 
 
4722
 
    def feature_name(self):
4723
 
        return 'POSIX permissions support'
4724
 
 
4725
 
posix_permissions_feature = _PosixPermissionsFeature()