~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/__init__.py

  • Committer: Ian Clatworthy
  • Date: 2009-09-09 15:30:59 UTC
  • mto: (4634.37.2 prepare-2.0)
  • mto: This revision was merged to the branch mainline in revision 4689.
  • Revision ID: ian.clatworthy@canonical.com-20090909153059-sb038agvd38ci2q8
more link fixes in the User Guide

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2013, 2015, 2016 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
 
from __future__ import absolute_import
 
18
# TODO: Perhaps there should be an API to find out if bzr running under the
 
19
# test suite -- some plugins might want to avoid making intrusive changes if
 
20
# this is the case.  However, we want behaviour under to test to diverge as
 
21
# little as possible, so this should be used rarely if it's added at all.
 
22
# (Suggestion from j-a-meinel, 2005-11-24)
20
23
 
21
24
# NOTE: Some classes in here use camelCaseNaming() rather than
22
25
# underscore_naming().  That's for consistency with unittest; it's not the
25
28
 
26
29
import atexit
27
30
import codecs
28
 
import copy
29
31
from cStringIO import StringIO
30
32
import difflib
31
33
import doctest
32
34
import errno
33
 
import itertools
34
35
import logging
35
36
import math
36
37
import os
37
 
import platform
38
 
import pprint
 
38
from pprint import pformat
39
39
import random
40
40
import re
41
41
import shlex
42
 
import site
43
42
import stat
44
 
import subprocess
 
43
from subprocess import Popen, PIPE, STDOUT
45
44
import sys
46
45
import tempfile
47
46
import threading
48
47
import time
49
 
import traceback
50
48
import unittest
51
49
import warnings
52
50
 
53
 
import testtools
54
 
# nb: check this before importing anything else from within it
55
 
_testtools_version = getattr(testtools, '__version__', ())
56
 
if _testtools_version < (0, 9, 5):
57
 
    raise ImportError("need at least testtools 0.9.5: %s is %r"
58
 
        % (testtools.__file__, _testtools_version))
59
 
from testtools import content
60
51
 
61
 
import bzrlib
62
52
from bzrlib import (
63
53
    branchbuilder,
64
 
    controldir,
65
 
    chk_map,
66
 
    commands as _mod_commands,
67
 
    config,
68
 
    i18n,
 
54
    bzrdir,
69
55
    debug,
70
56
    errors,
71
57
    hooks,
72
58
    lock as _mod_lock,
73
 
    lockdir,
74
59
    memorytree,
75
60
    osutils,
76
 
    plugin as _mod_plugin,
77
 
    pyutils,
 
61
    progress,
78
62
    ui,
79
63
    urlutils,
80
64
    registry,
81
 
    symbol_versioning,
82
 
    trace,
83
 
    transport as _mod_transport,
84
65
    workingtree,
85
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
86
74
try:
87
75
    import bzrlib.lsprof
88
76
except ImportError:
89
77
    # lsprof not available
90
78
    pass
91
 
from bzrlib.smart import client, request
92
 
from bzrlib.transport import (
93
 
    memory,
94
 
    pathfilter,
95
 
    )
 
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
96
85
from bzrlib.symbol_versioning import (
 
86
    DEPRECATED_PARAMETER,
97
87
    deprecated_function,
98
 
    deprecated_in,
99
 
    )
100
 
from bzrlib.tests import (
101
 
    fixtures,
102
 
    test_server,
103
 
    TestUtil,
104
 
    treeshape,
105
 
    )
 
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
106
105
from bzrlib.ui import NullProgressView
107
106
from bzrlib.ui.text import TextUIFactory
108
 
from bzrlib.tests.features import _CompatabilityThunkFeature
 
107
import bzrlib.version_info_formats.format_custom
 
108
from bzrlib.workingtree import WorkingTree, WorkingTreeFormat2
109
109
 
110
110
# Mark this python module as being part of the implementation
111
111
# of unittest: this gives us better tracebacks where the last
112
112
# shown frame is the test code, not our assertXYZ.
113
113
__unittest = 1
114
114
 
115
 
default_transport = test_server.LocalURLServer
116
 
 
117
 
 
118
 
_unitialized_attr = object()
119
 
"""A sentinel needed to act as a default value in a method signature."""
120
 
 
 
115
default_transport = LocalURLServer
121
116
 
122
117
# Subunit result codes, defined here to prevent a hard dependency on subunit.
123
118
SUBUNIT_SEEK_SET = 0
124
119
SUBUNIT_SEEK_CUR = 1
125
120
 
126
 
# These are intentionally brought into this namespace. That way plugins, etc
127
 
# can just "from bzrlib.tests import TestCase, TestLoader, etc"
128
 
TestSuite = TestUtil.TestSuite
129
 
TestLoader = TestUtil.TestLoader
130
 
 
131
 
# Tests should run in a clean and clearly defined environment. The goal is to
132
 
# keep them isolated from the running environment as mush as possible. The test
133
 
# framework ensures the variables defined below are set (or deleted if the
134
 
# value is None) before a test is run and reset to their original value after
135
 
# the test is run. Generally if some code depends on an environment variable,
136
 
# the tests should start without this variable in the environment. There are a
137
 
# few exceptions but you shouldn't violate this rule lightly.
138
 
isolated_environ = {
139
 
    'BZR_HOME': None,
140
 
    'HOME': None,
141
 
    'XDG_CONFIG_HOME': None,
142
 
    # bzr now uses the Win32 API and doesn't rely on APPDATA, but the
143
 
    # tests do check our impls match APPDATA
144
 
    'BZR_EDITOR': None, # test_msgeditor manipulates this variable
145
 
    'VISUAL': None,
146
 
    'EDITOR': None,
147
 
    'BZR_EMAIL': None,
148
 
    'BZREMAIL': None, # may still be present in the environment
149
 
    'EMAIL': 'jrandom@example.com', # set EMAIL as bzr does not guess
150
 
    'BZR_PROGRESS_BAR': None,
151
 
    # This should trap leaks to ~/.bzr.log. This occurs when tests use TestCase
152
 
    # as a base class instead of TestCaseInTempDir. Tests inheriting from
153
 
    # TestCase should not use disk resources, BZR_LOG is one.
154
 
    'BZR_LOG': '/you-should-use-TestCaseInTempDir-if-you-need-a-log-file',
155
 
    'BZR_PLUGIN_PATH': None,
156
 
    'BZR_DISABLE_PLUGINS': None,
157
 
    'BZR_PLUGINS_AT': None,
158
 
    'BZR_CONCURRENCY': None,
159
 
    # Make sure that any text ui tests are consistent regardless of
160
 
    # the environment the test case is run in; you may want tests that
161
 
    # test other combinations.  'dumb' is a reasonable guess for tests
162
 
    # going to a pipe or a StringIO.
163
 
    'TERM': 'dumb',
164
 
    'LINES': '25',
165
 
    'COLUMNS': '80',
166
 
    'BZR_COLUMNS': '80',
167
 
    # Disable SSH Agent
168
 
    'SSH_AUTH_SOCK': None,
169
 
    # Proxies
170
 
    'http_proxy': None,
171
 
    'HTTP_PROXY': None,
172
 
    'https_proxy': None,
173
 
    'HTTPS_PROXY': None,
174
 
    'no_proxy': None,
175
 
    'NO_PROXY': None,
176
 
    'all_proxy': None,
177
 
    'ALL_PROXY': None,
178
 
    # Nobody cares about ftp_proxy, FTP_PROXY AFAIK. So far at
179
 
    # least. If you do (care), please update this comment
180
 
    # -- vila 20080401
181
 
    'ftp_proxy': None,
182
 
    'FTP_PROXY': None,
183
 
    'BZR_REMOTE_PATH': None,
184
 
    # Generally speaking, we don't want apport reporting on crashes in
185
 
    # the test envirnoment unless we're specifically testing apport,
186
 
    # so that it doesn't leak into the real system environment.  We
187
 
    # use an env var so it propagates to subprocesses.
188
 
    'APPORT_DISABLE': '1',
189
 
    }
190
 
 
191
 
 
192
 
def override_os_environ(test, env=None):
193
 
    """Modify os.environ keeping a copy.
194
 
    
195
 
    :param test: A test instance
196
 
 
197
 
    :param env: A dict containing variable definitions to be installed
198
 
    """
199
 
    if env is None:
200
 
        env = isolated_environ
201
 
    test._original_os_environ = dict([(var, value)
202
 
                                      for var, value in os.environ.iteritems()])
203
 
    for var, value in env.iteritems():
204
 
        osutils.set_or_unset_env(var, value)
205
 
        if var not in test._original_os_environ:
206
 
            # The var is new, add it with a value of None, so
207
 
            # restore_os_environ will delete it
208
 
            test._original_os_environ[var] = None
209
 
 
210
 
 
211
 
def restore_os_environ(test):
212
 
    """Restore os.environ to its original state.
213
 
 
214
 
    :param test: A test instance previously passed to override_os_environ.
215
 
    """
216
 
    for var, value in test._original_os_environ.iteritems():
217
 
        # Restore the original value (or delete it if the value has been set to
218
 
        # None in override_os_environ).
219
 
        osutils.set_or_unset_env(var, value)
220
 
 
221
 
 
222
 
def _clear__type_equality_funcs(test):
223
 
    """Cleanup bound methods stored on TestCase instances
224
 
 
225
 
    Clear the dict breaking a few (mostly) harmless cycles in the affected
226
 
    unittests released with Python 2.6 and initial Python 2.7 versions.
227
 
 
228
 
    For a few revisions between Python 2.7.1 and Python 2.7.2 that annoyingly
229
 
    shipped in Oneiric, an object with no clear method was used, hence the
230
 
    extra complications, see bug 809048 for details.
231
 
    """
232
 
    type_equality_funcs = getattr(test, "_type_equality_funcs", None)
233
 
    if type_equality_funcs is not None:
234
 
        tef_clear = getattr(type_equality_funcs, "clear", None)
235
 
        if tef_clear is None:
236
 
            tef_instance_dict = getattr(type_equality_funcs, "__dict__", None)
237
 
            if tef_instance_dict is not None:
238
 
                tef_clear = tef_instance_dict.clear
239
 
        if tef_clear is not None:
240
 
            tef_clear()
241
 
 
242
 
 
243
 
class ExtendedTestResult(testtools.TextTestResult):
 
121
 
 
122
class ExtendedTestResult(unittest._TextTestResult):
244
123
    """Accepts, reports and accumulates the results of running tests.
245
124
 
246
125
    Compared to the unittest version this class adds support for
249
128
    different types of display.
250
129
 
251
130
    When a test finishes, in whatever way, it calls one of the addSuccess,
252
 
    addFailure or addError methods.  These in turn may redirect to a more
 
131
    addFailure or addError classes.  These in turn may redirect to a more
253
132
    specific case for the special test results supported by our extended
254
133
    tests.
255
134
 
267
146
        :param bench_history: Optionally, a writable file object to accumulate
268
147
            benchmark results.
269
148
        """
270
 
        testtools.TextTestResult.__init__(self, stream)
 
149
        unittest._TextTestResult.__init__(self, stream, descriptions, verbosity)
271
150
        if bench_history is not None:
272
151
            from bzrlib.version import _get_bzr_source_tree
273
152
            src_tree = _get_bzr_source_tree()
294
173
        self.count = 0
295
174
        self._overall_start_time = time.time()
296
175
        self._strict = strict
297
 
        self._first_thread_leaker_id = None
298
 
        self._tests_leaking_threads_count = 0
299
 
        self._traceback_from_test = None
300
176
 
301
 
    def stopTestRun(self):
302
 
        run = self.testsRun
303
 
        actionTaken = "Ran"
304
 
        stopTime = time.time()
305
 
        timeTaken = stopTime - self.startTime
306
 
        # GZ 2010-07-19: Seems testtools has no printErrors method, and though
307
 
        #                the parent class method is similar have to duplicate
308
 
        self._show_list('ERROR', self.errors)
309
 
        self._show_list('FAIL', self.failures)
310
 
        self.stream.write(self.sep2)
311
 
        self.stream.write("%s %d test%s in %.3fs\n\n" % (actionTaken,
312
 
                            run, run != 1 and "s" or "", timeTaken))
313
 
        if not self.wasSuccessful():
314
 
            self.stream.write("FAILED (")
315
 
            failed, errored = map(len, (self.failures, self.errors))
316
 
            if failed:
317
 
                self.stream.write("failures=%d" % failed)
318
 
            if errored:
319
 
                if failed: self.stream.write(", ")
320
 
                self.stream.write("errors=%d" % errored)
321
 
            if self.known_failure_count:
322
 
                if failed or errored: self.stream.write(", ")
323
 
                self.stream.write("known_failure_count=%d" %
324
 
                    self.known_failure_count)
325
 
            self.stream.write(")\n")
326
 
        else:
327
 
            if self.known_failure_count:
328
 
                self.stream.write("OK (known_failures=%d)\n" %
329
 
                    self.known_failure_count)
330
 
            else:
331
 
                self.stream.write("OK\n")
332
 
        if self.skip_count > 0:
333
 
            skipped = self.skip_count
334
 
            self.stream.write('%d test%s skipped\n' %
335
 
                                (skipped, skipped != 1 and "s" or ""))
336
 
        if self.unsupported:
337
 
            for feature, count in sorted(self.unsupported.items()):
338
 
                self.stream.write("Missing feature '%s' skipped %d tests.\n" %
339
 
                    (feature, count))
 
177
    def done(self):
 
178
        # nb: called stopTestRun in the version of this that Python merged
 
179
        # upstream, according to lifeless 20090803
340
180
        if self._strict:
341
181
            ok = self.wasStrictlySuccessful()
342
182
        else:
343
183
            ok = self.wasSuccessful()
344
 
        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:
345
189
            self.stream.write(
346
190
                '%s is leaking threads among %d leaking tests.\n' % (
347
 
                self._first_thread_leaker_id,
348
 
                self._tests_leaking_threads_count))
349
 
            # We don't report the main thread as an active one.
350
 
            self.stream.write(
351
 
                '%d non-main threads were left active in the end.\n'
352
 
                % (len(self._active_threads) - 1))
353
 
 
354
 
    def getDescription(self, test):
355
 
        return test.id()
356
 
 
357
 
    def _extractBenchmarkTime(self, testCase, details=None):
 
191
                TestCase._first_thread_leaker_id,
 
192
                TestCase._leaking_threads_tests))
 
193
 
 
194
    def _extractBenchmarkTime(self, testCase):
358
195
        """Add a benchmark time for the current test case."""
359
 
        if details and 'benchtime' in details:
360
 
            return float(''.join(details['benchtime'].iter_bytes()))
361
196
        return getattr(testCase, "_benchtime", None)
362
197
 
363
 
    def _delta_to_float(self, a_timedelta, precision):
364
 
        # This calls ceiling to ensure that the most pessimistic view of time
365
 
        # taken is shown (rather than leaving it to the Python %f operator
366
 
        # to decide whether to round/floor/ceiling. This was added when we
367
 
        # had pyp3 test failures that suggest a floor was happening.
368
 
        shift = 10 ** precision
369
 
        return math.ceil((a_timedelta.days * 86400.0 + a_timedelta.seconds +
370
 
            a_timedelta.microseconds / 1000000.0) * shift) / shift
371
 
 
372
198
    def _elapsedTestTimeString(self):
373
199
        """Return a time string for the overall time the current test has taken."""
374
 
        return self._formatTime(self._delta_to_float(
375
 
            self._now() - self._start_datetime, 3))
 
200
        return self._formatTime(time.time() - self._start_time)
376
201
 
377
202
    def _testTimeString(self, testCase):
378
203
        benchmark_time = self._extractBenchmarkTime(testCase)
389
214
 
390
215
    def _shortened_test_description(self, test):
391
216
        what = test.id()
392
 
        what = re.sub(r'^bzrlib\.tests\.', '', what)
 
217
        what = re.sub(r'^bzrlib\.(tests|benchmarks)\.', '', what)
393
218
        return what
394
219
 
395
 
    # GZ 2010-10-04: Cloned tests may end up harmlessly calling this method
396
 
    #                multiple times in a row, because the handler is added for
397
 
    #                each test but the container list is shared between cases.
398
 
    #                See lp:498869 lp:625574 and lp:637725 for background.
399
 
    def _record_traceback_from_test(self, exc_info):
400
 
        """Store the traceback from passed exc_info tuple till"""
401
 
        self._traceback_from_test = exc_info[2]
402
 
 
403
220
    def startTest(self, test):
404
 
        super(ExtendedTestResult, self).startTest(test)
 
221
        unittest.TestResult.startTest(self, test)
405
222
        if self.count == 0:
406
223
            self.startTests()
407
 
        self.count += 1
408
224
        self.report_test_start(test)
409
225
        test.number = self.count
410
226
        self._recordTestStartTime()
411
 
        # Make testtools cases give us the real traceback on failure
412
 
        addOnException = getattr(test, "addOnException", None)
413
 
        if addOnException is not None:
414
 
            addOnException(self._record_traceback_from_test)
415
 
        # Only check for thread leaks on bzrlib derived test cases
416
 
        if isinstance(test, TestCase):
417
 
            test.addCleanup(self._check_leaked_threads, test)
418
 
 
419
 
    def stopTest(self, test):
420
 
        super(ExtendedTestResult, self).stopTest(test)
421
 
        # Manually break cycles, means touching various private things but hey
422
 
        getDetails = getattr(test, "getDetails", None)
423
 
        if getDetails is not None:
424
 
            getDetails().clear()
425
 
        _clear__type_equality_funcs(test)
426
 
        self._traceback_from_test = None
427
227
 
428
228
    def startTests(self):
429
 
        self.report_tests_starting()
430
 
        self._active_threads = threading.enumerate()
431
 
 
432
 
    def _check_leaked_threads(self, test):
433
 
        """See if any threads have leaked since last call
434
 
 
435
 
        A sample of live threads is stored in the _active_threads attribute,
436
 
        when this method runs it compares the current live threads and any not
437
 
        in the previous sample are treated as having leaked.
438
 
        """
439
 
        now_active_threads = set(threading.enumerate())
440
 
        threads_leaked = now_active_threads.difference(self._active_threads)
441
 
        if threads_leaked:
442
 
            self._report_thread_leak(test, threads_leaked, now_active_threads)
443
 
            self._tests_leaking_threads_count += 1
444
 
            if self._first_thread_leaker_id is None:
445
 
                self._first_thread_leaker_id = test.id()
446
 
            self._active_threads = now_active_threads
 
229
        import platform
 
230
        if getattr(sys, 'frozen', None) is None:
 
231
            bzr_path = osutils.realpath(sys.argv[0])
 
232
        else:
 
233
            bzr_path = sys.executable
 
234
        self.stream.write(
 
235
            'testing: %s\n' % (bzr_path,))
 
236
        self.stream.write(
 
237
            '   %s\n' % (
 
238
                    bzrlib.__path__[0],))
 
239
        self.stream.write(
 
240
            '   bzr-%s python-%s %s\n' % (
 
241
                    bzrlib.version_string,
 
242
                    bzrlib._format_version_tuple(sys.version_info),
 
243
                    platform.platform(aliased=1),
 
244
                    ))
 
245
        self.stream.write('\n')
447
246
 
448
247
    def _recordTestStartTime(self):
449
248
        """Record that a test has started."""
450
 
        self._start_datetime = self._now()
 
249
        self._start_time = time.time()
 
250
 
 
251
    def _cleanupLogFile(self, test):
 
252
        # We can only do this if we have one of our TestCases, not if
 
253
        # we have a doctest.
 
254
        setKeepLogfile = getattr(test, 'setKeepLogfile', None)
 
255
        if setKeepLogfile is not None:
 
256
            setKeepLogfile()
451
257
 
452
258
    def addError(self, test, err):
453
259
        """Tell result that test finished with an error.
455
261
        Called from the TestCase run() method when the test
456
262
        fails with an unexpected error.
457
263
        """
458
 
        self._post_mortem(self._traceback_from_test)
459
 
        super(ExtendedTestResult, self).addError(test, err)
460
 
        self.error_count += 1
461
 
        self.report_error(test, err)
462
 
        if self.stop_early:
463
 
            self.stop()
 
264
        self._testConcluded(test)
 
265
        if isinstance(err[1], TestNotApplicable):
 
266
            return self._addNotApplicable(test, err)
 
267
        elif isinstance(err[1], UnavailableFeature):
 
268
            return self.addNotSupported(test, err[1].args[0])
 
269
        else:
 
270
            unittest.TestResult.addError(self, test, err)
 
271
            self.error_count += 1
 
272
            self.report_error(test, err)
 
273
            if self.stop_early:
 
274
                self.stop()
 
275
            self._cleanupLogFile(test)
464
276
 
465
277
    def addFailure(self, test, err):
466
278
        """Tell result that test failed.
468
280
        Called from the TestCase run() method when the test
469
281
        fails because e.g. an assert() method failed.
470
282
        """
471
 
        self._post_mortem(self._traceback_from_test)
472
 
        super(ExtendedTestResult, self).addFailure(test, err)
473
 
        self.failure_count += 1
474
 
        self.report_failure(test, err)
475
 
        if self.stop_early:
476
 
            self.stop()
 
283
        self._testConcluded(test)
 
284
        if isinstance(err[1], KnownFailure):
 
285
            return self._addKnownFailure(test, err)
 
286
        else:
 
287
            unittest.TestResult.addFailure(self, test, err)
 
288
            self.failure_count += 1
 
289
            self.report_failure(test, err)
 
290
            if self.stop_early:
 
291
                self.stop()
 
292
            self._cleanupLogFile(test)
477
293
 
478
 
    def addSuccess(self, test, details=None):
 
294
    def addSuccess(self, test):
479
295
        """Tell result that test completed successfully.
480
296
 
481
297
        Called from the TestCase run()
482
298
        """
 
299
        self._testConcluded(test)
483
300
        if self._bench_history is not None:
484
 
            benchmark_time = self._extractBenchmarkTime(test, details)
 
301
            benchmark_time = self._extractBenchmarkTime(test)
485
302
            if benchmark_time is not None:
486
303
                self._bench_history.write("%s %s\n" % (
487
304
                    self._formatTime(benchmark_time),
488
305
                    test.id()))
489
306
        self.report_success(test)
490
 
        super(ExtendedTestResult, self).addSuccess(test)
 
307
        self._cleanupLogFile(test)
 
308
        unittest.TestResult.addSuccess(self, test)
491
309
        test._log_contents = ''
492
310
 
493
 
    def addExpectedFailure(self, test, err):
 
311
    def _testConcluded(self, test):
 
312
        """Common code when a test has finished.
 
313
 
 
314
        Called regardless of whether it succeded, failed, etc.
 
315
        """
 
316
        pass
 
317
 
 
318
    def _addKnownFailure(self, test, err):
494
319
        self.known_failure_count += 1
495
320
        self.report_known_failure(test, err)
496
321
 
497
 
    def addUnexpectedSuccess(self, test, details=None):
498
 
        """Tell result the test unexpectedly passed, counting as a failure
499
 
 
500
 
        When the minimum version of testtools required becomes 0.9.8 this
501
 
        can be updated to use the new handling there.
502
 
        """
503
 
        super(ExtendedTestResult, self).addFailure(test, details=details)
504
 
        self.failure_count += 1
505
 
        self.report_unexpected_success(test,
506
 
            "".join(details["reason"].iter_text()))
507
 
        if self.stop_early:
508
 
            self.stop()
509
 
 
510
322
    def addNotSupported(self, test, feature):
511
323
        """The test will not be run because of a missing feature.
512
324
        """
513
325
        # this can be called in two different ways: it may be that the
514
 
        # test started running, and then raised (through requireFeature)
 
326
        # test started running, and then raised (through addError)
515
327
        # UnavailableFeature.  Alternatively this method can be called
516
 
        # while probing for features before running the test code proper; in
517
 
        # that case we will see startTest and stopTest, but the test will
518
 
        # never actually run.
 
328
        # while probing for features before running the tests; in that
 
329
        # case we will see startTest and stopTest, but the test will never
 
330
        # actually run.
519
331
        self.unsupported.setdefault(str(feature), 0)
520
332
        self.unsupported[str(feature)] += 1
521
333
        self.report_unsupported(test, feature)
525
337
        self.skip_count += 1
526
338
        self.report_skip(test, reason)
527
339
 
528
 
    def addNotApplicable(self, test, reason):
529
 
        self.not_applicable_count += 1
530
 
        self.report_not_applicable(test, reason)
531
 
 
532
 
    def _count_stored_tests(self):
533
 
        """Count of tests instances kept alive due to not succeeding"""
534
 
        return self.error_count + self.failure_count + self.known_failure_count
535
 
 
536
 
    def _post_mortem(self, tb=None):
537
 
        """Start a PDB post mortem session."""
538
 
        if os.environ.get('BZR_TEST_PDB', None):
539
 
            import pdb
540
 
            pdb.post_mortem(tb)
 
340
    def _addNotApplicable(self, test, skip_excinfo):
 
341
        if isinstance(skip_excinfo[1], TestNotApplicable):
 
342
            self.not_applicable_count += 1
 
343
            self.report_not_applicable(test, skip_excinfo)
 
344
        try:
 
345
            test.tearDown()
 
346
        except KeyboardInterrupt:
 
347
            raise
 
348
        except:
 
349
            self.addError(test, test.exc_info())
 
350
        else:
 
351
            # seems best to treat this as success from point-of-view of unittest
 
352
            # -- it actually does nothing so it barely matters :)
 
353
            unittest.TestResult.addSuccess(self, test)
 
354
            test._log_contents = ''
 
355
 
 
356
    def printErrorList(self, flavour, errors):
 
357
        for test, err in errors:
 
358
            self.stream.writeln(self.separator1)
 
359
            self.stream.write("%s: " % flavour)
 
360
            self.stream.writeln(self.getDescription(test))
 
361
            if getattr(test, '_get_log', None) is not None:
 
362
                log_contents = test._get_log()
 
363
                if log_contents:
 
364
                    self.stream.write('\n')
 
365
                    self.stream.write(
 
366
                            ('vvvv[log from %s]' % test.id()).ljust(78,'-'))
 
367
                    self.stream.write('\n')
 
368
                    self.stream.write(log_contents)
 
369
                    self.stream.write('\n')
 
370
                    self.stream.write(
 
371
                            ('^^^^[log from %s]' % test.id()).ljust(78,'-'))
 
372
                    self.stream.write('\n')
 
373
            self.stream.writeln(self.separator2)
 
374
            self.stream.writeln("%s" % err)
541
375
 
542
376
    def progress(self, offset, whence):
543
377
        """The test is adjusting the count of tests to run."""
548
382
        else:
549
383
            raise errors.BzrError("Unknown whence %r" % whence)
550
384
 
551
 
    def report_tests_starting(self):
552
 
        """Display information before the test run begins"""
553
 
        if getattr(sys, 'frozen', None) is None:
554
 
            bzr_path = osutils.realpath(sys.argv[0])
555
 
        else:
556
 
            bzr_path = sys.executable
557
 
        self.stream.write(
558
 
            'bzr selftest: %s\n' % (bzr_path,))
559
 
        self.stream.write(
560
 
            '   %s\n' % (
561
 
                    bzrlib.__path__[0],))
562
 
        self.stream.write(
563
 
            '   bzr-%s python-%s %s\n' % (
564
 
                    bzrlib.version_string,
565
 
                    bzrlib._format_version_tuple(sys.version_info),
566
 
                    platform.platform(aliased=1),
567
 
                    ))
568
 
        self.stream.write('\n')
569
 
 
570
 
    def report_test_start(self, test):
571
 
        """Display information on the test just about to be run"""
572
 
 
573
 
    def _report_thread_leak(self, test, leaked_threads, active_threads):
574
 
        """Display information on a test that leaked one or more threads"""
575
 
        # GZ 2010-09-09: A leak summary reported separately from the general
576
 
        #                thread debugging would be nice. Tests under subunit
577
 
        #                need something not using stream, perhaps adding a
578
 
        #                testtools details object would be fitting.
579
 
        if 'threads' in selftest_debug_flags:
580
 
            self.stream.write('%s is leaking, active is now %d\n' %
581
 
                (test.id(), len(active_threads)))
582
 
 
583
 
    def startTestRun(self):
584
 
        self.startTime = time.time()
 
385
    def finished(self):
 
386
        pass
 
387
 
 
388
    def report_cleaning_up(self):
 
389
        pass
585
390
 
586
391
    def report_success(self, test):
587
392
        pass
615
420
        self.pb.update_latency = 0
616
421
        self.pb.show_transport_activity = False
617
422
 
618
 
    def stopTestRun(self):
 
423
    def done(self):
619
424
        # called when the tests that are going to run have run
620
425
        self.pb.clear()
 
426
        super(TextTestResult, self).done()
 
427
 
 
428
    def finished(self):
621
429
        self.pb.finished()
622
 
        super(TextTestResult, self).stopTestRun()
623
430
 
624
 
    def report_tests_starting(self):
625
 
        super(TextTestResult, self).report_tests_starting()
 
431
    def report_starting(self):
626
432
        self.pb.update('[test 0/%d] Starting' % (self.num_tests))
627
433
 
 
434
    def printErrors(self):
 
435
        # clear the pb to make room for the error listing
 
436
        self.pb.clear()
 
437
        super(TextTestResult, self).printErrors()
 
438
 
628
439
    def _progress_prefix_text(self):
629
440
        # the longer this text, the less space we have to show the test
630
441
        # name...
643
454
            a += '%dm%ds' % (runtime / 60, runtime % 60)
644
455
        else:
645
456
            a += '%ds' % runtime
646
 
        total_fail_count = self.error_count + self.failure_count
647
 
        if total_fail_count:
648
 
            a += ', %d failed' % total_fail_count
649
 
        # if self.unsupported:
650
 
        #     a += ', %d missing' % len(self.unsupported)
 
457
        if self.error_count:
 
458
            a += ', %d err' % self.error_count
 
459
        if self.failure_count:
 
460
            a += ', %d fail' % self.failure_count
 
461
        if self.unsupported:
 
462
            a += ', %d missing' % len(self.unsupported)
651
463
        a += ']'
652
464
        return a
653
465
 
654
466
    def report_test_start(self, test):
 
467
        self.count += 1
655
468
        self.pb.update(
656
469
                self._progress_prefix_text()
657
470
                + ' '
661
474
        return self._shortened_test_description(test)
662
475
 
663
476
    def report_error(self, test, err):
664
 
        self.stream.write('ERROR: %s\n    %s\n' % (
 
477
        self.pb.note('ERROR: %s\n    %s\n',
665
478
            self._test_description(test),
666
479
            err[1],
667
 
            ))
 
480
            )
668
481
 
669
482
    def report_failure(self, test, err):
670
 
        self.stream.write('FAIL: %s\n    %s\n' % (
 
483
        self.pb.note('FAIL: %s\n    %s\n',
671
484
            self._test_description(test),
672
485
            err[1],
673
 
            ))
 
486
            )
674
487
 
675
488
    def report_known_failure(self, test, err):
676
 
        pass
677
 
 
678
 
    def report_unexpected_success(self, test, reason):
679
 
        self.stream.write('FAIL: %s\n    %s: %s\n' % (
680
 
            self._test_description(test),
681
 
            "Unexpected success. Should have failed",
682
 
            reason,
683
 
            ))
 
489
        self.pb.note('XFAIL: %s\n%s\n',
 
490
            self._test_description(test), err[1])
684
491
 
685
492
    def report_skip(self, test, reason):
686
493
        pass
687
494
 
688
 
    def report_not_applicable(self, test, reason):
 
495
    def report_not_applicable(self, test, skip_excinfo):
689
496
        pass
690
497
 
691
498
    def report_unsupported(self, test, feature):
692
499
        """test cannot be run because feature is missing."""
693
500
 
 
501
    def report_cleaning_up(self):
 
502
        self.pb.update('Cleaning up')
 
503
 
694
504
 
695
505
class VerboseTestResult(ExtendedTestResult):
696
506
    """Produce long output, with one line per test run plus times"""
703
513
            result = a_string
704
514
        return result.ljust(final_width)
705
515
 
706
 
    def report_tests_starting(self):
 
516
    def report_starting(self):
707
517
        self.stream.write('running %d tests...\n' % self.num_tests)
708
 
        super(VerboseTestResult, self).report_tests_starting()
709
518
 
710
519
    def report_test_start(self, test):
 
520
        self.count += 1
711
521
        name = self._shortened_test_description(test)
712
 
        width = osutils.terminal_width()
713
 
        if width is not None:
714
 
            # width needs space for 6 char status, plus 1 for slash, plus an
715
 
            # 11-char time string, plus a trailing blank
716
 
            # when NUMBERED_DIRS: plus 5 chars on test number, plus 1 char on
717
 
            # space
718
 
            self.stream.write(self._ellipsize_to_right(name, width-18))
719
 
        else:
720
 
            self.stream.write(name)
 
522
        # width needs space for 6 char status, plus 1 for slash, plus an
 
523
        # 11-char time string, plus a trailing blank
 
524
        # when NUMBERED_DIRS: plus 5 chars on test number, plus 1 char on space
 
525
        self.stream.write(self._ellipsize_to_right(name,
 
526
                          osutils.terminal_width()-18))
721
527
        self.stream.flush()
722
528
 
723
529
    def _error_summary(self, err):
725
531
        return '%s%s' % (indent, err[1])
726
532
 
727
533
    def report_error(self, test, err):
728
 
        self.stream.write('ERROR %s\n%s\n'
 
534
        self.stream.writeln('ERROR %s\n%s'
729
535
                % (self._testTimeString(test),
730
536
                   self._error_summary(err)))
731
537
 
732
538
    def report_failure(self, test, err):
733
 
        self.stream.write(' FAIL %s\n%s\n'
 
539
        self.stream.writeln(' FAIL %s\n%s'
734
540
                % (self._testTimeString(test),
735
541
                   self._error_summary(err)))
736
542
 
737
543
    def report_known_failure(self, test, err):
738
 
        self.stream.write('XFAIL %s\n%s\n'
 
544
        self.stream.writeln('XFAIL %s\n%s'
739
545
                % (self._testTimeString(test),
740
546
                   self._error_summary(err)))
741
547
 
742
 
    def report_unexpected_success(self, test, reason):
743
 
        self.stream.write(' FAIL %s\n%s: %s\n'
744
 
                % (self._testTimeString(test),
745
 
                   "Unexpected success. Should have failed",
746
 
                   reason))
747
 
 
748
548
    def report_success(self, test):
749
 
        self.stream.write('   OK %s\n' % self._testTimeString(test))
 
549
        self.stream.writeln('   OK %s' % self._testTimeString(test))
750
550
        for bench_called, stats in getattr(test, '_benchcalls', []):
751
 
            self.stream.write('LSProf output for %s(%s, %s)\n' % bench_called)
 
551
            self.stream.writeln('LSProf output for %s(%s, %s)' % bench_called)
752
552
            stats.pprint(file=self.stream)
753
553
        # flush the stream so that we get smooth output. This verbose mode is
754
554
        # used to show the output in PQM.
755
555
        self.stream.flush()
756
556
 
757
557
    def report_skip(self, test, reason):
758
 
        self.stream.write(' SKIP %s\n%s\n'
 
558
        self.stream.writeln(' SKIP %s\n%s'
759
559
                % (self._testTimeString(test), reason))
760
560
 
761
 
    def report_not_applicable(self, test, reason):
762
 
        self.stream.write('  N/A %s\n    %s\n'
763
 
                % (self._testTimeString(test), reason))
 
561
    def report_not_applicable(self, test, skip_excinfo):
 
562
        self.stream.writeln('  N/A %s\n%s'
 
563
                % (self._testTimeString(test),
 
564
                   self._error_summary(skip_excinfo)))
764
565
 
765
566
    def report_unsupported(self, test, feature):
766
567
        """test cannot be run because feature is missing."""
767
 
        self.stream.write("NODEP %s\n    The feature '%s' is not available.\n"
 
568
        self.stream.writeln("NODEP %s\n    The feature '%s' is not available."
768
569
                %(self._testTimeString(test), feature))
769
570
 
770
571
 
776
577
                 descriptions=0,
777
578
                 verbosity=1,
778
579
                 bench_history=None,
 
580
                 list_only=False,
779
581
                 strict=False,
780
 
                 result_decorators=None,
781
582
                 ):
782
 
        """Create a TextTestRunner.
783
 
 
784
 
        :param result_decorators: An optional list of decorators to apply
785
 
            to the result object being used by the runner. Decorators are
786
 
            applied left to right - the first element in the list is the 
787
 
            innermost decorator.
788
 
        """
789
 
        # stream may know claim to know to write unicode strings, but in older
790
 
        # pythons this goes sufficiently wrong that it is a bad idea. (
791
 
        # specifically a built in file with encoding 'UTF-8' will still try
792
 
        # to encode using ascii.
793
 
        new_encoding = osutils.get_terminal_encoding()
794
 
        codec = codecs.lookup(new_encoding)
795
 
        if type(codec) is tuple:
796
 
            # Python 2.4
797
 
            encode = codec[0]
798
 
        else:
799
 
            encode = codec.encode
800
 
        # GZ 2010-09-08: Really we don't want to be writing arbitrary bytes,
801
 
        #                so should swap to the plain codecs.StreamWriter
802
 
        stream = osutils.UnicodeOrBytesToBytesWriter(encode, stream,
803
 
            "backslashreplace")
804
 
        stream.encoding = new_encoding
805
 
        self.stream = stream
 
583
        self.stream = unittest._WritelnDecorator(stream)
806
584
        self.descriptions = descriptions
807
585
        self.verbosity = verbosity
808
586
        self._bench_history = bench_history
 
587
        self.list_only = list_only
809
588
        self._strict = strict
810
 
        self._result_decorators = result_decorators or []
811
589
 
812
590
    def run(self, test):
813
591
        "Run the given test case or test suite."
 
592
        startTime = time.time()
814
593
        if self.verbosity == 1:
815
594
            result_class = TextTestResult
816
595
        elif self.verbosity >= 2:
817
596
            result_class = VerboseTestResult
818
 
        original_result = result_class(self.stream,
 
597
        result = result_class(self.stream,
819
598
                              self.descriptions,
820
599
                              self.verbosity,
821
600
                              bench_history=self._bench_history,
822
601
                              strict=self._strict,
823
602
                              )
824
 
        # Signal to result objects that look at stop early policy to stop,
825
 
        original_result.stop_early = self.stop_on_failure
826
 
        result = original_result
827
 
        for decorator in self._result_decorators:
828
 
            result = decorator(result)
829
 
            result.stop_early = self.stop_on_failure
830
 
        result.startTestRun()
831
 
        try:
832
 
            test.run(result)
833
 
        finally:
834
 
            result.stopTestRun()
835
 
        # higher level code uses our extended protocol to determine
836
 
        # what exit code to give.
837
 
        return original_result
 
603
        result.stop_early = self.stop_on_failure
 
604
        result.report_starting()
 
605
        if self.list_only:
 
606
            if self.verbosity >= 2:
 
607
                self.stream.writeln("Listing tests only ...\n")
 
608
            run = 0
 
609
            for t in iter_suite_tests(test):
 
610
                self.stream.writeln("%s" % (t.id()))
 
611
                run += 1
 
612
            return None
 
613
        else:
 
614
            try:
 
615
                import testtools
 
616
            except ImportError:
 
617
                test.run(result)
 
618
            else:
 
619
                if isinstance(test, testtools.ConcurrentTestSuite):
 
620
                    # We need to catch bzr specific behaviors
 
621
                    test.run(BZRTransformingResult(result))
 
622
                else:
 
623
                    test.run(result)
 
624
            run = result.testsRun
 
625
            actionTaken = "Ran"
 
626
        stopTime = time.time()
 
627
        timeTaken = stopTime - startTime
 
628
        result.printErrors()
 
629
        self.stream.writeln(result.separator2)
 
630
        self.stream.writeln("%s %d test%s in %.3fs" % (actionTaken,
 
631
                            run, run != 1 and "s" or "", timeTaken))
 
632
        self.stream.writeln()
 
633
        if not result.wasSuccessful():
 
634
            self.stream.write("FAILED (")
 
635
            failed, errored = map(len, (result.failures, result.errors))
 
636
            if failed:
 
637
                self.stream.write("failures=%d" % failed)
 
638
            if errored:
 
639
                if failed: self.stream.write(", ")
 
640
                self.stream.write("errors=%d" % errored)
 
641
            if result.known_failure_count:
 
642
                if failed or errored: self.stream.write(", ")
 
643
                self.stream.write("known_failure_count=%d" %
 
644
                    result.known_failure_count)
 
645
            self.stream.writeln(")")
 
646
        else:
 
647
            if result.known_failure_count:
 
648
                self.stream.writeln("OK (known_failures=%d)" %
 
649
                    result.known_failure_count)
 
650
            else:
 
651
                self.stream.writeln("OK")
 
652
        if result.skip_count > 0:
 
653
            skipped = result.skip_count
 
654
            self.stream.writeln('%d test%s skipped' %
 
655
                                (skipped, skipped != 1 and "s" or ""))
 
656
        if result.unsupported:
 
657
            for feature, count in sorted(result.unsupported.items()):
 
658
                self.stream.writeln("Missing feature '%s' skipped %d tests." %
 
659
                    (feature, count))
 
660
        result.finished()
 
661
        return result
838
662
 
839
663
 
840
664
def iter_suite_tests(suite):
850
674
                        % (type(suite), suite))
851
675
 
852
676
 
853
 
TestSkipped = testtools.testcase.TestSkipped
 
677
class TestSkipped(Exception):
 
678
    """Indicates that a test was intentionally skipped, rather than failing."""
854
679
 
855
680
 
856
681
class TestNotApplicable(TestSkipped):
862
687
    """
863
688
 
864
689
 
865
 
# traceback._some_str fails to format exceptions that have the default
866
 
# __str__ which does an implicit ascii conversion. However, repr() on those
867
 
# objects works, for all that its not quite what the doctor may have ordered.
868
 
def _clever_some_str(value):
869
 
    try:
870
 
        return str(value)
871
 
    except:
872
 
        try:
873
 
            return repr(value).replace('\\n', '\n')
874
 
        except:
875
 
            return '<unprintable %s object>' % type(value).__name__
876
 
 
877
 
traceback._some_str = _clever_some_str
878
 
 
879
 
 
880
 
# deprecated - use self.knownFailure(), or self.expectFailure.
881
 
KnownFailure = testtools.testcase._ExpectedFailure
 
690
class KnownFailure(AssertionError):
 
691
    """Indicates that a test failed in a precisely expected manner.
 
692
 
 
693
    Such failures dont block the whole test suite from passing because they are
 
694
    indicators of partially completed code or of future work. We have an
 
695
    explicit error for them so that we can ensure that they are always visible:
 
696
    KnownFailures are always shown in the output of bzr selftest.
 
697
    """
882
698
 
883
699
 
884
700
class UnavailableFeature(Exception):
885
701
    """A feature required for this test was not available.
886
702
 
887
 
    This can be considered a specialised form of SkippedTest.
888
 
 
889
703
    The feature should be used to construct the exception.
890
704
    """
891
705
 
892
706
 
 
707
class CommandFailed(Exception):
 
708
    pass
 
709
 
 
710
 
893
711
class StringIOWrapper(object):
894
712
    """A wrapper around cStringIO which just adds an encoding attribute.
895
713
 
932
750
    # XXX: Should probably unify more with CannedInputUIFactory or a
933
751
    # particular configuration of TextUIFactory, or otherwise have a clearer
934
752
    # idea of how they're supposed to be different.
935
 
    # See https://bugs.launchpad.net/bzr/+bug/408213
 
753
    # See https://bugs.edge.launchpad.net/bzr/+bug/408213
936
754
 
937
755
    def __init__(self, stdout=None, stderr=None, stdin=None):
938
756
        if stdin is not None:
956
774
        return NullProgressView()
957
775
 
958
776
 
959
 
def isolated_doctest_setUp(test):
960
 
    override_os_environ(test)
961
 
 
962
 
 
963
 
def isolated_doctest_tearDown(test):
964
 
    restore_os_environ(test)
965
 
 
966
 
 
967
 
def IsolatedDocTestSuite(*args, **kwargs):
968
 
    """Overrides doctest.DocTestSuite to handle isolation.
969
 
 
970
 
    The method is really a factory and users are expected to use it as such.
971
 
    """
972
 
 
973
 
    kwargs['setUp'] = isolated_doctest_setUp
974
 
    kwargs['tearDown'] = isolated_doctest_tearDown
975
 
    return doctest.DocTestSuite(*args, **kwargs)
976
 
 
977
 
 
978
 
class TestCase(testtools.TestCase):
 
777
class TestCase(unittest.TestCase):
979
778
    """Base class for bzr unit tests.
980
779
 
981
780
    Tests that need access to disk resources should subclass
991
790
    routine, and to build and check bzr trees.
992
791
 
993
792
    In addition to the usual method of overriding tearDown(), this class also
994
 
    allows subclasses to register cleanup functions via addCleanup, which are
 
793
    allows subclasses to register functions into the _cleanups list, which is
995
794
    run in order as the object is torn down.  It's less likely this will be
996
795
    accidentally overlooked.
997
796
    """
998
797
 
999
 
    _log_file = None
 
798
    _active_threads = None
 
799
    _leaking_threads_tests = 0
 
800
    _first_thread_leaker_id = None
 
801
    _log_file_name = None
 
802
    _log_contents = ''
 
803
    _keep_log_file = False
1000
804
    # record lsprof data when performing benchmark calls.
1001
805
    _gather_lsprof_in_benchmarks = False
 
806
    attrs_to_keep = ('id', '_testMethodName', '_testMethodDoc',
 
807
                     '_log_contents', '_log_file_name', '_benchtime',
 
808
                     '_TestCase__testMethodName', '_TestCase__testMethodDoc',)
1002
809
 
1003
810
    def __init__(self, methodName='testMethod'):
1004
811
        super(TestCase, self).__init__(methodName)
1005
 
        self._directory_isolation = True
1006
 
        self.exception_handlers.insert(0,
1007
 
            (UnavailableFeature, self._do_unsupported_or_skip))
1008
 
        self.exception_handlers.insert(0,
1009
 
            (TestNotApplicable, self._do_not_applicable))
 
812
        self._cleanups = []
 
813
        self._bzr_test_setUp_run = False
 
814
        self._bzr_test_tearDown_run = False
1010
815
 
1011
816
    def setUp(self):
1012
 
        super(TestCase, self).setUp()
1013
 
 
1014
 
        # At this point we're still accessing the config files in $BZR_HOME (as
1015
 
        # set by the user running selftest).
1016
 
        timeout = config.GlobalStack().get('selftest.timeout')
1017
 
        if timeout:
1018
 
            timeout_fixture = fixtures.TimeoutFixture(timeout)
1019
 
            timeout_fixture.setUp()
1020
 
            self.addCleanup(timeout_fixture.cleanUp)
1021
 
 
1022
 
        for feature in getattr(self, '_test_needs_features', []):
1023
 
            self.requireFeature(feature)
 
817
        unittest.TestCase.setUp(self)
 
818
        self._bzr_test_setUp_run = True
1024
819
        self._cleanEnvironment()
1025
 
 
1026
 
        if bzrlib.global_state is not None:
1027
 
            self.overrideAttr(bzrlib.global_state, 'cmdline_overrides',
1028
 
                              config.CommandLineStore())
1029
 
 
1030
820
        self._silenceUI()
1031
821
        self._startLogFile()
1032
822
        self._benchcalls = []
1033
823
        self._benchtime = None
1034
824
        self._clear_hooks()
1035
 
        self._track_transports()
1036
825
        self._track_locks()
1037
826
        self._clear_debug_flags()
1038
 
        # Isolate global verbosity level, to make sure it's reproducible
1039
 
        # between tests.  We should get rid of this altogether: bug 656694. --
1040
 
        # mbp 20101008
1041
 
        self.overrideAttr(bzrlib.trace, '_verbosity_level', 0)
1042
 
        self._log_files = set()
1043
 
        # Each key in the ``_counters`` dict holds a value for a different
1044
 
        # counter. When the test ends, addDetail() should be used to output the
1045
 
        # counter values. This happens in install_counter_hook().
1046
 
        self._counters = {}
1047
 
        if 'config_stats' in selftest_debug_flags:
1048
 
            self._install_config_stats_hooks()
1049
 
        # Do not use i18n for tests (unless the test reverses this)
1050
 
        i18n.disable_i18n()
 
827
        TestCase._active_threads = threading.activeCount()
 
828
        self.addCleanup(self._check_leaked_threads)
1051
829
 
1052
830
    def debug(self):
1053
831
        # debug a frame up.
1054
832
        import pdb
1055
 
        # The sys preserved stdin/stdout should allow blackbox tests debugging
1056
 
        pdb.Pdb(stdin=sys.__stdin__, stdout=sys.__stdout__
1057
 
                ).set_trace(sys._getframe().f_back)
1058
 
 
1059
 
    def discardDetail(self, name):
1060
 
        """Extend the addDetail, getDetails api so we can remove a detail.
1061
 
 
1062
 
        eg. bzr always adds the 'log' detail at startup, but we don't want to
1063
 
        include it for skipped, xfail, etc tests.
1064
 
 
1065
 
        It is safe to call this for a detail that doesn't exist, in case this
1066
 
        gets called multiple times.
1067
 
        """
1068
 
        # We cheat. details is stored in __details which means we shouldn't
1069
 
        # touch it. but getDetails() returns the dict directly, so we can
1070
 
        # mutate it.
1071
 
        details = self.getDetails()
1072
 
        if name in details:
1073
 
            del details[name]
1074
 
 
1075
 
    def install_counter_hook(self, hooks, name, counter_name=None):
1076
 
        """Install a counting hook.
1077
 
 
1078
 
        Any hook can be counted as long as it doesn't need to return a value.
1079
 
 
1080
 
        :param hooks: Where the hook should be installed.
1081
 
 
1082
 
        :param name: The hook name that will be counted.
1083
 
 
1084
 
        :param counter_name: The counter identifier in ``_counters``, defaults
1085
 
            to ``name``.
1086
 
        """
1087
 
        _counters = self._counters # Avoid closing over self
1088
 
        if counter_name is None:
1089
 
            counter_name = name
1090
 
        if _counters.has_key(counter_name):
1091
 
            raise AssertionError('%s is already used as a counter name'
1092
 
                                  % (counter_name,))
1093
 
        _counters[counter_name] = 0
1094
 
        self.addDetail(counter_name, content.Content(content.UTF8_TEXT,
1095
 
            lambda: ['%d' % (_counters[counter_name],)]))
1096
 
        def increment_counter(*args, **kwargs):
1097
 
            _counters[counter_name] += 1
1098
 
        label = 'count %s calls' % (counter_name,)
1099
 
        hooks.install_named_hook(name, increment_counter, label)
1100
 
        self.addCleanup(hooks.uninstall_named_hook, name, label)
1101
 
 
1102
 
    def _install_config_stats_hooks(self):
1103
 
        """Install config hooks to count hook calls.
1104
 
 
1105
 
        """
1106
 
        for hook_name in ('get', 'set', 'remove', 'load', 'save'):
1107
 
            self.install_counter_hook(config.ConfigHooks, hook_name,
1108
 
                                       'config.%s' % (hook_name,))
1109
 
 
1110
 
        # The OldConfigHooks are private and need special handling to protect
1111
 
        # against recursive tests (tests that run other tests), so we just do
1112
 
        # manually what registering them into _builtin_known_hooks will provide
1113
 
        # us.
1114
 
        self.overrideAttr(config, 'OldConfigHooks', config._OldConfigHooks())
1115
 
        for hook_name in ('get', 'set', 'remove', 'load', 'save'):
1116
 
            self.install_counter_hook(config.OldConfigHooks, hook_name,
1117
 
                                      'old_config.%s' % (hook_name,))
 
833
        pdb.Pdb().set_trace(sys._getframe().f_back)
 
834
 
 
835
    def _check_leaked_threads(self):
 
836
        active = threading.activeCount()
 
837
        leaked_threads = active - TestCase._active_threads
 
838
        TestCase._active_threads = active
 
839
        if leaked_threads:
 
840
            TestCase._leaking_threads_tests += 1
 
841
            if TestCase._first_thread_leaker_id is None:
 
842
                TestCase._first_thread_leaker_id = self.id()
1118
843
 
1119
844
    def _clear_debug_flags(self):
1120
845
        """Prevent externally set debug flags affecting tests.
1122
847
        Tests that want to use debug flags can just set them in the
1123
848
        debug_flags set during setup/teardown.
1124
849
        """
1125
 
        # Start with a copy of the current debug flags we can safely modify.
1126
 
        self.overrideAttr(debug, 'debug_flags', set(debug.debug_flags))
 
850
        self._preserved_debug_flags = set(debug.debug_flags)
1127
851
        if 'allow_debug' not in selftest_debug_flags:
1128
852
            debug.debug_flags.clear()
1129
853
        if 'disable_lock_checks' not in selftest_debug_flags:
1130
854
            debug.debug_flags.add('strict_locks')
 
855
        self.addCleanup(self._restore_debug_flags)
1131
856
 
1132
857
    def _clear_hooks(self):
1133
858
        # prevent hooks affecting tests
1134
 
        known_hooks = hooks.known_hooks
1135
859
        self._preserved_hooks = {}
1136
 
        for key, (parent, name) in known_hooks.iter_parent_objects():
1137
 
            current_hooks = getattr(parent, name)
 
860
        for key, factory in hooks.known_hooks.items():
 
861
            parent, name = hooks.known_hooks_key_to_parent_and_attribute(key)
 
862
            current_hooks = hooks.known_hooks_key_to_object(key)
1138
863
            self._preserved_hooks[parent] = (name, current_hooks)
1139
 
        self._preserved_lazy_hooks = hooks._lazy_hooks
1140
 
        hooks._lazy_hooks = {}
1141
864
        self.addCleanup(self._restoreHooks)
1142
 
        for key, (parent, name) in known_hooks.iter_parent_objects():
1143
 
            factory = known_hooks.get(key)
 
865
        for key, factory in hooks.known_hooks.items():
 
866
            parent, name = hooks.known_hooks_key_to_parent_and_attribute(key)
1144
867
            setattr(parent, name, factory())
1145
868
        # this hook should always be installed
1146
869
        request._install_hook()
1147
870
 
1148
 
    def disable_directory_isolation(self):
1149
 
        """Turn off directory isolation checks."""
1150
 
        self._directory_isolation = False
1151
 
 
1152
 
    def enable_directory_isolation(self):
1153
 
        """Enable directory isolation checks."""
1154
 
        self._directory_isolation = True
1155
 
 
1156
871
    def _silenceUI(self):
1157
872
        """Turn off UI for duration of test"""
1158
873
        # by default the UI is off; tests can turn it on if they want it.
1159
 
        self.overrideAttr(ui, 'ui_factory', ui.SilentUIFactory())
 
874
        saved = ui.ui_factory
 
875
        def _restore():
 
876
            ui.ui_factory = saved
 
877
        ui.ui_factory = ui.SilentUIFactory()
 
878
        self.addCleanup(_restore)
1160
879
 
1161
880
    def _check_locks(self):
1162
881
        """Check that all lock take/release actions have been paired."""
1175
894
        # break some locks on purpose and should be taken into account by
1176
895
        # considering that breaking a lock is just a dirty way of releasing it.
1177
896
        if len(acquired_locks) != (len(released_locks) + len(broken_locks)):
1178
 
            message = (
1179
 
                'Different number of acquired and '
1180
 
                'released or broken locks.\n'
1181
 
                'acquired=%s\n'
1182
 
                'released=%s\n'
1183
 
                'broken=%s\n' %
1184
 
                (acquired_locks, released_locks, broken_locks))
 
897
            message = ('Different number of acquired and '
 
898
                       'released or broken locks. (%s, %s + %s)' %
 
899
                       (acquired_locks, released_locks, broken_locks))
1185
900
            if not self._lock_check_thorough:
1186
901
                # Rather than fail, just warn
1187
902
                print "Broken test %s: %s" % (self, message)
1195
910
            self._lock_check_thorough = False
1196
911
        else:
1197
912
            self._lock_check_thorough = True
1198
 
 
 
913
            
1199
914
        self.addCleanup(self._check_locks)
1200
915
        _mod_lock.Lock.hooks.install_named_hook('lock_acquired',
1201
916
                                                self._lock_acquired, None)
1213
928
    def _lock_broken(self, result):
1214
929
        self._lock_actions.append(('broken', result))
1215
930
 
1216
 
    def permit_dir(self, name):
1217
 
        """Permit a directory to be used by this test. See permit_url."""
1218
 
        name_transport = _mod_transport.get_transport_from_path(name)
1219
 
        self.permit_url(name)
1220
 
        self.permit_url(name_transport.base)
1221
 
 
1222
 
    def permit_url(self, url):
1223
 
        """Declare that url is an ok url to use in this test.
1224
 
        
1225
 
        Do this for memory transports, temporary test directory etc.
1226
 
        
1227
 
        Do not do this for the current working directory, /tmp, or any other
1228
 
        preexisting non isolated url.
1229
 
        """
1230
 
        if not url.endswith('/'):
1231
 
            url += '/'
1232
 
        self._bzr_selftest_roots.append(url)
1233
 
 
1234
 
    def permit_source_tree_branch_repo(self):
1235
 
        """Permit the source tree bzr is running from to be opened.
1236
 
 
1237
 
        Some code such as bzrlib.version attempts to read from the bzr branch
1238
 
        that bzr is executing from (if any). This method permits that directory
1239
 
        to be used in the test suite.
1240
 
        """
1241
 
        path = self.get_source_path()
1242
 
        self.record_directory_isolation()
1243
 
        try:
1244
 
            try:
1245
 
                workingtree.WorkingTree.open(path)
1246
 
            except (errors.NotBranchError, errors.NoWorkingTree):
1247
 
                raise TestSkipped('Needs a working tree of bzr sources')
1248
 
        finally:
1249
 
            self.enable_directory_isolation()
1250
 
 
1251
 
    def _preopen_isolate_transport(self, transport):
1252
 
        """Check that all transport openings are done in the test work area."""
1253
 
        while isinstance(transport, pathfilter.PathFilteringTransport):
1254
 
            # Unwrap pathfiltered transports
1255
 
            transport = transport.server.backing_transport.clone(
1256
 
                transport._filter('.'))
1257
 
        url = transport.base
1258
 
        # ReadonlySmartTCPServer_for_testing decorates the backing transport
1259
 
        # urls it is given by prepending readonly+. This is appropriate as the
1260
 
        # client shouldn't know that the server is readonly (or not readonly).
1261
 
        # We could register all servers twice, with readonly+ prepending, but
1262
 
        # that makes for a long list; this is about the same but easier to
1263
 
        # read.
1264
 
        if url.startswith('readonly+'):
1265
 
            url = url[len('readonly+'):]
1266
 
        self._preopen_isolate_url(url)
1267
 
 
1268
 
    def _preopen_isolate_url(self, url):
1269
 
        if not self._directory_isolation:
1270
 
            return
1271
 
        if self._directory_isolation == 'record':
1272
 
            self._bzr_selftest_roots.append(url)
1273
 
            return
1274
 
        # This prevents all transports, including e.g. sftp ones backed on disk
1275
 
        # from working unless they are explicitly granted permission. We then
1276
 
        # depend on the code that sets up test transports to check that they are
1277
 
        # appropriately isolated and enable their use by calling
1278
 
        # self.permit_transport()
1279
 
        if not osutils.is_inside_any(self._bzr_selftest_roots, url):
1280
 
            raise errors.BzrError("Attempt to escape test isolation: %r %r"
1281
 
                % (url, self._bzr_selftest_roots))
1282
 
 
1283
 
    def record_directory_isolation(self):
1284
 
        """Gather accessed directories to permit later access.
1285
 
        
1286
 
        This is used for tests that access the branch bzr is running from.
1287
 
        """
1288
 
        self._directory_isolation = "record"
1289
 
 
1290
 
    def start_server(self, transport_server, backing_server=None):
1291
 
        """Start transport_server for this test.
1292
 
 
1293
 
        This starts the server, registers a cleanup for it and permits the
1294
 
        server's urls to be used.
1295
 
        """
1296
 
        if backing_server is None:
1297
 
            transport_server.start_server()
1298
 
        else:
1299
 
            transport_server.start_server(backing_server)
1300
 
        self.addCleanup(transport_server.stop_server)
1301
 
        # Obtain a real transport because if the server supplies a password, it
1302
 
        # will be hidden from the base on the client side.
1303
 
        t = _mod_transport.get_transport_from_url(transport_server.get_url())
1304
 
        # Some transport servers effectively chroot the backing transport;
1305
 
        # others like SFTPServer don't - users of the transport can walk up the
1306
 
        # transport to read the entire backing transport. This wouldn't matter
1307
 
        # except that the workdir tests are given - and that they expect the
1308
 
        # server's url to point at - is one directory under the safety net. So
1309
 
        # Branch operations into the transport will attempt to walk up one
1310
 
        # directory. Chrooting all servers would avoid this but also mean that
1311
 
        # we wouldn't be testing directly against non-root urls. Alternatively
1312
 
        # getting the test framework to start the server with a backing server
1313
 
        # at the actual safety net directory would work too, but this then
1314
 
        # means that the self.get_url/self.get_transport methods would need
1315
 
        # to transform all their results. On balance its cleaner to handle it
1316
 
        # here, and permit a higher url when we have one of these transports.
1317
 
        if t.base.endswith('/work/'):
1318
 
            # we have safety net/test root/work
1319
 
            t = t.clone('../..')
1320
 
        elif isinstance(transport_server,
1321
 
                        test_server.SmartTCPServer_for_testing):
1322
 
            # The smart server adds a path similar to work, which is traversed
1323
 
            # up from by the client. But the server is chrooted - the actual
1324
 
            # backing transport is not escaped from, and VFS requests to the
1325
 
            # root will error (because they try to escape the chroot).
1326
 
            t2 = t.clone('..')
1327
 
            while t2.base != t.base:
1328
 
                t = t2
1329
 
                t2 = t.clone('..')
1330
 
        self.permit_url(t.base)
1331
 
 
1332
 
    def _track_transports(self):
1333
 
        """Install checks for transport usage."""
1334
 
        # TestCase has no safe place it can write to.
1335
 
        self._bzr_selftest_roots = []
1336
 
        # Currently the easiest way to be sure that nothing is going on is to
1337
 
        # hook into bzr dir opening. This leaves a small window of error for
1338
 
        # transport tests, but they are well known, and we can improve on this
1339
 
        # step.
1340
 
        controldir.ControlDir.hooks.install_named_hook("pre_open",
1341
 
            self._preopen_isolate_transport, "Check bzr directories are safe.")
1342
 
 
1343
931
    def _ndiff_strings(self, a, b):
1344
932
        """Return ndiff between two strings containing lines.
1345
933
 
1362
950
        except UnicodeError, e:
1363
951
            # If we can't compare without getting a UnicodeError, then
1364
952
            # obviously they are different
1365
 
            trace.mutter('UnicodeError: %s', e)
 
953
            mutter('UnicodeError: %s', e)
1366
954
        if message:
1367
955
            message += '\n'
1368
956
        raise AssertionError("%snot equal:\na = %s\nb = %s\n"
1369
957
            % (message,
1370
 
               pprint.pformat(a), pprint.pformat(b)))
 
958
               pformat(a), pformat(b)))
1371
959
 
1372
 
    # FIXME: This is deprecated in unittest2 but plugins may still use it so we
1373
 
    # need a deprecation period for them -- vila 2016-02-01
1374
960
    assertEquals = assertEqual
1375
961
 
1376
962
    def assertEqualDiff(self, a, b, message=None):
1379
965
        This is intended for use with multi-line strings where it can
1380
966
        be hard to find the differences by eye.
1381
967
        """
1382
 
        # TODO: perhaps override assertEqual to call this for strings?
 
968
        # TODO: perhaps override assertEquals to call this for strings?
1383
969
        if a == b:
1384
970
            return
1385
971
        if message is None:
1386
972
            message = "texts not equal:\n"
 
973
        if a == b + '\n':
 
974
            message = 'first string is missing a final newline.\n'
1387
975
        if a + '\n' == b:
1388
 
            message = 'first string is missing a final newline.\n'
1389
 
        if a == b + '\n':
1390
976
            message = 'second string is missing a final newline.\n'
1391
977
        raise AssertionError(message +
1392
978
                             self._ndiff_strings(a, b))
1403
989
        :raises AssertionError: If the expected and actual stat values differ
1404
990
            other than by atime.
1405
991
        """
1406
 
        self.assertEqual(expected.st_size, actual.st_size,
1407
 
                         'st_size did not match')
1408
 
        self.assertEqual(expected.st_mtime, actual.st_mtime,
1409
 
                         'st_mtime did not match')
1410
 
        self.assertEqual(expected.st_ctime, actual.st_ctime,
1411
 
                         'st_ctime did not match')
1412
 
        if sys.platform == 'win32':
1413
 
            # On Win32 both 'dev' and 'ino' cannot be trusted. In python2.4 it
1414
 
            # is 'dev' that varies, in python 2.5 (6?) it is st_ino that is
1415
 
            # odd. We just force it to always be 0 to avoid any problems.
1416
 
            self.assertEqual(0, expected.st_dev)
1417
 
            self.assertEqual(0, actual.st_dev)
1418
 
            self.assertEqual(0, expected.st_ino)
1419
 
            self.assertEqual(0, actual.st_ino)
1420
 
        else:
1421
 
            self.assertEqual(expected.st_dev, actual.st_dev,
1422
 
                             'st_dev did not match')
1423
 
            self.assertEqual(expected.st_ino, actual.st_ino,
1424
 
                             'st_ino did not match')
1425
 
        self.assertEqual(expected.st_mode, actual.st_mode,
1426
 
                         'st_mode did not match')
 
992
        self.assertEqual(expected.st_size, actual.st_size)
 
993
        self.assertEqual(expected.st_mtime, actual.st_mtime)
 
994
        self.assertEqual(expected.st_ctime, actual.st_ctime)
 
995
        self.assertEqual(expected.st_dev, actual.st_dev)
 
996
        self.assertEqual(expected.st_ino, actual.st_ino)
 
997
        self.assertEqual(expected.st_mode, actual.st_mode)
1427
998
 
1428
999
    def assertLength(self, length, obj_with_len):
1429
1000
        """Assert that obj_with_len is of length length."""
1431
1002
            self.fail("Incorrect length: wanted %d, got %d for %r" % (
1432
1003
                length, len(obj_with_len), obj_with_len))
1433
1004
 
1434
 
    def assertLogsError(self, exception_class, func, *args, **kwargs):
1435
 
        """Assert that `func(*args, **kwargs)` quietly logs a specific error.
1436
 
        """
1437
 
        captured = []
1438
 
        orig_log_exception_quietly = trace.log_exception_quietly
1439
 
        try:
1440
 
            def capture():
1441
 
                orig_log_exception_quietly()
1442
 
                captured.append(sys.exc_info()[1])
1443
 
            trace.log_exception_quietly = capture
1444
 
            func(*args, **kwargs)
1445
 
        finally:
1446
 
            trace.log_exception_quietly = orig_log_exception_quietly
1447
 
        self.assertLength(1, captured)
1448
 
        err = captured[0]
1449
 
        self.assertIsInstance(err, exception_class)
1450
 
        return err
1451
 
 
1452
1005
    def assertPositive(self, val):
1453
1006
        """Assert that val is greater than 0."""
1454
1007
        self.assertTrue(val > 0, 'expected a positive value, but got %s' % val)
1484
1037
            raise AssertionError('pattern "%s" found in "%s"'
1485
1038
                    % (needle_re, haystack))
1486
1039
 
1487
 
    def assertContainsString(self, haystack, needle):
1488
 
        if haystack.find(needle) == -1:
1489
 
            self.fail("string %r not found in '''%s'''" % (needle, haystack))
1490
 
 
1491
 
    def assertNotContainsString(self, haystack, needle):
1492
 
        if haystack.find(needle) != -1:
1493
 
            self.fail("string %r found in '''%s'''" % (needle, haystack))
1494
 
 
1495
1040
    def assertSubset(self, sublist, superlist):
1496
1041
        """Assert that every entry in sublist is present in superlist."""
1497
1042
        missing = set(sublist) - set(superlist)
1584
1129
                m += ": " + msg
1585
1130
            self.fail(m)
1586
1131
 
 
1132
    def expectFailure(self, reason, assertion, *args, **kwargs):
 
1133
        """Invoke a test, expecting it to fail for the given reason.
 
1134
 
 
1135
        This is for assertions that ought to succeed, but currently fail.
 
1136
        (The failure is *expected* but not *wanted*.)  Please be very precise
 
1137
        about the failure you're expecting.  If a new bug is introduced,
 
1138
        AssertionError should be raised, not KnownFailure.
 
1139
 
 
1140
        Frequently, expectFailure should be followed by an opposite assertion.
 
1141
        See example below.
 
1142
 
 
1143
        Intended to be used with a callable that raises AssertionError as the
 
1144
        'assertion' parameter.  args and kwargs are passed to the 'assertion'.
 
1145
 
 
1146
        Raises KnownFailure if the test fails.  Raises AssertionError if the
 
1147
        test succeeds.
 
1148
 
 
1149
        example usage::
 
1150
 
 
1151
          self.expectFailure('Math is broken', self.assertNotEqual, 54,
 
1152
                             dynamic_val)
 
1153
          self.assertEqual(42, dynamic_val)
 
1154
 
 
1155
          This means that a dynamic_val of 54 will cause the test to raise
 
1156
          a KnownFailure.  Once math is fixed and the expectFailure is removed,
 
1157
          only a dynamic_val of 42 will allow the test to pass.  Anything other
 
1158
          than 54 or 42 will cause an AssertionError.
 
1159
        """
 
1160
        try:
 
1161
            assertion(*args, **kwargs)
 
1162
        except AssertionError:
 
1163
            raise KnownFailure(reason)
 
1164
        else:
 
1165
            self.fail('Unexpected success.  Should have failed: %s' % reason)
 
1166
 
1587
1167
    def assertFileEqual(self, content, path):
1588
1168
        """Fail if path does not contain 'content'."""
1589
 
        self.assertPathExists(path)
 
1169
        self.failUnlessExists(path)
1590
1170
        f = file(path, 'rb')
1591
1171
        try:
1592
1172
            s = f.read()
1594
1174
            f.close()
1595
1175
        self.assertEqualDiff(content, s)
1596
1176
 
1597
 
    def assertDocstring(self, expected_docstring, obj):
1598
 
        """Fail if obj does not have expected_docstring"""
1599
 
        if __doc__ is None:
1600
 
            # With -OO the docstring should be None instead
1601
 
            self.assertIs(obj.__doc__, None)
1602
 
        else:
1603
 
            self.assertEqual(expected_docstring, obj.__doc__)
1604
 
 
1605
 
    @symbol_versioning.deprecated_method(symbol_versioning.deprecated_in((2, 4)))
1606
1177
    def failUnlessExists(self, path):
1607
 
        return self.assertPathExists(path)
1608
 
 
1609
 
    def assertPathExists(self, path):
1610
1178
        """Fail unless path or paths, which may be abs or relative, exist."""
1611
1179
        if not isinstance(path, basestring):
1612
1180
            for p in path:
1613
 
                self.assertPathExists(p)
 
1181
                self.failUnlessExists(p)
1614
1182
        else:
1615
 
            self.assertTrue(osutils.lexists(path),
1616
 
                path + " does not exist")
 
1183
            self.failUnless(osutils.lexists(path),path+" does not exist")
1617
1184
 
1618
 
    @symbol_versioning.deprecated_method(symbol_versioning.deprecated_in((2, 4)))
1619
1185
    def failIfExists(self, path):
1620
 
        return self.assertPathDoesNotExist(path)
1621
 
 
1622
 
    def assertPathDoesNotExist(self, path):
1623
1186
        """Fail if path or paths, which may be abs or relative, exist."""
1624
1187
        if not isinstance(path, basestring):
1625
1188
            for p in path:
1626
 
                self.assertPathDoesNotExist(p)
 
1189
                self.failIfExists(p)
1627
1190
        else:
1628
 
            self.assertFalse(osutils.lexists(path),
1629
 
                path + " exists")
 
1191
            self.failIf(osutils.lexists(path),path+" exists")
1630
1192
 
1631
1193
    def _capture_deprecation_warnings(self, a_callable, *args, **kwargs):
1632
1194
        """A helper for callDeprecated and applyDeprecated.
1658
1220
        not other callers that go direct to the warning module.
1659
1221
 
1660
1222
        To test that a deprecated method raises an error, do something like
1661
 
        this (remember that both assertRaises and applyDeprecated delays *args
1662
 
        and **kwargs passing)::
 
1223
        this::
1663
1224
 
1664
1225
            self.assertRaises(errors.ReservedId,
1665
1226
                self.applyDeprecated,
1743
1304
        return result
1744
1305
 
1745
1306
    def _startLogFile(self):
1746
 
        """Setup a in-memory target for bzr and testcase log messages"""
1747
 
        pseudo_log_file = StringIO()
1748
 
        def _get_log_contents_for_weird_testtools_api():
1749
 
            return [pseudo_log_file.getvalue().decode(
1750
 
                "utf-8", "replace").encode("utf-8")]
1751
 
        self.addDetail("log", content.Content(content.ContentType("text",
1752
 
            "plain", {"charset": "utf8"}),
1753
 
            _get_log_contents_for_weird_testtools_api))
1754
 
        self._log_file = pseudo_log_file
1755
 
        self._log_memento = trace.push_log_file(self._log_file)
 
1307
        """Send bzr and test log messages to a temporary file.
 
1308
 
 
1309
        The file is removed as the test is torn down.
 
1310
        """
 
1311
        fileno, name = tempfile.mkstemp(suffix='.log', prefix='testbzr')
 
1312
        self._log_file = os.fdopen(fileno, 'w+')
 
1313
        self._log_memento = bzrlib.trace.push_log_file(self._log_file)
 
1314
        self._log_file_name = name
1756
1315
        self.addCleanup(self._finishLogFile)
1757
1316
 
1758
1317
    def _finishLogFile(self):
1759
 
        """Flush and dereference the in-memory log for this testcase"""
1760
 
        if trace._trace_file:
1761
 
            # flush the log file, to get all content
1762
 
            trace._trace_file.flush()
1763
 
        trace.pop_log_file(self._log_memento)
1764
 
        # The logging module now tracks references for cleanup so discard ours
1765
 
        del self._log_memento
 
1318
        """Finished with the log file.
 
1319
 
 
1320
        Close the file and delete it, unless setKeepLogfile was called.
 
1321
        """
 
1322
        if self._log_file is None:
 
1323
            return
 
1324
        bzrlib.trace.pop_log_file(self._log_memento)
 
1325
        self._log_file.close()
 
1326
        self._log_file = None
 
1327
        if not self._keep_log_file:
 
1328
            os.remove(self._log_file_name)
 
1329
            self._log_file_name = None
 
1330
 
 
1331
    def setKeepLogfile(self):
 
1332
        """Make the logfile not be deleted when _finishLogFile is called."""
 
1333
        self._keep_log_file = True
1766
1334
 
1767
1335
    def thisFailsStrictLockCheck(self):
1768
1336
        """It is known that this test would fail with -Dstrict_locks.
1777
1345
        """
1778
1346
        debug.debug_flags.discard('strict_locks')
1779
1347
 
1780
 
    def overrideAttr(self, obj, attr_name, new=_unitialized_attr):
1781
 
        """Overrides an object attribute restoring it after the test.
1782
 
 
1783
 
        :note: This should be used with discretion; you should think about
1784
 
        whether it's better to make the code testable without monkey-patching.
1785
 
 
1786
 
        :param obj: The object that will be mutated.
1787
 
 
1788
 
        :param attr_name: The attribute name we want to preserve/override in
1789
 
            the object.
1790
 
 
1791
 
        :param new: The optional value we want to set the attribute to.
1792
 
 
1793
 
        :returns: The actual attr value.
1794
 
        """
1795
 
        # The actual value is captured by the call below
1796
 
        value = getattr(obj, attr_name, _unitialized_attr)
1797
 
        if value is _unitialized_attr:
1798
 
            # When the test completes, the attribute should not exist, but if
1799
 
            # we aren't setting a value, we don't need to do anything.
1800
 
            if new is not _unitialized_attr:
1801
 
                self.addCleanup(delattr, obj, attr_name)
1802
 
        else:
1803
 
            self.addCleanup(setattr, obj, attr_name, value)
1804
 
        if new is not _unitialized_attr:
1805
 
            setattr(obj, attr_name, new)
1806
 
        return value
1807
 
 
1808
 
    def overrideEnv(self, name, new):
1809
 
        """Set an environment variable, and reset it after the test.
1810
 
 
1811
 
        :param name: The environment variable name.
1812
 
 
1813
 
        :param new: The value to set the variable to. If None, the 
1814
 
            variable is deleted from the environment.
1815
 
 
1816
 
        :returns: The actual variable value.
1817
 
        """
1818
 
        value = osutils.set_or_unset_env(name, new)
1819
 
        self.addCleanup(osutils.set_or_unset_env, name, value)
1820
 
        return value
1821
 
 
1822
 
    def recordCalls(self, obj, attr_name):
1823
 
        """Monkeypatch in a wrapper that will record calls.
1824
 
 
1825
 
        The monkeypatch is automatically removed when the test concludes.
1826
 
 
1827
 
        :param obj: The namespace holding the reference to be replaced;
1828
 
            typically a module, class, or object.
1829
 
        :param attr_name: A string for the name of the attribute to 
1830
 
            patch.
1831
 
        :returns: A list that will be extended with one item every time the
1832
 
            function is called, with a tuple of (args, kwargs).
1833
 
        """
1834
 
        calls = []
1835
 
 
1836
 
        def decorator(*args, **kwargs):
1837
 
            calls.append((args, kwargs))
1838
 
            return orig(*args, **kwargs)
1839
 
        orig = self.overrideAttr(obj, attr_name, decorator)
1840
 
        return calls
 
1348
    def addCleanup(self, callable, *args, **kwargs):
 
1349
        """Arrange to run a callable when this case is torn down.
 
1350
 
 
1351
        Callables are run in the reverse of the order they are registered,
 
1352
        ie last-in first-out.
 
1353
        """
 
1354
        self._cleanups.append((callable, args, kwargs))
1841
1355
 
1842
1356
    def _cleanEnvironment(self):
1843
 
        for name, value in isolated_environ.iteritems():
1844
 
            self.overrideEnv(name, value)
 
1357
        new_env = {
 
1358
            'BZR_HOME': None, # Don't inherit BZR_HOME to all the tests.
 
1359
            'HOME': os.getcwd(),
 
1360
            # bzr now uses the Win32 API and doesn't rely on APPDATA, but the
 
1361
            # tests do check our impls match APPDATA
 
1362
            'BZR_EDITOR': None, # test_msgeditor manipulates this variable
 
1363
            'VISUAL': None,
 
1364
            'EDITOR': None,
 
1365
            'BZR_EMAIL': None,
 
1366
            'BZREMAIL': None, # may still be present in the environment
 
1367
            'EMAIL': None,
 
1368
            'BZR_PROGRESS_BAR': None,
 
1369
            'BZR_LOG': None,
 
1370
            'BZR_PLUGIN_PATH': None,
 
1371
            # Make sure that any text ui tests are consistent regardless of
 
1372
            # the environment the test case is run in; you may want tests that
 
1373
            # test other combinations.  'dumb' is a reasonable guess for tests
 
1374
            # going to a pipe or a StringIO.
 
1375
            'TERM': 'dumb',
 
1376
            'LINES': '25',
 
1377
            'COLUMNS': '80',
 
1378
            # SSH Agent
 
1379
            'SSH_AUTH_SOCK': None,
 
1380
            # Proxies
 
1381
            'http_proxy': None,
 
1382
            'HTTP_PROXY': None,
 
1383
            'https_proxy': None,
 
1384
            'HTTPS_PROXY': None,
 
1385
            'no_proxy': None,
 
1386
            'NO_PROXY': None,
 
1387
            'all_proxy': None,
 
1388
            'ALL_PROXY': None,
 
1389
            # Nobody cares about ftp_proxy, FTP_PROXY AFAIK. So far at
 
1390
            # least. If you do (care), please update this comment
 
1391
            # -- vila 20080401
 
1392
            'ftp_proxy': None,
 
1393
            'FTP_PROXY': None,
 
1394
            'BZR_REMOTE_PATH': None,
 
1395
        }
 
1396
        self.__old_env = {}
 
1397
        self.addCleanup(self._restoreEnvironment)
 
1398
        for name, value in new_env.iteritems():
 
1399
            self._captureVar(name, value)
 
1400
 
 
1401
    def _captureVar(self, name, newvalue):
 
1402
        """Set an environment variable, and reset it when finished."""
 
1403
        self.__old_env[name] = osutils.set_or_unset_env(name, newvalue)
 
1404
 
 
1405
    def _restore_debug_flags(self):
 
1406
        debug.debug_flags.clear()
 
1407
        debug.debug_flags.update(self._preserved_debug_flags)
 
1408
 
 
1409
    def _restoreEnvironment(self):
 
1410
        for name, value in self.__old_env.iteritems():
 
1411
            osutils.set_or_unset_env(name, value)
1845
1412
 
1846
1413
    def _restoreHooks(self):
1847
1414
        for klass, (name, hooks) in self._preserved_hooks.items():
1848
1415
            setattr(klass, name, hooks)
1849
 
        self._preserved_hooks.clear()
1850
 
        bzrlib.hooks._lazy_hooks = self._preserved_lazy_hooks
1851
 
        self._preserved_lazy_hooks.clear()
1852
1416
 
1853
1417
    def knownFailure(self, reason):
1854
 
        """Declare that this test fails for a known reason
1855
 
 
1856
 
        Tests that are known to fail should generally be using expectedFailure
1857
 
        with an appropriate reverse assertion if a change could cause the test
1858
 
        to start passing. Conversely if the test has no immediate prospect of
1859
 
        succeeding then using skip is more suitable.
1860
 
 
1861
 
        When this method is called while an exception is being handled, that
1862
 
        traceback will be used, otherwise a new exception will be thrown to
1863
 
        provide one but won't be reported.
1864
 
        """
1865
 
        self._add_reason(reason)
1866
 
        try:
1867
 
            exc_info = sys.exc_info()
1868
 
            if exc_info != (None, None, None):
1869
 
                self._report_traceback(exc_info)
1870
 
            else:
1871
 
                try:
1872
 
                    raise self.failureException(reason)
1873
 
                except self.failureException:
1874
 
                    exc_info = sys.exc_info()
1875
 
            # GZ 02-08-2011: Maybe cleanup this err.exc_info attribute too?
1876
 
            raise testtools.testcase._ExpectedFailure(exc_info)
1877
 
        finally:
1878
 
            del exc_info
1879
 
 
1880
 
    def _suppress_log(self):
1881
 
        """Remove the log info from details."""
1882
 
        self.discardDetail('log')
 
1418
        """This test has failed for some known reason."""
 
1419
        raise KnownFailure(reason)
1883
1420
 
1884
1421
    def _do_skip(self, result, reason):
1885
 
        self._suppress_log()
1886
1422
        addSkip = getattr(result, 'addSkip', None)
1887
1423
        if not callable(addSkip):
1888
 
            result.addSuccess(result)
 
1424
            result.addError(self, sys.exc_info())
1889
1425
        else:
1890
1426
            addSkip(self, reason)
1891
1427
 
1892
 
    @staticmethod
1893
 
    def _do_known_failure(self, result, e):
1894
 
        self._suppress_log()
1895
 
        err = sys.exc_info()
1896
 
        addExpectedFailure = getattr(result, 'addExpectedFailure', None)
1897
 
        if addExpectedFailure is not None:
1898
 
            addExpectedFailure(self, err)
1899
 
        else:
1900
 
            result.addSuccess(self)
1901
 
 
1902
 
    @staticmethod
1903
 
    def _do_not_applicable(self, result, e):
1904
 
        if not e.args:
1905
 
            reason = 'No reason given'
1906
 
        else:
1907
 
            reason = e.args[0]
1908
 
        self._suppress_log ()
1909
 
        addNotApplicable = getattr(result, 'addNotApplicable', None)
1910
 
        if addNotApplicable is not None:
1911
 
            result.addNotApplicable(self, reason)
1912
 
        else:
1913
 
            self._do_skip(result, reason)
1914
 
 
1915
 
    @staticmethod
1916
 
    def _report_skip(self, result, err):
1917
 
        """Override the default _report_skip.
1918
 
 
1919
 
        We want to strip the 'log' detail. If we waint until _do_skip, it has
1920
 
        already been formatted into the 'reason' string, and we can't pull it
1921
 
        out again.
1922
 
        """
1923
 
        self._suppress_log()
1924
 
        super(TestCase, self)._report_skip(self, result, err)
1925
 
 
1926
 
    @staticmethod
1927
 
    def _report_expected_failure(self, result, err):
1928
 
        """Strip the log.
1929
 
 
1930
 
        See _report_skip for motivation.
1931
 
        """
1932
 
        self._suppress_log()
1933
 
        super(TestCase, self)._report_expected_failure(self, result, err)
1934
 
 
1935
 
    @staticmethod
1936
 
    def _do_unsupported_or_skip(self, result, e):
1937
 
        reason = e.args[0]
1938
 
        self._suppress_log()
1939
 
        addNotSupported = getattr(result, 'addNotSupported', None)
1940
 
        if addNotSupported is not None:
1941
 
            result.addNotSupported(self, reason)
1942
 
        else:
1943
 
            self._do_skip(result, reason)
 
1428
    def run(self, result=None):
 
1429
        if result is None: result = self.defaultTestResult()
 
1430
        for feature in getattr(self, '_test_needs_features', []):
 
1431
            if not feature.available():
 
1432
                result.startTest(self)
 
1433
                if getattr(result, 'addNotSupported', None):
 
1434
                    result.addNotSupported(self, feature)
 
1435
                else:
 
1436
                    result.addSuccess(self)
 
1437
                result.stopTest(self)
 
1438
                return result
 
1439
        try:
 
1440
            try:
 
1441
                result.startTest(self)
 
1442
                absent_attr = object()
 
1443
                # Python 2.5
 
1444
                method_name = getattr(self, '_testMethodName', absent_attr)
 
1445
                if method_name is absent_attr:
 
1446
                    # Python 2.4
 
1447
                    method_name = getattr(self, '_TestCase__testMethodName')
 
1448
                testMethod = getattr(self, method_name)
 
1449
                try:
 
1450
                    try:
 
1451
                        self.setUp()
 
1452
                        if not self._bzr_test_setUp_run:
 
1453
                            self.fail(
 
1454
                                "test setUp did not invoke "
 
1455
                                "bzrlib.tests.TestCase's setUp")
 
1456
                    except KeyboardInterrupt:
 
1457
                        self._runCleanups()
 
1458
                        raise
 
1459
                    except TestSkipped, e:
 
1460
                        self._do_skip(result, e.args[0])
 
1461
                        self.tearDown()
 
1462
                        return result
 
1463
                    except:
 
1464
                        result.addError(self, sys.exc_info())
 
1465
                        self._runCleanups()
 
1466
                        return result
 
1467
 
 
1468
                    ok = False
 
1469
                    try:
 
1470
                        testMethod()
 
1471
                        ok = True
 
1472
                    except self.failureException:
 
1473
                        result.addFailure(self, sys.exc_info())
 
1474
                    except TestSkipped, e:
 
1475
                        if not e.args:
 
1476
                            reason = "No reason given."
 
1477
                        else:
 
1478
                            reason = e.args[0]
 
1479
                        self._do_skip(result, reason)
 
1480
                    except KeyboardInterrupt:
 
1481
                        self._runCleanups()
 
1482
                        raise
 
1483
                    except:
 
1484
                        result.addError(self, sys.exc_info())
 
1485
 
 
1486
                    try:
 
1487
                        self.tearDown()
 
1488
                        if not self._bzr_test_tearDown_run:
 
1489
                            self.fail(
 
1490
                                "test tearDown did not invoke "
 
1491
                                "bzrlib.tests.TestCase's tearDown")
 
1492
                    except KeyboardInterrupt:
 
1493
                        self._runCleanups()
 
1494
                        raise
 
1495
                    except:
 
1496
                        result.addError(self, sys.exc_info())
 
1497
                        self._runCleanups()
 
1498
                        ok = False
 
1499
                    if ok: result.addSuccess(self)
 
1500
                finally:
 
1501
                    result.stopTest(self)
 
1502
                return result
 
1503
            except TestNotApplicable:
 
1504
                # Not moved from the result [yet].
 
1505
                self._runCleanups()
 
1506
                raise
 
1507
            except KeyboardInterrupt:
 
1508
                self._runCleanups()
 
1509
                raise
 
1510
        finally:
 
1511
            saved_attrs = {}
 
1512
            for attr_name in self.attrs_to_keep:
 
1513
                if attr_name in self.__dict__:
 
1514
                    saved_attrs[attr_name] = self.__dict__[attr_name]
 
1515
            self.__dict__ = saved_attrs
 
1516
 
 
1517
    def tearDown(self):
 
1518
        self._runCleanups()
 
1519
        self._log_contents = ''
 
1520
        self._bzr_test_tearDown_run = True
 
1521
        unittest.TestCase.tearDown(self)
1944
1522
 
1945
1523
    def time(self, callable, *args, **kwargs):
1946
1524
        """Run callable and accrue the time it takes to the benchmark time.
1950
1528
        self._benchcalls.
1951
1529
        """
1952
1530
        if self._benchtime is None:
1953
 
            self.addDetail('benchtime', content.Content(content.ContentType(
1954
 
                "text", "plain"), lambda:[str(self._benchtime)]))
1955
1531
            self._benchtime = 0
1956
1532
        start = time.time()
1957
1533
        try:
1966
1542
        finally:
1967
1543
            self._benchtime += time.time() - start
1968
1544
 
 
1545
    def _runCleanups(self):
 
1546
        """Run registered cleanup functions.
 
1547
 
 
1548
        This should only be called from TestCase.tearDown.
 
1549
        """
 
1550
        # TODO: Perhaps this should keep running cleanups even if
 
1551
        # one of them fails?
 
1552
 
 
1553
        # Actually pop the cleanups from the list so tearDown running
 
1554
        # twice is safe (this happens for skipped tests).
 
1555
        while self._cleanups:
 
1556
            cleanup, args, kwargs = self._cleanups.pop()
 
1557
            cleanup(*args, **kwargs)
 
1558
 
1969
1559
    def log(self, *args):
1970
 
        trace.mutter(*args)
1971
 
 
1972
 
    def get_log(self):
1973
 
        """Get a unicode string containing the log from bzrlib.trace.
1974
 
 
1975
 
        Undecodable characters are replaced.
 
1560
        mutter(*args)
 
1561
 
 
1562
    def _get_log(self, keep_log_file=False):
 
1563
        """Get the log from bzrlib.trace calls from this test.
 
1564
 
 
1565
        :param keep_log_file: When True, if the log is still a file on disk
 
1566
            leave it as a file on disk. When False, if the log is still a file
 
1567
            on disk, the log file is deleted and the log preserved as
 
1568
            self._log_contents.
 
1569
        :return: A string containing the log.
1976
1570
        """
1977
 
        return u"".join(self.getDetails()['log'].iter_text())
 
1571
        # flush the log file, to get all content
 
1572
        import bzrlib.trace
 
1573
        if bzrlib.trace._trace_file:
 
1574
            bzrlib.trace._trace_file.flush()
 
1575
        if self._log_contents:
 
1576
            # XXX: this can hardly contain the content flushed above --vila
 
1577
            # 20080128
 
1578
            return self._log_contents
 
1579
        if self._log_file_name is not None:
 
1580
            logfile = open(self._log_file_name)
 
1581
            try:
 
1582
                log_contents = logfile.read()
 
1583
            finally:
 
1584
                logfile.close()
 
1585
            if not keep_log_file:
 
1586
                self._log_contents = log_contents
 
1587
                try:
 
1588
                    os.remove(self._log_file_name)
 
1589
                except OSError, e:
 
1590
                    if sys.platform == 'win32' and e.errno == errno.EACCES:
 
1591
                        sys.stderr.write(('Unable to delete log file '
 
1592
                                             ' %r\n' % self._log_file_name))
 
1593
                    else:
 
1594
                        raise
 
1595
            return log_contents
 
1596
        else:
 
1597
            return "DELETED log file to reduce memory footprint"
1978
1598
 
1979
1599
    def requireFeature(self, feature):
1980
1600
        """This test requires a specific feature is available.
1997
1617
 
1998
1618
    def _run_bzr_core(self, args, retcode, encoding, stdin,
1999
1619
            working_dir):
2000
 
        # Clear chk_map page cache, because the contents are likely to mask
2001
 
        # locking errors.
2002
 
        chk_map.clear_cache()
2003
1620
        if encoding is None:
2004
1621
            encoding = osutils.get_user_encoding()
2005
1622
        stdout = StringIOWrapper()
2009
1626
 
2010
1627
        self.log('run bzr: %r', args)
2011
1628
        # FIXME: don't call into logging here
2012
 
        handler = trace.EncodedStreamHandler(stderr, errors="replace",
2013
 
            level=logging.INFO)
 
1629
        handler = logging.StreamHandler(stderr)
 
1630
        handler.setLevel(logging.INFO)
2014
1631
        logger = logging.getLogger('')
2015
1632
        logger.addHandler(handler)
2016
1633
        old_ui_factory = ui.ui_factory
2022
1639
            os.chdir(working_dir)
2023
1640
 
2024
1641
        try:
2025
 
            try:
2026
 
                result = self.apply_redirected(
2027
 
                    ui.ui_factory.stdin,
2028
 
                    stdout, stderr,
2029
 
                    _mod_commands.run_bzr_catch_user_errors,
2030
 
                    args)
2031
 
            except KeyboardInterrupt:
2032
 
                # Reraise KeyboardInterrupt with contents of redirected stdout
2033
 
                # and stderr as arguments, for tests which are interested in
2034
 
                # stdout and stderr and are expecting the exception.
2035
 
                out = stdout.getvalue()
2036
 
                err = stderr.getvalue()
2037
 
                if out:
2038
 
                    self.log('output:\n%r', out)
2039
 
                if err:
2040
 
                    self.log('errors:\n%r', err)
2041
 
                raise KeyboardInterrupt(out, err)
 
1642
            result = self.apply_redirected(ui.ui_factory.stdin,
 
1643
                stdout, stderr,
 
1644
                bzrlib.commands.run_bzr_catch_user_errors,
 
1645
                args)
2042
1646
        finally:
2043
1647
            logger.removeHandler(handler)
2044
1648
            ui.ui_factory = old_ui_factory
2052
1656
        if err:
2053
1657
            self.log('errors:\n%r', err)
2054
1658
        if retcode is not None:
2055
 
            self.assertEqual(retcode, result,
 
1659
            self.assertEquals(retcode, result,
2056
1660
                              message='Unexpected return code')
2057
 
        return result, out, err
 
1661
        return out, err
2058
1662
 
2059
1663
    def run_bzr(self, args, retcode=0, encoding=None, stdin=None,
2060
1664
                working_dir=None, error_regexes=[], output_encoding=None):
2089
1693
        :keyword error_regexes: A list of expected error messages.  If
2090
1694
            specified they must be seen in the error output of the command.
2091
1695
        """
2092
 
        retcode, out, err = self._run_bzr_autosplit(
 
1696
        out, err = self._run_bzr_autosplit(
2093
1697
            args=args,
2094
1698
            retcode=retcode,
2095
1699
            encoding=encoding,
2174
1778
    def start_bzr_subprocess(self, process_args, env_changes=None,
2175
1779
                             skip_if_plan_to_signal=False,
2176
1780
                             working_dir=None,
2177
 
                             allow_plugins=False, stderr=subprocess.PIPE):
 
1781
                             allow_plugins=False):
2178
1782
        """Start bzr in a subprocess for testing.
2179
1783
 
2180
1784
        This starts a new Python interpreter and runs bzr in there.
2189
1793
            variables. A value of None will unset the env variable.
2190
1794
            The values must be strings. The change will only occur in the
2191
1795
            child, so you don't need to fix the environment after running.
2192
 
        :param skip_if_plan_to_signal: raise TestSkipped when true and system
2193
 
            doesn't support signalling subprocesses.
 
1796
        :param skip_if_plan_to_signal: raise TestSkipped when true and os.kill
 
1797
            is not available.
2194
1798
        :param allow_plugins: If False (default) pass --no-plugins to bzr.
2195
 
        :param stderr: file to use for the subprocess's stderr.  Valid values
2196
 
            are those valid for the stderr argument of `subprocess.Popen`.
2197
 
            Default value is ``subprocess.PIPE``.
2198
1799
 
2199
1800
        :returns: Popen object for the started process.
2200
1801
        """
2201
1802
        if skip_if_plan_to_signal:
2202
 
            if os.name != "posix":
2203
 
                raise TestSkipped("Sending signals not supported")
 
1803
            if not getattr(os, 'kill', None):
 
1804
                raise TestSkipped("os.kill not available.")
2204
1805
 
2205
1806
        if env_changes is None:
2206
1807
            env_changes = {}
2207
 
        # Because $HOME is set to a tempdir for the context of a test, modules
2208
 
        # installed in the user dir will not be found unless $PYTHONUSERBASE
2209
 
        # gets set to the computed directory of this parent process.
2210
 
        if site.USER_BASE is not None:
2211
 
            env_changes["PYTHONUSERBASE"] = site.USER_BASE
2212
1808
        old_env = {}
2213
1809
 
2214
1810
        def cleanup_environment():
2231
1827
            # so we will avoid using it on all platforms, just to
2232
1828
            # make sure the code path is used, and we don't break on win32
2233
1829
            cleanup_environment()
2234
 
            # Include the subprocess's log file in the test details, in case
2235
 
            # the test fails due to an error in the subprocess.
2236
 
            self._add_subprocess_log(trace._get_bzr_log_filename())
2237
1830
            command = [sys.executable]
2238
1831
            # frozen executables don't need the path to bzr
2239
1832
            if getattr(sys, "frozen", None) is None:
2241
1834
            if not allow_plugins:
2242
1835
                command.append('--no-plugins')
2243
1836
            command.extend(process_args)
2244
 
            process = self._popen(command, stdin=subprocess.PIPE,
2245
 
                                  stdout=subprocess.PIPE,
2246
 
                                  stderr=stderr)
 
1837
            process = self._popen(command, stdin=PIPE, stdout=PIPE, stderr=PIPE)
2247
1838
        finally:
2248
1839
            restore_environment()
2249
1840
            if cwd is not None:
2251
1842
 
2252
1843
        return process
2253
1844
 
2254
 
    def _add_subprocess_log(self, log_file_path):
2255
 
        if len(self._log_files) == 0:
2256
 
            # Register an addCleanup func.  We do this on the first call to
2257
 
            # _add_subprocess_log rather than in TestCase.setUp so that this
2258
 
            # addCleanup is registered after any cleanups for tempdirs that
2259
 
            # subclasses might create, which will probably remove the log file
2260
 
            # we want to read.
2261
 
            self.addCleanup(self._subprocess_log_cleanup)
2262
 
        # self._log_files is a set, so if a log file is reused we won't grab it
2263
 
        # twice.
2264
 
        self._log_files.add(log_file_path)
2265
 
 
2266
 
    def _subprocess_log_cleanup(self):
2267
 
        for count, log_file_path in enumerate(self._log_files):
2268
 
            # We use buffer_now=True to avoid holding the file open beyond
2269
 
            # the life of this function, which might interfere with e.g.
2270
 
            # cleaning tempdirs on Windows.
2271
 
            # XXX: Testtools 0.9.5 doesn't have the content_from_file helper
2272
 
            #detail_content = content.content_from_file(
2273
 
            #    log_file_path, buffer_now=True)
2274
 
            with open(log_file_path, 'rb') as log_file:
2275
 
                log_file_bytes = log_file.read()
2276
 
            detail_content = content.Content(content.ContentType("text",
2277
 
                "plain", {"charset": "utf8"}), lambda: [log_file_bytes])
2278
 
            self.addDetail("start_bzr_subprocess-log-%d" % (count,),
2279
 
                detail_content)
2280
 
 
2281
1845
    def _popen(self, *args, **kwargs):
2282
1846
        """Place a call to Popen.
2283
1847
 
2284
1848
        Allows tests to override this method to intercept the calls made to
2285
1849
        Popen for introspection.
2286
1850
        """
2287
 
        return subprocess.Popen(*args, **kwargs)
2288
 
 
2289
 
    def get_source_path(self):
2290
 
        """Return the path of the directory containing bzrlib."""
2291
 
        return os.path.dirname(os.path.dirname(bzrlib.__file__))
 
1851
        return Popen(*args, **kwargs)
2292
1852
 
2293
1853
    def get_bzr_path(self):
2294
1854
        """Return the path of the 'bzr' executable for this test suite."""
2295
 
        bzr_path = os.path.join(self.get_source_path(), "bzr")
 
1855
        bzr_path = os.path.dirname(os.path.dirname(bzrlib.__file__))+'/bzr'
2296
1856
        if not os.path.isfile(bzr_path):
2297
1857
            # We are probably installed. Assume sys.argv is the right file
2298
1858
            bzr_path = sys.argv[0]
2320
1880
        if retcode is not None and retcode != process.returncode:
2321
1881
            if process_args is None:
2322
1882
                process_args = "(unknown args)"
2323
 
            trace.mutter('Output of bzr %s:\n%s', process_args, out)
2324
 
            trace.mutter('Error for bzr %s:\n%s', process_args, err)
 
1883
            mutter('Output of bzr %s:\n%s', process_args, out)
 
1884
            mutter('Error for bzr %s:\n%s', process_args, err)
2325
1885
            self.fail('Command bzr %s failed with retcode %s != %s'
2326
1886
                      % (process_args, retcode, process.returncode))
2327
1887
        return [out, err]
2328
1888
 
2329
 
    def check_tree_shape(self, tree, shape):
2330
 
        """Compare a tree to a list of expected names.
 
1889
    def check_inventory_shape(self, inv, shape):
 
1890
        """Compare an inventory to a list of expected names.
2331
1891
 
2332
1892
        Fail if they are not precisely equal.
2333
1893
        """
2334
1894
        extras = []
2335
1895
        shape = list(shape)             # copy
2336
 
        for path, ie in tree.iter_entries_by_dir():
 
1896
        for path, ie in inv.entries():
2337
1897
            name = path.replace('\\', '/')
2338
1898
            if ie.kind == 'directory':
2339
1899
                name = name + '/'
2340
 
            if name == "/":
2341
 
                pass # ignore root entry
2342
 
            elif name in shape:
 
1900
            if name in shape:
2343
1901
                shape.remove(name)
2344
1902
            else:
2345
1903
                extras.append(name)
2386
1944
 
2387
1945
        Tests that expect to provoke LockContention errors should call this.
2388
1946
        """
2389
 
        self.overrideAttr(lockdir, '_DEFAULT_TIMEOUT_SECONDS', 0)
 
1947
        orig_timeout = bzrlib.lockdir._DEFAULT_TIMEOUT_SECONDS
 
1948
        def resetTimeout():
 
1949
            bzrlib.lockdir._DEFAULT_TIMEOUT_SECONDS = orig_timeout
 
1950
        self.addCleanup(resetTimeout)
 
1951
        bzrlib.lockdir._DEFAULT_TIMEOUT_SECONDS = 0
2390
1952
 
2391
1953
    def make_utf8_encoded_stringio(self, encoding_type=None):
2392
1954
        """Return a StringIOWrapper instance, that will encode Unicode
2405
1967
        from bzrlib.smart import request
2406
1968
        request_handlers = request.request_handlers
2407
1969
        orig_method = request_handlers.get(verb)
2408
 
        orig_info = request_handlers.get_info(verb)
2409
1970
        request_handlers.remove(verb)
2410
 
        self.addCleanup(request_handlers.register, verb, orig_method,
2411
 
            info=orig_info)
 
1971
        def restoreVerb():
 
1972
            request_handlers.register(verb, orig_method)
 
1973
        self.addCleanup(restoreVerb)
2412
1974
 
2413
1975
 
2414
1976
class CapturedCall(object):
2437
1999
class TestCaseWithMemoryTransport(TestCase):
2438
2000
    """Common test class for tests that do not need disk resources.
2439
2001
 
2440
 
    Tests that need disk resources should derive from TestCaseInTempDir
2441
 
    orTestCaseWithTransport.
 
2002
    Tests that need disk resources should derive from TestCaseWithTransport.
2442
2003
 
2443
2004
    TestCaseWithMemoryTransport sets the TEST_ROOT variable for all bzr tests.
2444
2005
 
2445
 
    For TestCaseWithMemoryTransport the ``test_home_dir`` is set to the name of
 
2006
    For TestCaseWithMemoryTransport the test_home_dir is set to the name of
2446
2007
    a directory which does not exist. This serves to help ensure test isolation
2447
 
    is preserved. ``test_dir`` is set to the TEST_ROOT, as is cwd, because they
2448
 
    must exist. However, TestCaseWithMemoryTransport does not offer local file
2449
 
    defaults for the transport in tests, nor does it obey the command line
 
2008
    is preserved. test_dir is set to the TEST_ROOT, as is cwd, because they
 
2009
    must exist. However, TestCaseWithMemoryTransport does not offer local
 
2010
    file defaults for the transport in tests, nor does it obey the command line
2450
2011
    override, so tests that accidentally write to the common directory should
2451
2012
    be rare.
2452
2013
 
2453
 
    :cvar TEST_ROOT: Directory containing all temporary directories, plus a
2454
 
        ``.bzr`` directory that stops us ascending higher into the filesystem.
 
2014
    :cvar TEST_ROOT: Directory containing all temporary directories, plus
 
2015
    a .bzr directory that stops us ascending higher into the filesystem.
2455
2016
    """
2456
2017
 
2457
2018
    TEST_ROOT = None
2467
2028
        self.transport_readonly_server = None
2468
2029
        self.__vfs_server = None
2469
2030
 
2470
 
    def setUp(self):
2471
 
        super(TestCaseWithMemoryTransport, self).setUp()
2472
 
 
2473
 
        def _add_disconnect_cleanup(transport):
2474
 
            """Schedule disconnection of given transport at test cleanup
2475
 
 
2476
 
            This needs to happen for all connected transports or leaks occur.
2477
 
 
2478
 
            Note reconnections may mean we call disconnect multiple times per
2479
 
            transport which is suboptimal but seems harmless.
2480
 
            """
2481
 
            self.addCleanup(transport.disconnect)
2482
 
 
2483
 
        _mod_transport.Transport.hooks.install_named_hook('post_connect',
2484
 
            _add_disconnect_cleanup, None)
2485
 
 
2486
 
        self._make_test_root()
2487
 
        self.addCleanup(os.chdir, os.getcwdu())
2488
 
        self.makeAndChdirToTestDir()
2489
 
        self.overrideEnvironmentForTesting()
2490
 
        self.__readonly_server = None
2491
 
        self.__server = None
2492
 
        self.reduceLockdirTimeout()
2493
 
        # Each test may use its own config files even if the local config files
2494
 
        # don't actually exist. They'll rightly fail if they try to create them
2495
 
        # though.
2496
 
        self.overrideAttr(config, '_shared_stores', {})
2497
 
 
2498
2031
    def get_transport(self, relpath=None):
2499
2032
        """Return a writeable transport.
2500
2033
 
2503
2036
 
2504
2037
        :param relpath: a path relative to the base url.
2505
2038
        """
2506
 
        t = _mod_transport.get_transport_from_url(self.get_url(relpath))
 
2039
        t = get_transport(self.get_url(relpath))
2507
2040
        self.assertFalse(t.is_readonly())
2508
2041
        return t
2509
2042
 
2515
2048
 
2516
2049
        :param relpath: a path relative to the base url.
2517
2050
        """
2518
 
        t = _mod_transport.get_transport_from_url(
2519
 
            self.get_readonly_url(relpath))
 
2051
        t = get_transport(self.get_readonly_url(relpath))
2520
2052
        self.assertTrue(t.is_readonly())
2521
2053
        return t
2522
2054
 
2535
2067
        if self.__readonly_server is None:
2536
2068
            if self.transport_readonly_server is None:
2537
2069
                # readonly decorator requested
2538
 
                self.__readonly_server = test_server.ReadonlyServer()
 
2070
                # bring up the server
 
2071
                self.__readonly_server = ReadonlyServer()
 
2072
                self.__readonly_server.setUp(self.get_vfs_only_server())
2539
2073
            else:
2540
 
                # explicit readonly transport.
2541
2074
                self.__readonly_server = self.create_transport_readonly_server()
2542
 
            self.start_server(self.__readonly_server,
2543
 
                self.get_vfs_only_server())
 
2075
                self.__readonly_server.setUp(self.get_vfs_only_server())
 
2076
            self.addCleanup(self.__readonly_server.tearDown)
2544
2077
        return self.__readonly_server
2545
2078
 
2546
2079
    def get_readonly_url(self, relpath=None):
2564
2097
        is no means to override it.
2565
2098
        """
2566
2099
        if self.__vfs_server is None:
2567
 
            self.__vfs_server = memory.MemoryServer()
2568
 
            self.start_server(self.__vfs_server)
 
2100
            self.__vfs_server = MemoryServer()
 
2101
            self.__vfs_server.setUp()
 
2102
            self.addCleanup(self.__vfs_server.tearDown)
2569
2103
        return self.__vfs_server
2570
2104
 
2571
2105
    def get_server(self):
2578
2112
        then the self.get_vfs_server is returned.
2579
2113
        """
2580
2114
        if self.__server is None:
2581
 
            if (self.transport_server is None or self.transport_server is
2582
 
                self.vfs_transport_factory):
2583
 
                self.__server = self.get_vfs_only_server()
 
2115
            if self.transport_server is None or self.transport_server is self.vfs_transport_factory:
 
2116
                return self.get_vfs_only_server()
2584
2117
            else:
2585
2118
                # bring up a decorated means of access to the vfs only server.
2586
2119
                self.__server = self.transport_server()
2587
 
                self.start_server(self.__server, self.get_vfs_only_server())
 
2120
                try:
 
2121
                    self.__server.setUp(self.get_vfs_only_server())
 
2122
                except TypeError, e:
 
2123
                    # This should never happen; the try:Except here is to assist
 
2124
                    # developers having to update code rather than seeing an
 
2125
                    # uninformative TypeError.
 
2126
                    raise Exception, "Old server API in use: %s, %s" % (self.__server, e)
 
2127
            self.addCleanup(self.__server.tearDown)
2588
2128
        return self.__server
2589
2129
 
2590
2130
    def _adjust_url(self, base, relpath):
2643
2183
        real branch.
2644
2184
        """
2645
2185
        root = TestCaseWithMemoryTransport.TEST_ROOT
2646
 
        try:
2647
 
            # Make sure we get a readable and accessible home for .bzr.log
2648
 
            # and/or config files, and not fallback to weird defaults (see
2649
 
            # http://pad.lv/825027).
2650
 
            self.assertIs(None, os.environ.get('BZR_HOME', None))
2651
 
            os.environ['BZR_HOME'] = root
2652
 
            wt = controldir.ControlDir.create_standalone_workingtree(root)
2653
 
            del os.environ['BZR_HOME']
2654
 
        except Exception, e:
2655
 
            self.fail("Fail to initialize the safety net: %r\n" % (e,))
2656
 
        # Hack for speed: remember the raw bytes of the dirstate file so that
2657
 
        # we don't need to re-open the wt to check it hasn't changed.
2658
 
        TestCaseWithMemoryTransport._SAFETY_NET_PRISTINE_DIRSTATE = (
2659
 
            wt.control_transport.get_bytes('dirstate'))
 
2186
        bzrdir.BzrDir.create_standalone_workingtree(root)
2660
2187
 
2661
2188
    def _check_safety_net(self):
2662
2189
        """Check that the safety .bzr directory have not been touched.
2665
2192
        propagating. This method ensures than a test did not leaked.
2666
2193
        """
2667
2194
        root = TestCaseWithMemoryTransport.TEST_ROOT
2668
 
        t = _mod_transport.get_transport_from_path(root)
2669
 
        self.permit_url(t.base)
2670
 
        if (t.get_bytes('.bzr/checkout/dirstate') != 
2671
 
                TestCaseWithMemoryTransport._SAFETY_NET_PRISTINE_DIRSTATE):
 
2195
        wt = workingtree.WorkingTree.open(root)
 
2196
        last_rev = wt.last_revision()
 
2197
        if last_rev != 'null:':
2672
2198
            # The current test have modified the /bzr directory, we need to
2673
2199
            # recreate a new one or all the followng tests will fail.
2674
2200
            # If you need to inspect its content uncomment the following line
2675
2201
            # import pdb; pdb.set_trace()
2676
 
            _rmtree_temp_dir(root + '/.bzr', test_id=self.id())
 
2202
            _rmtree_temp_dir(root + '/.bzr')
2677
2203
            self._create_safety_net()
2678
2204
            raise AssertionError('%s/.bzr should not be modified' % root)
2679
2205
 
2680
2206
    def _make_test_root(self):
2681
2207
        if TestCaseWithMemoryTransport.TEST_ROOT is None:
2682
 
            # Watch out for tricky test dir (on OSX /tmp -> /private/tmp)
2683
 
            root = osutils.realpath(osutils.mkdtemp(prefix='testbzr-',
2684
 
                                                    suffix='.tmp'))
 
2208
            root = osutils.mkdtemp(prefix='testbzr-', suffix='.tmp')
2685
2209
            TestCaseWithMemoryTransport.TEST_ROOT = root
2686
2210
 
2687
2211
            self._create_safety_net()
2690
2214
            # specifically told when all tests are finished.  This will do.
2691
2215
            atexit.register(_rmtree_temp_dir, root)
2692
2216
 
2693
 
        self.permit_dir(TestCaseWithMemoryTransport.TEST_ROOT)
2694
2217
        self.addCleanup(self._check_safety_net)
2695
2218
 
2696
2219
    def makeAndChdirToTestDir(self):
2704
2227
        os.chdir(TestCaseWithMemoryTransport.TEST_ROOT)
2705
2228
        self.test_dir = TestCaseWithMemoryTransport.TEST_ROOT
2706
2229
        self.test_home_dir = self.test_dir + "/MemoryTransportMissingHomeDir"
2707
 
        self.permit_dir(self.test_dir)
2708
2230
 
2709
 
    def make_branch(self, relpath, format=None, name=None):
 
2231
    def make_branch(self, relpath, format=None):
2710
2232
        """Create a branch on the transport at relpath."""
2711
2233
        repo = self.make_repository(relpath, format=format)
2712
 
        return repo.bzrdir.create_branch(append_revisions_only=False,
2713
 
                                         name=name)
2714
 
 
2715
 
    def get_default_format(self):
2716
 
        return 'default'
2717
 
 
2718
 
    def resolve_format(self, format):
2719
 
        """Resolve an object to a ControlDir format object.
2720
 
 
2721
 
        The initial format object can either already be
2722
 
        a ControlDirFormat, None (for the default format),
2723
 
        or a string with the name of the control dir format.
2724
 
 
2725
 
        :param format: Object to resolve
2726
 
        :return A ControlDirFormat instance
2727
 
        """
2728
 
        if format is None:
2729
 
            format = self.get_default_format()
2730
 
        if isinstance(format, basestring):
2731
 
            format = controldir.format_registry.make_bzrdir(format)
2732
 
        return format
 
2234
        return repo.bzrdir.create_branch()
2733
2235
 
2734
2236
    def make_bzrdir(self, relpath, format=None):
2735
2237
        try:
2736
2238
            # might be a relative or absolute path
2737
2239
            maybe_a_url = self.get_url(relpath)
2738
2240
            segments = maybe_a_url.rsplit('/', 1)
2739
 
            t = _mod_transport.get_transport(maybe_a_url)
 
2241
            t = get_transport(maybe_a_url)
2740
2242
            if len(segments) > 1 and segments[-1] not in ('', '.'):
2741
2243
                t.ensure_base()
2742
 
            format = self.resolve_format(format)
 
2244
            if format is None:
 
2245
                format = 'default'
 
2246
            if isinstance(format, basestring):
 
2247
                format = bzrdir.format_registry.make_bzrdir(format)
2743
2248
            return format.initialize_on_transport(t)
2744
2249
        except errors.UninitializableFormat:
2745
2250
            raise TestSkipped("Format %s is not initializable." % format)
2746
2251
 
2747
 
    def make_repository(self, relpath, shared=None, format=None):
 
2252
    def make_repository(self, relpath, shared=False, format=None):
2748
2253
        """Create a repository on our default transport at relpath.
2749
2254
 
2750
2255
        Note that relpath must be a relative path, not a full url.
2756
2261
        made_control = self.make_bzrdir(relpath, format=format)
2757
2262
        return made_control.create_repository(shared=shared)
2758
2263
 
2759
 
    def make_smart_server(self, path, backing_server=None):
2760
 
        if backing_server is None:
2761
 
            backing_server = self.get_server()
2762
 
        smart_server = test_server.SmartTCPServer_for_testing()
2763
 
        self.start_server(smart_server, backing_server)
2764
 
        remote_transport = _mod_transport.get_transport_from_url(smart_server.get_url()
2765
 
                                                   ).clone(path)
 
2264
    def make_smart_server(self, path):
 
2265
        smart_server = server.SmartTCPServer_for_testing()
 
2266
        smart_server.setUp(self.get_server())
 
2267
        remote_transport = get_transport(smart_server.get_url()).clone(path)
 
2268
        self.addCleanup(smart_server.tearDown)
2766
2269
        return remote_transport
2767
2270
 
2768
2271
    def make_branch_and_memory_tree(self, relpath, format=None):
2775
2278
        return branchbuilder.BranchBuilder(branch=branch)
2776
2279
 
2777
2280
    def overrideEnvironmentForTesting(self):
2778
 
        test_home_dir = self.test_home_dir
2779
 
        if isinstance(test_home_dir, unicode):
2780
 
            test_home_dir = test_home_dir.encode(sys.getfilesystemencoding())
2781
 
        self.overrideEnv('HOME', test_home_dir)
2782
 
        self.overrideEnv('BZR_HOME', test_home_dir)
 
2281
        os.environ['HOME'] = self.test_home_dir
 
2282
        os.environ['BZR_HOME'] = self.test_home_dir
 
2283
 
 
2284
    def setUp(self):
 
2285
        super(TestCaseWithMemoryTransport, self).setUp()
 
2286
        self._make_test_root()
 
2287
        _currentdir = os.getcwdu()
 
2288
        def _leaveDirectory():
 
2289
            os.chdir(_currentdir)
 
2290
        self.addCleanup(_leaveDirectory)
 
2291
        self.makeAndChdirToTestDir()
 
2292
        self.overrideEnvironmentForTesting()
 
2293
        self.__readonly_server = None
 
2294
        self.__server = None
 
2295
        self.reduceLockdirTimeout()
2783
2296
 
2784
2297
    def setup_smart_server_with_call_log(self):
2785
2298
        """Sets up a smart server as the transport server with a call log."""
2786
 
        self.transport_server = test_server.SmartTCPServer_for_testing
2787
 
        self.hpss_connections = []
 
2299
        self.transport_server = server.SmartTCPServer_for_testing
2788
2300
        self.hpss_calls = []
2789
2301
        import traceback
2790
2302
        # Skip the current stack down to the caller of
2793
2305
        def capture_hpss_call(params):
2794
2306
            self.hpss_calls.append(
2795
2307
                CapturedCall(params, prefix_length))
2796
 
        def capture_connect(transport):
2797
 
            self.hpss_connections.append(transport)
2798
2308
        client._SmartClient.hooks.install_named_hook(
2799
2309
            'call', capture_hpss_call, None)
2800
 
        _mod_transport.Transport.hooks.install_named_hook(
2801
 
            'post_connect', capture_connect, None)
2802
2310
 
2803
2311
    def reset_smart_call_log(self):
2804
2312
        self.hpss_calls = []
2805
 
        self.hpss_connections = []
2806
2313
 
2807
2314
 
2808
2315
class TestCaseInTempDir(TestCaseWithMemoryTransport):
2827
2334
 
2828
2335
    OVERRIDE_PYTHON = 'python'
2829
2336
 
2830
 
    def setUp(self):
2831
 
        super(TestCaseInTempDir, self).setUp()
2832
 
        # Remove the protection set in isolated_environ, we have a proper
2833
 
        # access to disk resources now.
2834
 
        self.overrideEnv('BZR_LOG', None)
2835
 
 
2836
2337
    def check_file_contents(self, filename, expect):
2837
2338
        self.log("check contents of file %s" % filename)
2838
 
        f = file(filename)
2839
 
        try:
2840
 
            contents = f.read()
2841
 
        finally:
2842
 
            f.close()
 
2339
        contents = file(filename, 'r').read()
2843
2340
        if contents != expect:
2844
2341
            self.log("expected: %r" % expect)
2845
2342
            self.log("actually: %r" % contents)
2868
2365
            if os.path.exists(name):
2869
2366
                name = name_prefix + '_' + str(i)
2870
2367
            else:
2871
 
                # now create test and home directories within this dir
2872
 
                self.test_base_dir = name
2873
 
                self.addCleanup(self.deleteTestDir)
2874
 
                os.mkdir(self.test_base_dir)
 
2368
                os.mkdir(name)
2875
2369
                break
2876
 
        self.permit_dir(self.test_base_dir)
2877
 
        # 'sprouting' and 'init' of a branch both walk up the tree to find
2878
 
        # stacking policy to honour; create a bzr dir with an unshared
2879
 
        # repository (but not a branch - our code would be trying to escape
2880
 
        # then!) to stop them, and permit it to be read.
2881
 
        # control = controldir.ControlDir.create(self.test_base_dir)
2882
 
        # control.create_repository()
 
2370
        # now create test and home directories within this dir
 
2371
        self.test_base_dir = name
2883
2372
        self.test_home_dir = self.test_base_dir + '/home'
2884
2373
        os.mkdir(self.test_home_dir)
2885
2374
        self.test_dir = self.test_base_dir + '/work'
2891
2380
            f.write(self.id())
2892
2381
        finally:
2893
2382
            f.close()
 
2383
        self.addCleanup(self.deleteTestDir)
2894
2384
 
2895
2385
    def deleteTestDir(self):
2896
2386
        os.chdir(TestCaseWithMemoryTransport.TEST_ROOT)
2897
 
        _rmtree_temp_dir(self.test_base_dir, test_id=self.id())
 
2387
        _rmtree_temp_dir(self.test_base_dir)
2898
2388
 
2899
2389
    def build_tree(self, shape, line_endings='binary', transport=None):
2900
2390
        """Build a test tree according to a pattern.
2919
2409
                "a list or a tuple. Got %r instead" % (shape,))
2920
2410
        # It's OK to just create them using forward slashes on windows.
2921
2411
        if transport is None or transport.is_readonly():
2922
 
            transport = _mod_transport.get_transport_from_path(".")
 
2412
            transport = get_transport(".")
2923
2413
        for name in shape:
2924
2414
            self.assertIsInstance(name, basestring)
2925
2415
            if name[-1] == '/':
2935
2425
                content = "contents of %s%s" % (name.encode('utf-8'), end)
2936
2426
                transport.put_bytes_non_atomic(urlutils.escape(name), content)
2937
2427
 
2938
 
    build_tree_contents = staticmethod(treeshape.build_tree_contents)
 
2428
    def build_tree_contents(self, shape):
 
2429
        build_tree_contents(shape)
2939
2430
 
2940
2431
    def assertInWorkingTree(self, path, root_path='.', tree=None):
2941
2432
        """Assert whether path or paths are in the WorkingTree"""
2973
2464
    readwrite one must both define get_url() as resolving to os.getcwd().
2974
2465
    """
2975
2466
 
2976
 
    def setUp(self):
2977
 
        super(TestCaseWithTransport, self).setUp()
2978
 
        self.__vfs_server = None
2979
 
 
2980
2467
    def get_vfs_only_server(self):
2981
2468
        """See TestCaseWithMemoryTransport.
2982
2469
 
2985
2472
        """
2986
2473
        if self.__vfs_server is None:
2987
2474
            self.__vfs_server = self.vfs_transport_factory()
2988
 
            self.start_server(self.__vfs_server)
 
2475
            self.__vfs_server.setUp()
 
2476
            self.addCleanup(self.__vfs_server.tearDown)
2989
2477
        return self.__vfs_server
2990
2478
 
2991
2479
    def make_branch_and_tree(self, relpath, format=None):
2998
2486
        repository will also be accessed locally. Otherwise a lightweight
2999
2487
        checkout is created and returned.
3000
2488
 
3001
 
        We do this because we can't physically create a tree in the local
3002
 
        path, with a branch reference to the transport_factory url, and
3003
 
        a branch + repository in the vfs_transport, unless the vfs_transport
3004
 
        namespace is distinct from the local disk - the two branch objects
3005
 
        would collide. While we could construct a tree with its branch object
3006
 
        pointing at the transport_factory transport in memory, reopening it
3007
 
        would behaving unexpectedly, and has in the past caused testing bugs
3008
 
        when we tried to do it that way.
3009
 
 
3010
2489
        :param format: The BzrDirFormat.
3011
2490
        :returns: the WorkingTree.
3012
2491
        """
3014
2493
        # this obviously requires a format that supports branch references
3015
2494
        # so check for that by checking bzrdir.BzrDirFormat.get_default_format()
3016
2495
        # RBC 20060208
3017
 
        format = self.resolve_format(format=format)
3018
 
        if not format.supports_workingtrees:
3019
 
            b = self.make_branch(relpath+'.branch', format=format)
3020
 
            return b.create_checkout(relpath, lightweight=True)
3021
2496
        b = self.make_branch(relpath, format=format)
3022
2497
        try:
3023
2498
            return b.bzrdir.create_workingtree()
3025
2500
            # We can only make working trees locally at the moment.  If the
3026
2501
            # transport can't support them, then we keep the non-disk-backed
3027
2502
            # branch and create a local checkout.
3028
 
            if self.vfs_transport_factory is test_server.LocalURLServer:
 
2503
            if self.vfs_transport_factory is LocalURLServer:
3029
2504
                # the branch is colocated on disk, we cannot create a checkout.
3030
2505
                # hopefully callers will expect this.
3031
 
                local_controldir = controldir.ControlDir.open(
3032
 
                    self.get_vfs_only_url(relpath))
 
2506
                local_controldir= bzrdir.BzrDir.open(self.get_vfs_only_url(relpath))
3033
2507
                wt = local_controldir.create_workingtree()
3034
2508
                if wt.branch._format != b._format:
3035
2509
                    wt._branch = b
3065
2539
        self.assertFalse(differences.has_changed(),
3066
2540
            "Trees %r and %r are different: %r" % (left, right, differences))
3067
2541
 
3068
 
    def disable_missing_extensions_warning(self):
3069
 
        """Some tests expect a precise stderr content.
3070
 
 
3071
 
        There is no point in forcing them to duplicate the extension related
3072
 
        warning.
3073
 
        """
3074
 
        config.GlobalStack().set('ignore_missing_extensions', True)
 
2542
    def setUp(self):
 
2543
        super(TestCaseWithTransport, self).setUp()
 
2544
        self.__vfs_server = None
3075
2545
 
3076
2546
 
3077
2547
class ChrootedTestCase(TestCaseWithTransport):
3087
2557
    """
3088
2558
 
3089
2559
    def setUp(self):
3090
 
        from bzrlib.tests import http_server
3091
2560
        super(ChrootedTestCase, self).setUp()
3092
 
        if not self.vfs_transport_factory == memory.MemoryServer:
3093
 
            self.transport_readonly_server = http_server.HttpServer
 
2561
        if not self.vfs_transport_factory == MemoryServer:
 
2562
            self.transport_readonly_server = HttpServer
3094
2563
 
3095
2564
 
3096
2565
def condition_id_re(pattern):
3099
2568
    :param pattern: A regular expression string.
3100
2569
    :return: A callable that returns True if the re matches.
3101
2570
    """
3102
 
    filter_re = re.compile(pattern, 0)
 
2571
    filter_re = osutils.re_compile_checked(pattern, 0,
 
2572
        'test filter')
3103
2573
    def condition(test):
3104
2574
        test_id = test.id()
3105
2575
        return filter_re.search(test_id)
3292
2762
              strict=False,
3293
2763
              runner_class=None,
3294
2764
              suite_decorators=None,
3295
 
              stream=None,
3296
 
              result_decorators=None,
3297
 
              ):
 
2765
              stream=None):
3298
2766
    """Run a test suite for bzr selftest.
3299
2767
 
3300
2768
    :param runner_class: The class of runner to use. Must support the
3315
2783
                            descriptions=0,
3316
2784
                            verbosity=verbosity,
3317
2785
                            bench_history=bench_history,
 
2786
                            list_only=list_only,
3318
2787
                            strict=strict,
3319
 
                            result_decorators=result_decorators,
3320
2788
                            )
3321
2789
    runner.stop_on_failure=stop_on_failure
3322
 
    if isinstance(suite, unittest.TestSuite):
3323
 
        # Empty out _tests list of passed suite and populate new TestSuite
3324
 
        suite._tests[:], suite = [], TestSuite(suite)
3325
2790
    # built in decorator factories:
3326
2791
    decorators = [
3327
2792
        random_order(random_seed, runner),
3340
2805
        decorators.append(CountingDecorator)
3341
2806
    for decorator in decorators:
3342
2807
        suite = decorator(suite)
 
2808
    result = runner.run(suite)
3343
2809
    if list_only:
3344
 
        # Done after test suite decoration to allow randomisation etc
3345
 
        # to take effect, though that is of marginal benefit.
3346
 
        if verbosity >= 2:
3347
 
            stream.write("Listing tests only ...\n")
3348
 
        for t in iter_suite_tests(suite):
3349
 
            stream.write("%s\n" % (t.id()))
3350
2810
        return True
3351
 
    result = runner.run(suite)
 
2811
    result.done()
3352
2812
    if strict:
3353
2813
        return result.wasStrictlySuccessful()
3354
2814
    else:
3360
2820
 
3361
2821
 
3362
2822
def fork_decorator(suite):
3363
 
    if getattr(os, "fork", None) is None:
3364
 
        raise errors.BzrCommandError("platform does not support fork,"
3365
 
            " try --parallel=subprocess instead.")
3366
2823
    concurrency = osutils.local_concurrency()
3367
2824
    if concurrency == 1:
3368
2825
        return suite
3423
2880
    return suite
3424
2881
 
3425
2882
 
3426
 
class TestDecorator(TestUtil.TestSuite):
 
2883
class TestDecorator(TestSuite):
3427
2884
    """A decorator for TestCase/TestSuite objects.
3428
 
 
3429
 
    Contains rather than flattening suite passed on construction
 
2885
    
 
2886
    Usually, subclasses should override __iter__(used when flattening test
 
2887
    suites), which we do to filter, reorder, parallelise and so on, run() and
 
2888
    debug().
3430
2889
    """
3431
2890
 
3432
 
    def __init__(self, suite=None):
3433
 
        super(TestDecorator, self).__init__()
3434
 
        if suite is not None:
3435
 
            self.addTest(suite)
3436
 
 
3437
 
    # Don't need subclass run method with suite emptying
3438
 
    run = unittest.TestSuite.run
 
2891
    def __init__(self, suite):
 
2892
        TestSuite.__init__(self)
 
2893
        self.addTest(suite)
 
2894
 
 
2895
    def countTestCases(self):
 
2896
        cases = 0
 
2897
        for test in self:
 
2898
            cases += test.countTestCases()
 
2899
        return cases
 
2900
 
 
2901
    def debug(self):
 
2902
        for test in self:
 
2903
            test.debug()
 
2904
 
 
2905
    def run(self, result):
 
2906
        # Use iteration on self, not self._tests, to allow subclasses to hook
 
2907
        # into __iter__.
 
2908
        for test in self:
 
2909
            if result.shouldStop:
 
2910
                break
 
2911
            test.run(result)
 
2912
        return result
3439
2913
 
3440
2914
 
3441
2915
class CountingDecorator(TestDecorator):
3452
2926
    """A decorator which excludes test matching an exclude pattern."""
3453
2927
 
3454
2928
    def __init__(self, suite, exclude_pattern):
3455
 
        super(ExcludeDecorator, self).__init__(
3456
 
            exclude_tests_by_re(suite, exclude_pattern))
 
2929
        TestDecorator.__init__(self, suite)
 
2930
        self.exclude_pattern = exclude_pattern
 
2931
        self.excluded = False
 
2932
 
 
2933
    def __iter__(self):
 
2934
        if self.excluded:
 
2935
            return iter(self._tests)
 
2936
        self.excluded = True
 
2937
        suite = exclude_tests_by_re(self, self.exclude_pattern)
 
2938
        del self._tests[:]
 
2939
        self.addTests(suite)
 
2940
        return iter(self._tests)
3457
2941
 
3458
2942
 
3459
2943
class FilterTestsDecorator(TestDecorator):
3460
2944
    """A decorator which filters tests to those matching a pattern."""
3461
2945
 
3462
2946
    def __init__(self, suite, pattern):
3463
 
        super(FilterTestsDecorator, self).__init__(
3464
 
            filter_suite_by_re(suite, pattern))
 
2947
        TestDecorator.__init__(self, suite)
 
2948
        self.pattern = pattern
 
2949
        self.filtered = False
 
2950
 
 
2951
    def __iter__(self):
 
2952
        if self.filtered:
 
2953
            return iter(self._tests)
 
2954
        self.filtered = True
 
2955
        suite = filter_suite_by_re(self, self.pattern)
 
2956
        del self._tests[:]
 
2957
        self.addTests(suite)
 
2958
        return iter(self._tests)
3465
2959
 
3466
2960
 
3467
2961
class RandomDecorator(TestDecorator):
3468
2962
    """A decorator which randomises the order of its tests."""
3469
2963
 
3470
2964
    def __init__(self, suite, random_seed, stream):
3471
 
        random_seed = self.actual_seed(random_seed)
3472
 
        stream.write("Randomizing test order using seed %s\n\n" %
3473
 
            (random_seed,))
 
2965
        TestDecorator.__init__(self, suite)
 
2966
        self.random_seed = random_seed
 
2967
        self.randomised = False
 
2968
        self.stream = stream
 
2969
 
 
2970
    def __iter__(self):
 
2971
        if self.randomised:
 
2972
            return iter(self._tests)
 
2973
        self.randomised = True
 
2974
        self.stream.writeln("Randomizing test order using seed %s\n" %
 
2975
            (self.actual_seed()))
3474
2976
        # Initialise the random number generator.
3475
 
        random.seed(random_seed)
3476
 
        super(RandomDecorator, self).__init__(randomize_suite(suite))
 
2977
        random.seed(self.actual_seed())
 
2978
        suite = randomize_suite(self)
 
2979
        del self._tests[:]
 
2980
        self.addTests(suite)
 
2981
        return iter(self._tests)
3477
2982
 
3478
 
    @staticmethod
3479
 
    def actual_seed(seed):
3480
 
        if seed == "now":
 
2983
    def actual_seed(self):
 
2984
        if self.random_seed == "now":
3481
2985
            # We convert the seed to a long to make it reuseable across
3482
2986
            # invocations (because the user can reenter it).
3483
 
            return long(time.time())
 
2987
            self.random_seed = long(time.time())
3484
2988
        else:
3485
2989
            # Convert the seed to a long if we can
3486
2990
            try:
3487
 
                return long(seed)
3488
 
            except (TypeError, ValueError):
 
2991
                self.random_seed = long(self.random_seed)
 
2992
            except:
3489
2993
                pass
3490
 
        return seed
 
2994
        return self.random_seed
3491
2995
 
3492
2996
 
3493
2997
class TestFirstDecorator(TestDecorator):
3494
2998
    """A decorator which moves named tests to the front."""
3495
2999
 
3496
3000
    def __init__(self, suite, pattern):
3497
 
        super(TestFirstDecorator, self).__init__()
3498
 
        self.addTests(split_suite_by_re(suite, pattern))
 
3001
        TestDecorator.__init__(self, suite)
 
3002
        self.pattern = pattern
 
3003
        self.filtered = False
 
3004
 
 
3005
    def __iter__(self):
 
3006
        if self.filtered:
 
3007
            return iter(self._tests)
 
3008
        self.filtered = True
 
3009
        suites = split_suite_by_re(self, self.pattern)
 
3010
        del self._tests[:]
 
3011
        self.addTests(suites)
 
3012
        return iter(self._tests)
3499
3013
 
3500
3014
 
3501
3015
def partition_tests(suite, count):
3502
3016
    """Partition suite into count lists of tests."""
3503
 
    # This just assigns tests in a round-robin fashion.  On one hand this
3504
 
    # splits up blocks of related tests that might run faster if they shared
3505
 
    # resources, but on the other it avoids assigning blocks of slow tests to
3506
 
    # just one partition.  So the slowest partition shouldn't be much slower
3507
 
    # than the fastest.
3508
 
    partitions = [list() for i in range(count)]
3509
 
    tests = iter_suite_tests(suite)
3510
 
    for partition, test in itertools.izip(itertools.cycle(partitions), tests):
3511
 
        partition.append(test)
3512
 
    return partitions
3513
 
 
3514
 
 
3515
 
def workaround_zealous_crypto_random():
3516
 
    """Crypto.Random want to help us being secure, but we don't care here.
3517
 
 
3518
 
    This workaround some test failure related to the sftp server. Once paramiko
3519
 
    stop using the controversial API in Crypto.Random, we may get rid of it.
3520
 
    """
3521
 
    try:
3522
 
        from Crypto.Random import atfork
3523
 
        atfork()
3524
 
    except ImportError:
3525
 
        pass
 
3017
    result = []
 
3018
    tests = list(iter_suite_tests(suite))
 
3019
    tests_per_process = int(math.ceil(float(len(tests)) / count))
 
3020
    for block in range(count):
 
3021
        low_test = block * tests_per_process
 
3022
        high_test = low_test + tests_per_process
 
3023
        process_tests = tests[low_test:high_test]
 
3024
        result.append(process_tests)
 
3025
    return result
3526
3026
 
3527
3027
 
3528
3028
def fork_for_tests(suite):
3533
3033
    """
3534
3034
    concurrency = osutils.local_concurrency()
3535
3035
    result = []
3536
 
    from subunit import ProtocolTestCase
3537
 
    from subunit.test_results import AutoTimingTestResultDecorator
 
3036
    from subunit import TestProtocolClient, ProtocolTestCase
 
3037
    try:
 
3038
        from subunit.test_results import AutoTimingTestResultDecorator
 
3039
    except ImportError:
 
3040
        AutoTimingTestResultDecorator = lambda x:x
3538
3041
    class TestInOtherProcess(ProtocolTestCase):
3539
3042
        # Should be in subunit, I think. RBC.
3540
3043
        def __init__(self, stream, pid):
3545
3048
            try:
3546
3049
                ProtocolTestCase.run(self, result)
3547
3050
            finally:
3548
 
                pid, status = os.waitpid(self.pid, 0)
3549
 
            # GZ 2011-10-18: If status is nonzero, should report to the result
3550
 
            #                that something went wrong.
 
3051
                os.waitpid(self.pid, os.WNOHANG)
3551
3052
 
3552
3053
    test_blocks = partition_tests(suite, concurrency)
3553
 
    # Clear the tests from the original suite so it doesn't keep them alive
3554
 
    suite._tests[:] = []
3555
3054
    for process_tests in test_blocks:
3556
 
        process_suite = TestUtil.TestSuite(process_tests)
3557
 
        # Also clear each split list so new suite has only reference
3558
 
        process_tests[:] = []
 
3055
        process_suite = TestSuite()
 
3056
        process_suite.addTests(process_tests)
3559
3057
        c2pread, c2pwrite = os.pipe()
3560
3058
        pid = os.fork()
3561
3059
        if pid == 0:
3562
3060
            try:
3563
 
                stream = os.fdopen(c2pwrite, 'wb', 1)
3564
 
                workaround_zealous_crypto_random()
3565
3061
                os.close(c2pread)
3566
3062
                # Leave stderr and stdout open so we can see test noise
3567
3063
                # Close stdin so that the child goes away if it decides to
3568
3064
                # read from stdin (otherwise its a roulette to see what
3569
3065
                # child actually gets keystrokes for pdb etc).
3570
3066
                sys.stdin.close()
 
3067
                sys.stdin = None
 
3068
                stream = os.fdopen(c2pwrite, 'wb', 1)
3571
3069
                subunit_result = AutoTimingTestResultDecorator(
3572
 
                    SubUnitBzrProtocolClient(stream))
 
3070
                    TestProtocolClient(stream))
3573
3071
                process_suite.run(subunit_result)
3574
 
            except:
3575
 
                # Try and report traceback on stream, but exit with error even
3576
 
                # if stream couldn't be created or something else goes wrong.
3577
 
                # The traceback is formatted to a string and written in one go
3578
 
                # to avoid interleaving lines from multiple failing children.
3579
 
                try:
3580
 
                    stream.write(traceback.format_exc())
3581
 
                finally:
3582
 
                    os._exit(1)
3583
 
            os._exit(0)
 
3072
            finally:
 
3073
                os._exit(0)
3584
3074
        else:
3585
3075
            os.close(c2pwrite)
3586
3076
            stream = os.fdopen(c2pread, 'rb', 1)
3619
3109
        if not os.path.isfile(bzr_path):
3620
3110
            # We are probably installed. Assume sys.argv is the right file
3621
3111
            bzr_path = sys.argv[0]
3622
 
        bzr_path = [bzr_path]
3623
 
        if sys.platform == "win32":
3624
 
            # if we're on windows, we can't execute the bzr script directly
3625
 
            bzr_path = [sys.executable] + bzr_path
3626
3112
        fd, test_list_file_name = tempfile.mkstemp()
3627
3113
        test_list_file = os.fdopen(fd, 'wb', 1)
3628
3114
        for test in process_tests:
3629
3115
            test_list_file.write(test.id() + '\n')
3630
3116
        test_list_file.close()
3631
3117
        try:
3632
 
            argv = bzr_path + ['selftest', '--load-list', test_list_file_name,
 
3118
            argv = [bzr_path, 'selftest', '--load-list', test_list_file_name,
3633
3119
                '--subunit']
3634
3120
            if '--no-plugins' in sys.argv:
3635
3121
                argv.append('--no-plugins')
3636
 
            # stderr=subprocess.STDOUT would be ideal, but until we prevent
3637
 
            # noise on stderr it can interrupt the subunit protocol.
3638
 
            process = subprocess.Popen(argv, stdin=subprocess.PIPE,
3639
 
                                      stdout=subprocess.PIPE,
3640
 
                                      stderr=subprocess.PIPE,
3641
 
                                      bufsize=1)
 
3122
            # stderr=STDOUT would be ideal, but until we prevent noise on
 
3123
            # stderr it can interrupt the subunit protocol.
 
3124
            process = Popen(argv, stdin=PIPE, stdout=PIPE, stderr=PIPE,
 
3125
                bufsize=1)
3642
3126
            test = TestInSubprocess(process, test_list_file_name)
3643
3127
            result.append(test)
3644
3128
        except:
3647
3131
    return result
3648
3132
 
3649
3133
 
3650
 
class ProfileResult(testtools.ExtendedToOriginalDecorator):
3651
 
    """Generate profiling data for all activity between start and success.
3652
 
    
3653
 
    The profile data is appended to the test's _benchcalls attribute and can
3654
 
    be accessed by the forwarded-to TestResult.
 
3134
class BZRTransformingResult(unittest.TestResult):
3655
3135
 
3656
 
    While it might be cleaner do accumulate this in stopTest, addSuccess is
3657
 
    where our existing output support for lsprof is, and this class aims to
3658
 
    fit in with that: while it could be moved it's not necessary to accomplish
3659
 
    test profiling, nor would it be dramatically cleaner.
3660
 
    """
 
3136
    def __init__(self, target):
 
3137
        unittest.TestResult.__init__(self)
 
3138
        self.result = target
3661
3139
 
3662
3140
    def startTest(self, test):
3663
 
        self.profiler = bzrlib.lsprof.BzrProfiler()
3664
 
        # Prevent deadlocks in tests that use lsprof: those tests will
3665
 
        # unavoidably fail.
3666
 
        bzrlib.lsprof.BzrProfiler.profiler_block = 0
3667
 
        self.profiler.start()
3668
 
        testtools.ExtendedToOriginalDecorator.startTest(self, test)
 
3141
        self.result.startTest(test)
 
3142
 
 
3143
    def stopTest(self, test):
 
3144
        self.result.stopTest(test)
 
3145
 
 
3146
    def addError(self, test, err):
 
3147
        feature = self._error_looks_like('UnavailableFeature: ', err)
 
3148
        if feature is not None:
 
3149
            self.result.addNotSupported(test, feature)
 
3150
        else:
 
3151
            self.result.addError(test, err)
 
3152
 
 
3153
    def addFailure(self, test, err):
 
3154
        known = self._error_looks_like('KnownFailure: ', err)
 
3155
        if known is not None:
 
3156
            self.result._addKnownFailure(test, [KnownFailure,
 
3157
                                                KnownFailure(known), None])
 
3158
        else:
 
3159
            self.result.addFailure(test, err)
 
3160
 
 
3161
    def addSkip(self, test, reason):
 
3162
        self.result.addSkip(test, reason)
3669
3163
 
3670
3164
    def addSuccess(self, test):
3671
 
        stats = self.profiler.stop()
3672
 
        try:
3673
 
            calls = test._benchcalls
3674
 
        except AttributeError:
3675
 
            test._benchcalls = []
3676
 
            calls = test._benchcalls
3677
 
        calls.append(((test.id(), "", ""), stats))
3678
 
        testtools.ExtendedToOriginalDecorator.addSuccess(self, test)
 
3165
        self.result.addSuccess(test)
3679
3166
 
3680
 
    def stopTest(self, test):
3681
 
        testtools.ExtendedToOriginalDecorator.stopTest(self, test)
3682
 
        self.profiler = None
 
3167
    def _error_looks_like(self, prefix, err):
 
3168
        """Deserialize exception and returns the stringify value."""
 
3169
        import subunit
 
3170
        value = None
 
3171
        typ, exc, _ = err
 
3172
        if isinstance(exc, subunit.RemoteException):
 
3173
            # stringify the exception gives access to the remote traceback
 
3174
            # We search the last line for 'prefix'
 
3175
            lines = str(exc).split('\n')
 
3176
            while lines and not lines[-1]:
 
3177
                lines.pop(-1)
 
3178
            if lines:
 
3179
                if lines[-1].startswith(prefix):
 
3180
                    value = lines[-1][len(prefix):]
 
3181
        return value
3683
3182
 
3684
3183
 
3685
3184
# Controlled by "bzr selftest -E=..." option
3690
3189
#                           rather than failing tests. And no longer raise
3691
3190
#                           LockContention when fctnl locks are not being used
3692
3191
#                           with proper exclusion rules.
3693
 
#   -Ethreads               Will display thread ident at creation/join time to
3694
 
#                           help track thread leaks
3695
 
#   -Euncollected_cases     Display the identity of any test cases that weren't
3696
 
#                           deallocated after being completed.
3697
 
#   -Econfig_stats          Will collect statistics using addDetail
3698
3192
selftest_debug_flags = set()
3699
3193
 
3700
3194
 
3714
3208
             runner_class=None,
3715
3209
             suite_decorators=None,
3716
3210
             stream=None,
3717
 
             lsprof_tests=False,
3718
3211
             ):
3719
3212
    """Run the whole test suite under the enhanced runner"""
3720
3213
    # XXX: Very ugly way to do this...
3749
3242
        if starting_with:
3750
3243
            # But always filter as requested.
3751
3244
            suite = filter_suite_by_id_startswith(suite, starting_with)
3752
 
        result_decorators = []
3753
 
        if lsprof_tests:
3754
 
            result_decorators.append(ProfileResult)
3755
3245
        return run_suite(suite, 'testbzr', verbose=verbose, pattern=pattern,
3756
3246
                     stop_on_failure=stop_on_failure,
3757
3247
                     transport=transport,
3765
3255
                     runner_class=runner_class,
3766
3256
                     suite_decorators=suite_decorators,
3767
3257
                     stream=stream,
3768
 
                     result_decorators=result_decorators,
3769
3258
                     )
3770
3259
    finally:
3771
3260
        default_transport = old_transport
3804
3293
 
3805
3294
    :return: (absents, duplicates) absents is a list containing the test found
3806
3295
        in id_list but not in test_suite, duplicates is a list containing the
3807
 
        tests found multiple times in test_suite.
 
3296
        test found multiple times in test_suite.
3808
3297
 
3809
3298
    When using a prefined test id list, it may occurs that some tests do not
3810
3299
    exist anymore or that some tests use the same id. This function warns the
3894
3383
                key, obj, help=help, info=info, override_existing=False)
3895
3384
        except KeyError:
3896
3385
            actual = self.get(key)
3897
 
            trace.note(
3898
 
                'Test prefix alias %s is already used for %s, ignoring %s'
3899
 
                % (key, actual, obj))
 
3386
            note('Test prefix alias %s is already used for %s, ignoring %s'
 
3387
                 % (key, actual, obj))
3900
3388
 
3901
3389
    def resolve_alias(self, id_start):
3902
3390
        """Replace the alias by the prefix in the given string.
3920
3408
# appear prefixed ('bzrlib.' is "replaced" by 'bzrlib.').
3921
3409
test_prefix_alias_registry.register('bzrlib', 'bzrlib')
3922
3410
 
3923
 
# Obvious highest levels prefixes, feel free to add your own via a plugin
 
3411
# Obvious higest levels prefixes, feel free to add your own via a plugin
3924
3412
test_prefix_alias_registry.register('bd', 'bzrlib.doc')
3925
3413
test_prefix_alias_registry.register('bu', 'bzrlib.utils')
3926
3414
test_prefix_alias_registry.register('bt', 'bzrlib.tests')
3928
3416
test_prefix_alias_registry.register('bp', 'bzrlib.plugins')
3929
3417
 
3930
3418
 
3931
 
def _test_suite_testmod_names():
3932
 
    """Return the standard list of test module names to test."""
3933
 
    return [
3934
 
        'bzrlib.doc',
3935
 
        'bzrlib.tests.blackbox',
3936
 
        'bzrlib.tests.commands',
3937
 
        'bzrlib.tests.per_branch',
3938
 
        'bzrlib.tests.per_bzrdir',
3939
 
        'bzrlib.tests.per_controldir',
3940
 
        'bzrlib.tests.per_controldir_colo',
3941
 
        'bzrlib.tests.per_foreign_vcs',
3942
 
        'bzrlib.tests.per_interrepository',
3943
 
        'bzrlib.tests.per_intertree',
3944
 
        'bzrlib.tests.per_inventory',
3945
 
        'bzrlib.tests.per_interbranch',
3946
 
        'bzrlib.tests.per_lock',
3947
 
        'bzrlib.tests.per_merger',
3948
 
        'bzrlib.tests.per_transport',
3949
 
        'bzrlib.tests.per_tree',
3950
 
        'bzrlib.tests.per_pack_repository',
3951
 
        'bzrlib.tests.per_repository',
3952
 
        'bzrlib.tests.per_repository_chk',
3953
 
        'bzrlib.tests.per_repository_reference',
3954
 
        'bzrlib.tests.per_repository_vf',
3955
 
        'bzrlib.tests.per_uifactory',
3956
 
        'bzrlib.tests.per_versionedfile',
3957
 
        'bzrlib.tests.per_workingtree',
3958
 
        'bzrlib.tests.test__annotator',
3959
 
        'bzrlib.tests.test__bencode',
3960
 
        'bzrlib.tests.test__btree_serializer',
3961
 
        'bzrlib.tests.test__chk_map',
3962
 
        'bzrlib.tests.test__dirstate_helpers',
3963
 
        'bzrlib.tests.test__groupcompress',
3964
 
        'bzrlib.tests.test__known_graph',
3965
 
        'bzrlib.tests.test__rio',
3966
 
        'bzrlib.tests.test__simple_set',
3967
 
        'bzrlib.tests.test__static_tuple',
3968
 
        'bzrlib.tests.test__walkdirs_win32',
3969
 
        'bzrlib.tests.test_ancestry',
3970
 
        'bzrlib.tests.test_annotate',
3971
 
        'bzrlib.tests.test_api',
3972
 
        'bzrlib.tests.test_atomicfile',
3973
 
        'bzrlib.tests.test_bad_files',
3974
 
        'bzrlib.tests.test_bisect_multi',
3975
 
        'bzrlib.tests.test_branch',
3976
 
        'bzrlib.tests.test_branchbuilder',
3977
 
        'bzrlib.tests.test_btree_index',
3978
 
        'bzrlib.tests.test_bugtracker',
3979
 
        'bzrlib.tests.test_bundle',
3980
 
        'bzrlib.tests.test_bzrdir',
3981
 
        'bzrlib.tests.test__chunks_to_lines',
3982
 
        'bzrlib.tests.test_cache_utf8',
3983
 
        'bzrlib.tests.test_chk_map',
3984
 
        'bzrlib.tests.test_chk_serializer',
3985
 
        'bzrlib.tests.test_chunk_writer',
3986
 
        'bzrlib.tests.test_clean_tree',
3987
 
        'bzrlib.tests.test_cleanup',
3988
 
        'bzrlib.tests.test_cmdline',
3989
 
        'bzrlib.tests.test_commands',
3990
 
        'bzrlib.tests.test_commit',
3991
 
        'bzrlib.tests.test_commit_merge',
3992
 
        'bzrlib.tests.test_config',
3993
 
        'bzrlib.tests.test_conflicts',
3994
 
        'bzrlib.tests.test_controldir',
3995
 
        'bzrlib.tests.test_counted_lock',
3996
 
        'bzrlib.tests.test_crash',
3997
 
        'bzrlib.tests.test_decorators',
3998
 
        'bzrlib.tests.test_delta',
3999
 
        'bzrlib.tests.test_debug',
4000
 
        'bzrlib.tests.test_diff',
4001
 
        'bzrlib.tests.test_directory_service',
4002
 
        'bzrlib.tests.test_dirstate',
4003
 
        'bzrlib.tests.test_email_message',
4004
 
        'bzrlib.tests.test_eol_filters',
4005
 
        'bzrlib.tests.test_errors',
4006
 
        'bzrlib.tests.test_estimate_compressed_size',
4007
 
        'bzrlib.tests.test_export',
4008
 
        'bzrlib.tests.test_export_pot',
4009
 
        'bzrlib.tests.test_extract',
4010
 
        'bzrlib.tests.test_features',
4011
 
        'bzrlib.tests.test_fetch',
4012
 
        'bzrlib.tests.test_fixtures',
4013
 
        'bzrlib.tests.test_fifo_cache',
4014
 
        'bzrlib.tests.test_filters',
4015
 
        'bzrlib.tests.test_filter_tree',
4016
 
        'bzrlib.tests.test_ftp_transport',
4017
 
        'bzrlib.tests.test_foreign',
4018
 
        'bzrlib.tests.test_generate_docs',
4019
 
        'bzrlib.tests.test_generate_ids',
4020
 
        'bzrlib.tests.test_globbing',
4021
 
        'bzrlib.tests.test_gpg',
4022
 
        'bzrlib.tests.test_graph',
4023
 
        'bzrlib.tests.test_groupcompress',
4024
 
        'bzrlib.tests.test_hashcache',
4025
 
        'bzrlib.tests.test_help',
4026
 
        'bzrlib.tests.test_hooks',
4027
 
        'bzrlib.tests.test_http',
4028
 
        'bzrlib.tests.test_http_response',
4029
 
        'bzrlib.tests.test_https_ca_bundle',
4030
 
        'bzrlib.tests.test_https_urllib',
4031
 
        'bzrlib.tests.test_i18n',
4032
 
        'bzrlib.tests.test_identitymap',
4033
 
        'bzrlib.tests.test_ignores',
4034
 
        'bzrlib.tests.test_index',
4035
 
        'bzrlib.tests.test_import_tariff',
4036
 
        'bzrlib.tests.test_info',
4037
 
        'bzrlib.tests.test_inv',
4038
 
        'bzrlib.tests.test_inventory_delta',
4039
 
        'bzrlib.tests.test_knit',
4040
 
        'bzrlib.tests.test_lazy_import',
4041
 
        'bzrlib.tests.test_lazy_regex',
4042
 
        'bzrlib.tests.test_library_state',
4043
 
        'bzrlib.tests.test_lock',
4044
 
        'bzrlib.tests.test_lockable_files',
4045
 
        'bzrlib.tests.test_lockdir',
4046
 
        'bzrlib.tests.test_log',
4047
 
        'bzrlib.tests.test_lru_cache',
4048
 
        'bzrlib.tests.test_lsprof',
4049
 
        'bzrlib.tests.test_mail_client',
4050
 
        'bzrlib.tests.test_matchers',
4051
 
        'bzrlib.tests.test_memorytree',
4052
 
        'bzrlib.tests.test_merge',
4053
 
        'bzrlib.tests.test_merge3',
4054
 
        'bzrlib.tests.test_merge_core',
4055
 
        'bzrlib.tests.test_merge_directive',
4056
 
        'bzrlib.tests.test_mergetools',
4057
 
        'bzrlib.tests.test_missing',
4058
 
        'bzrlib.tests.test_msgeditor',
4059
 
        'bzrlib.tests.test_multiparent',
4060
 
        'bzrlib.tests.test_mutabletree',
4061
 
        'bzrlib.tests.test_nonascii',
4062
 
        'bzrlib.tests.test_options',
4063
 
        'bzrlib.tests.test_osutils',
4064
 
        'bzrlib.tests.test_osutils_encodings',
4065
 
        'bzrlib.tests.test_pack',
4066
 
        'bzrlib.tests.test_patch',
4067
 
        'bzrlib.tests.test_patches',
4068
 
        'bzrlib.tests.test_permissions',
4069
 
        'bzrlib.tests.test_plugins',
4070
 
        'bzrlib.tests.test_progress',
4071
 
        'bzrlib.tests.test_pyutils',
4072
 
        'bzrlib.tests.test_read_bundle',
4073
 
        'bzrlib.tests.test_reconcile',
4074
 
        'bzrlib.tests.test_reconfigure',
4075
 
        'bzrlib.tests.test_registry',
4076
 
        'bzrlib.tests.test_remote',
4077
 
        'bzrlib.tests.test_rename_map',
4078
 
        'bzrlib.tests.test_repository',
4079
 
        'bzrlib.tests.test_revert',
4080
 
        'bzrlib.tests.test_revision',
4081
 
        'bzrlib.tests.test_revisionspec',
4082
 
        'bzrlib.tests.test_revisiontree',
4083
 
        'bzrlib.tests.test_rio',
4084
 
        'bzrlib.tests.test_rules',
4085
 
        'bzrlib.tests.test_url_policy_open',
4086
 
        'bzrlib.tests.test_sampler',
4087
 
        'bzrlib.tests.test_scenarios',
4088
 
        'bzrlib.tests.test_script',
4089
 
        'bzrlib.tests.test_selftest',
4090
 
        'bzrlib.tests.test_serializer',
4091
 
        'bzrlib.tests.test_setup',
4092
 
        'bzrlib.tests.test_sftp_transport',
4093
 
        'bzrlib.tests.test_shelf',
4094
 
        'bzrlib.tests.test_shelf_ui',
4095
 
        'bzrlib.tests.test_smart',
4096
 
        'bzrlib.tests.test_smart_add',
4097
 
        'bzrlib.tests.test_smart_request',
4098
 
        'bzrlib.tests.test_smart_signals',
4099
 
        'bzrlib.tests.test_smart_transport',
4100
 
        'bzrlib.tests.test_smtp_connection',
4101
 
        'bzrlib.tests.test_source',
4102
 
        'bzrlib.tests.test_ssh_transport',
4103
 
        'bzrlib.tests.test_status',
4104
 
        'bzrlib.tests.test_store',
4105
 
        'bzrlib.tests.test_strace',
4106
 
        'bzrlib.tests.test_subsume',
4107
 
        'bzrlib.tests.test_switch',
4108
 
        'bzrlib.tests.test_symbol_versioning',
4109
 
        'bzrlib.tests.test_tag',
4110
 
        'bzrlib.tests.test_test_server',
4111
 
        'bzrlib.tests.test_testament',
4112
 
        'bzrlib.tests.test_textfile',
4113
 
        'bzrlib.tests.test_textmerge',
4114
 
        'bzrlib.tests.test_cethread',
4115
 
        'bzrlib.tests.test_timestamp',
4116
 
        'bzrlib.tests.test_trace',
4117
 
        'bzrlib.tests.test_transactions',
4118
 
        'bzrlib.tests.test_transform',
4119
 
        'bzrlib.tests.test_transport',
4120
 
        'bzrlib.tests.test_transport_log',
4121
 
        'bzrlib.tests.test_tree',
4122
 
        'bzrlib.tests.test_treebuilder',
4123
 
        'bzrlib.tests.test_treeshape',
4124
 
        'bzrlib.tests.test_tsort',
4125
 
        'bzrlib.tests.test_tuned_gzip',
4126
 
        'bzrlib.tests.test_ui',
4127
 
        'bzrlib.tests.test_uncommit',
4128
 
        'bzrlib.tests.test_upgrade',
4129
 
        'bzrlib.tests.test_upgrade_stacked',
4130
 
        'bzrlib.tests.test_urlutils',
4131
 
        'bzrlib.tests.test_utextwrap',
4132
 
        'bzrlib.tests.test_version',
4133
 
        'bzrlib.tests.test_version_info',
4134
 
        'bzrlib.tests.test_versionedfile',
4135
 
        'bzrlib.tests.test_vf_search',
4136
 
        'bzrlib.tests.test_weave',
4137
 
        'bzrlib.tests.test_whitebox',
4138
 
        'bzrlib.tests.test_win32utils',
4139
 
        'bzrlib.tests.test_workingtree',
4140
 
        'bzrlib.tests.test_workingtree_4',
4141
 
        'bzrlib.tests.test_wsgi',
4142
 
        'bzrlib.tests.test_xml',
4143
 
        ]
4144
 
 
4145
 
 
4146
 
def _test_suite_modules_to_doctest():
4147
 
    """Return the list of modules to doctest."""
4148
 
    if __doc__ is None:
4149
 
        # GZ 2009-03-31: No docstrings with -OO so there's nothing to doctest
4150
 
        return []
4151
 
    return [
4152
 
        'bzrlib',
4153
 
        'bzrlib.branchbuilder',
4154
 
        'bzrlib.decorators',
4155
 
        'bzrlib.inventory',
4156
 
        'bzrlib.iterablefile',
4157
 
        'bzrlib.lockdir',
4158
 
        'bzrlib.merge3',
4159
 
        'bzrlib.option',
4160
 
        'bzrlib.pyutils',
4161
 
        'bzrlib.symbol_versioning',
4162
 
        'bzrlib.tests',
4163
 
        'bzrlib.tests.fixtures',
4164
 
        'bzrlib.timestamp',
4165
 
        'bzrlib.transport.http',
4166
 
        'bzrlib.version_info_formats.format_custom',
4167
 
        ]
4168
 
 
4169
 
 
4170
3419
def test_suite(keep_only=None, starting_with=None):
4171
3420
    """Build and return TestSuite for the whole of bzrlib.
4172
3421
 
4178
3427
    This function can be replaced if you need to change the default test
4179
3428
    suite on a global basis, but it is not encouraged.
4180
3429
    """
 
3430
    testmod_names = [
 
3431
                   'bzrlib.doc',
 
3432
                   'bzrlib.tests.blackbox',
 
3433
                   'bzrlib.tests.commands',
 
3434
                   'bzrlib.tests.per_branch',
 
3435
                   'bzrlib.tests.per_bzrdir',
 
3436
                   'bzrlib.tests.per_interrepository',
 
3437
                   'bzrlib.tests.per_intertree',
 
3438
                   'bzrlib.tests.per_inventory',
 
3439
                   'bzrlib.tests.per_interbranch',
 
3440
                   'bzrlib.tests.per_lock',
 
3441
                   'bzrlib.tests.per_transport',
 
3442
                   'bzrlib.tests.per_tree',
 
3443
                   'bzrlib.tests.per_pack_repository',
 
3444
                   'bzrlib.tests.per_repository',
 
3445
                   'bzrlib.tests.per_repository_chk',
 
3446
                   'bzrlib.tests.per_repository_reference',
 
3447
                   'bzrlib.tests.per_versionedfile',
 
3448
                   'bzrlib.tests.per_workingtree',
 
3449
                   'bzrlib.tests.test__annotator',
 
3450
                   'bzrlib.tests.test__chk_map',
 
3451
                   'bzrlib.tests.test__dirstate_helpers',
 
3452
                   'bzrlib.tests.test__groupcompress',
 
3453
                   'bzrlib.tests.test__known_graph',
 
3454
                   'bzrlib.tests.test__rio',
 
3455
                   'bzrlib.tests.test__walkdirs_win32',
 
3456
                   'bzrlib.tests.test_ancestry',
 
3457
                   'bzrlib.tests.test_annotate',
 
3458
                   'bzrlib.tests.test_api',
 
3459
                   'bzrlib.tests.test_atomicfile',
 
3460
                   'bzrlib.tests.test_bad_files',
 
3461
                   'bzrlib.tests.test_bencode',
 
3462
                   'bzrlib.tests.test_bisect_multi',
 
3463
                   'bzrlib.tests.test_branch',
 
3464
                   'bzrlib.tests.test_branchbuilder',
 
3465
                   'bzrlib.tests.test_btree_index',
 
3466
                   'bzrlib.tests.test_bugtracker',
 
3467
                   'bzrlib.tests.test_bundle',
 
3468
                   'bzrlib.tests.test_bzrdir',
 
3469
                   'bzrlib.tests.test__chunks_to_lines',
 
3470
                   'bzrlib.tests.test_cache_utf8',
 
3471
                   'bzrlib.tests.test_chk_map',
 
3472
                   'bzrlib.tests.test_chk_serializer',
 
3473
                   'bzrlib.tests.test_chunk_writer',
 
3474
                   'bzrlib.tests.test_clean_tree',
 
3475
                   'bzrlib.tests.test_commands',
 
3476
                   'bzrlib.tests.test_commit',
 
3477
                   'bzrlib.tests.test_commit_merge',
 
3478
                   'bzrlib.tests.test_config',
 
3479
                   'bzrlib.tests.test_conflicts',
 
3480
                   'bzrlib.tests.test_counted_lock',
 
3481
                   'bzrlib.tests.test_crash',
 
3482
                   'bzrlib.tests.test_decorators',
 
3483
                   'bzrlib.tests.test_delta',
 
3484
                   'bzrlib.tests.test_debug',
 
3485
                   'bzrlib.tests.test_deprecated_graph',
 
3486
                   'bzrlib.tests.test_diff',
 
3487
                   'bzrlib.tests.test_directory_service',
 
3488
                   'bzrlib.tests.test_dirstate',
 
3489
                   'bzrlib.tests.test_email_message',
 
3490
                   'bzrlib.tests.test_eol_filters',
 
3491
                   'bzrlib.tests.test_errors',
 
3492
                   'bzrlib.tests.test_export',
 
3493
                   'bzrlib.tests.test_extract',
 
3494
                   'bzrlib.tests.test_fetch',
 
3495
                   'bzrlib.tests.test_fifo_cache',
 
3496
                   'bzrlib.tests.test_filters',
 
3497
                   'bzrlib.tests.test_ftp_transport',
 
3498
                   'bzrlib.tests.test_foreign',
 
3499
                   'bzrlib.tests.test_generate_docs',
 
3500
                   'bzrlib.tests.test_generate_ids',
 
3501
                   'bzrlib.tests.test_globbing',
 
3502
                   'bzrlib.tests.test_gpg',
 
3503
                   'bzrlib.tests.test_graph',
 
3504
                   'bzrlib.tests.test_groupcompress',
 
3505
                   'bzrlib.tests.test_hashcache',
 
3506
                   'bzrlib.tests.test_help',
 
3507
                   'bzrlib.tests.test_hooks',
 
3508
                   'bzrlib.tests.test_http',
 
3509
                   'bzrlib.tests.test_http_response',
 
3510
                   'bzrlib.tests.test_https_ca_bundle',
 
3511
                   'bzrlib.tests.test_identitymap',
 
3512
                   'bzrlib.tests.test_ignores',
 
3513
                   'bzrlib.tests.test_index',
 
3514
                   'bzrlib.tests.test_info',
 
3515
                   'bzrlib.tests.test_inv',
 
3516
                   'bzrlib.tests.test_inventory_delta',
 
3517
                   'bzrlib.tests.test_knit',
 
3518
                   'bzrlib.tests.test_lazy_import',
 
3519
                   'bzrlib.tests.test_lazy_regex',
 
3520
                   'bzrlib.tests.test_lock',
 
3521
                   'bzrlib.tests.test_lockable_files',
 
3522
                   'bzrlib.tests.test_lockdir',
 
3523
                   'bzrlib.tests.test_log',
 
3524
                   'bzrlib.tests.test_lru_cache',
 
3525
                   'bzrlib.tests.test_lsprof',
 
3526
                   'bzrlib.tests.test_mail_client',
 
3527
                   'bzrlib.tests.test_memorytree',
 
3528
                   'bzrlib.tests.test_merge',
 
3529
                   'bzrlib.tests.test_merge3',
 
3530
                   'bzrlib.tests.test_merge_core',
 
3531
                   'bzrlib.tests.test_merge_directive',
 
3532
                   'bzrlib.tests.test_missing',
 
3533
                   'bzrlib.tests.test_msgeditor',
 
3534
                   'bzrlib.tests.test_multiparent',
 
3535
                   'bzrlib.tests.test_mutabletree',
 
3536
                   'bzrlib.tests.test_nonascii',
 
3537
                   'bzrlib.tests.test_options',
 
3538
                   'bzrlib.tests.test_osutils',
 
3539
                   'bzrlib.tests.test_osutils_encodings',
 
3540
                   'bzrlib.tests.test_pack',
 
3541
                   'bzrlib.tests.test_patch',
 
3542
                   'bzrlib.tests.test_patches',
 
3543
                   'bzrlib.tests.test_permissions',
 
3544
                   'bzrlib.tests.test_plugins',
 
3545
                   'bzrlib.tests.test_progress',
 
3546
                   'bzrlib.tests.test_read_bundle',
 
3547
                   'bzrlib.tests.test_reconcile',
 
3548
                   'bzrlib.tests.test_reconfigure',
 
3549
                   'bzrlib.tests.test_registry',
 
3550
                   'bzrlib.tests.test_remote',
 
3551
                   'bzrlib.tests.test_rename_map',
 
3552
                   'bzrlib.tests.test_repository',
 
3553
                   'bzrlib.tests.test_revert',
 
3554
                   'bzrlib.tests.test_revision',
 
3555
                   'bzrlib.tests.test_revisionspec',
 
3556
                   'bzrlib.tests.test_revisiontree',
 
3557
                   'bzrlib.tests.test_rio',
 
3558
                   'bzrlib.tests.test_rules',
 
3559
                   'bzrlib.tests.test_sampler',
 
3560
                   'bzrlib.tests.test_selftest',
 
3561
                   'bzrlib.tests.test_serializer',
 
3562
                   'bzrlib.tests.test_setup',
 
3563
                   'bzrlib.tests.test_sftp_transport',
 
3564
                   'bzrlib.tests.test_shelf',
 
3565
                   'bzrlib.tests.test_shelf_ui',
 
3566
                   'bzrlib.tests.test_smart',
 
3567
                   'bzrlib.tests.test_smart_add',
 
3568
                   'bzrlib.tests.test_smart_request',
 
3569
                   'bzrlib.tests.test_smart_transport',
 
3570
                   'bzrlib.tests.test_smtp_connection',
 
3571
                   'bzrlib.tests.test_source',
 
3572
                   'bzrlib.tests.test_ssh_transport',
 
3573
                   'bzrlib.tests.test_status',
 
3574
                   'bzrlib.tests.test_store',
 
3575
                   'bzrlib.tests.test_strace',
 
3576
                   'bzrlib.tests.test_subsume',
 
3577
                   'bzrlib.tests.test_switch',
 
3578
                   'bzrlib.tests.test_symbol_versioning',
 
3579
                   'bzrlib.tests.test_tag',
 
3580
                   'bzrlib.tests.test_testament',
 
3581
                   'bzrlib.tests.test_textfile',
 
3582
                   'bzrlib.tests.test_textmerge',
 
3583
                   'bzrlib.tests.test_timestamp',
 
3584
                   'bzrlib.tests.test_trace',
 
3585
                   'bzrlib.tests.test_transactions',
 
3586
                   'bzrlib.tests.test_transform',
 
3587
                   'bzrlib.tests.test_transport',
 
3588
                   'bzrlib.tests.test_transport_log',
 
3589
                   'bzrlib.tests.test_tree',
 
3590
                   'bzrlib.tests.test_treebuilder',
 
3591
                   'bzrlib.tests.test_tsort',
 
3592
                   'bzrlib.tests.test_tuned_gzip',
 
3593
                   'bzrlib.tests.test_ui',
 
3594
                   'bzrlib.tests.test_uncommit',
 
3595
                   'bzrlib.tests.test_upgrade',
 
3596
                   'bzrlib.tests.test_upgrade_stacked',
 
3597
                   'bzrlib.tests.test_urlutils',
 
3598
                   'bzrlib.tests.test_version',
 
3599
                   'bzrlib.tests.test_version_info',
 
3600
                   'bzrlib.tests.test_weave',
 
3601
                   'bzrlib.tests.test_whitebox',
 
3602
                   'bzrlib.tests.test_win32utils',
 
3603
                   'bzrlib.tests.test_workingtree',
 
3604
                   'bzrlib.tests.test_workingtree_4',
 
3605
                   'bzrlib.tests.test_wsgi',
 
3606
                   'bzrlib.tests.test_xml',
 
3607
                   ]
4181
3608
 
4182
3609
    loader = TestUtil.TestLoader()
4183
3610
 
4212
3639
    suite = loader.suiteClass()
4213
3640
 
4214
3641
    # modules building their suite with loadTestsFromModuleNames
4215
 
    suite.addTest(loader.loadTestsFromModuleNames(_test_suite_testmod_names()))
4216
 
 
4217
 
    for mod in _test_suite_modules_to_doctest():
 
3642
    suite.addTest(loader.loadTestsFromModuleNames(testmod_names))
 
3643
 
 
3644
    modules_to_doctest = [
 
3645
        'bzrlib',
 
3646
        'bzrlib.branchbuilder',
 
3647
        'bzrlib.export',
 
3648
        'bzrlib.inventory',
 
3649
        'bzrlib.iterablefile',
 
3650
        'bzrlib.lockdir',
 
3651
        'bzrlib.merge3',
 
3652
        'bzrlib.option',
 
3653
        'bzrlib.symbol_versioning',
 
3654
        'bzrlib.tests',
 
3655
        'bzrlib.timestamp',
 
3656
        'bzrlib.version_info_formats.format_custom',
 
3657
        ]
 
3658
 
 
3659
    for mod in modules_to_doctest:
4218
3660
        if not interesting_module(mod):
4219
3661
            # No tests to keep here, move along
4220
3662
            continue
4221
3663
        try:
4222
3664
            # note that this really does mean "report only" -- doctest
4223
3665
            # still runs the rest of the examples
4224
 
            doc_suite = IsolatedDocTestSuite(
4225
 
                mod, optionflags=doctest.REPORT_ONLY_FIRST_FAILURE)
 
3666
            doc_suite = doctest.DocTestSuite(mod,
 
3667
                optionflags=doctest.REPORT_ONLY_FIRST_FAILURE)
4226
3668
        except ValueError, e:
4227
3669
            print '**failed to get doctest for: %s\n%s' % (mod, e)
4228
3670
            raise
4231
3673
        suite.addTest(doc_suite)
4232
3674
 
4233
3675
    default_encoding = sys.getdefaultencoding()
4234
 
    for name, plugin in _mod_plugin.plugins().items():
 
3676
    for name, plugin in bzrlib.plugin.plugins().items():
4235
3677
        if not interesting_module(plugin.module.__name__):
4236
3678
            continue
4237
3679
        plugin_suite = plugin.test_suite()
4243
3685
        if plugin_suite is not None:
4244
3686
            suite.addTest(plugin_suite)
4245
3687
        if default_encoding != sys.getdefaultencoding():
4246
 
            trace.warning(
 
3688
            bzrlib.trace.warning(
4247
3689
                'Plugin "%s" tried to reset default encoding to: %s', name,
4248
3690
                sys.getdefaultencoding())
4249
3691
            reload(sys)
4264
3706
            # Some tests mentioned in the list are not in the test suite. The
4265
3707
            # list may be out of date, report to the tester.
4266
3708
            for id in not_found:
4267
 
                trace.warning('"%s" not found in the test suite', id)
 
3709
                bzrlib.trace.warning('"%s" not found in the test suite', id)
4268
3710
        for id in duplicates:
4269
 
            trace.warning('"%s" is used as an id by several tests', id)
 
3711
            bzrlib.trace.warning('"%s" is used as an id by several tests', id)
4270
3712
 
4271
3713
    return suite
4272
3714
 
4273
3715
 
4274
 
def multiply_scenarios(*scenarios):
4275
 
    """Multiply two or more iterables of scenarios.
4276
 
 
4277
 
    It is safe to pass scenario generators or iterators.
4278
 
 
4279
 
    :returns: A list of compound scenarios: the cross-product of all 
4280
 
        scenarios, with the names concatenated and the parameters
4281
 
        merged together.
4282
 
    """
4283
 
    return reduce(_multiply_two_scenarios, map(list, scenarios))
4284
 
 
4285
 
 
4286
 
def _multiply_two_scenarios(scenarios_left, scenarios_right):
 
3716
def multiply_scenarios(scenarios_left, scenarios_right):
4287
3717
    """Multiply two sets of scenarios.
4288
3718
 
4289
3719
    :returns: the cartesian product of the two sets of scenarios, that is
4320
3750
    ...     bzrlib.tests.test_sampler.DemoTest('test_nothing'),
4321
3751
    ...     [('one', dict(param=1)),
4322
3752
    ...      ('two', dict(param=2))],
4323
 
    ...     TestUtil.TestSuite())
 
3753
    ...     TestSuite())
4324
3754
    >>> tests = list(iter_suite_tests(r))
4325
3755
    >>> len(tests)
4326
3756
    2
4353
3783
    """Copy test and apply scenario to it.
4354
3784
 
4355
3785
    :param test: A test to adapt.
4356
 
    :param scenario: A tuple describing the scenario.
 
3786
    :param scenario: A tuple describing the scenarion.
4357
3787
        The first element of the tuple is the new test id.
4358
3788
        The second element is a dict containing attributes to set on the
4359
3789
        test.
4373
3803
    :param new_id: The id to assign to it.
4374
3804
    :return: The new test.
4375
3805
    """
4376
 
    new_test = copy.copy(test)
 
3806
    from copy import deepcopy
 
3807
    new_test = deepcopy(test)
4377
3808
    new_test.id = lambda: new_id
4378
 
    # XXX: Workaround <https://bugs.launchpad.net/testtools/+bug/637725>, which
4379
 
    # causes cloned tests to share the 'details' dict.  This makes it hard to
4380
 
    # read the test output for parameterized tests, because tracebacks will be
4381
 
    # associated with irrelevant tests.
4382
 
    try:
4383
 
        details = new_test._TestCase__details
4384
 
    except AttributeError:
4385
 
        # must be a different version of testtools than expected.  Do nothing.
4386
 
        pass
4387
 
    else:
4388
 
        # Reset the '__details' dict.
4389
 
        new_test._TestCase__details = {}
4390
3809
    return new_test
4391
3810
 
4392
3811
 
4393
 
def permute_tests_for_extension(standard_tests, loader, py_module_name,
4394
 
                                ext_module_name):
4395
 
    """Helper for permutating tests against an extension module.
4396
 
 
4397
 
    This is meant to be used inside a modules 'load_tests()' function. It will
4398
 
    create 2 scenarios, and cause all tests in the 'standard_tests' to be run
4399
 
    against both implementations. Setting 'test.module' to the appropriate
4400
 
    module. See bzrlib.tests.test__chk_map.load_tests as an example.
4401
 
 
4402
 
    :param standard_tests: A test suite to permute
4403
 
    :param loader: A TestLoader
4404
 
    :param py_module_name: The python path to a python module that can always
4405
 
        be loaded, and will be considered the 'python' implementation. (eg
4406
 
        'bzrlib._chk_map_py')
4407
 
    :param ext_module_name: The python path to an extension module. If the
4408
 
        module cannot be loaded, a single test will be added, which notes that
4409
 
        the module is not available. If it can be loaded, all standard_tests
4410
 
        will be run against that module.
4411
 
    :return: (suite, feature) suite is a test-suite that has all the permuted
4412
 
        tests. feature is the Feature object that can be used to determine if
4413
 
        the module is available.
4414
 
    """
4415
 
 
4416
 
    from bzrlib.tests.features import ModuleAvailableFeature
4417
 
    py_module = pyutils.get_named_object(py_module_name)
4418
 
    scenarios = [
4419
 
        ('python', {'module': py_module}),
4420
 
    ]
4421
 
    suite = loader.suiteClass()
4422
 
    feature = ModuleAvailableFeature(ext_module_name)
4423
 
    if feature.available():
4424
 
        scenarios.append(('C', {'module': feature.module}))
4425
 
    else:
4426
 
        # the compiled module isn't available, so we add a failing test
4427
 
        class FailWithoutFeature(TestCase):
4428
 
            def test_fail(self):
4429
 
                self.requireFeature(feature)
4430
 
        suite.addTest(loader.loadTestsFromTestCase(FailWithoutFeature))
4431
 
    result = multiply_tests(standard_tests, scenarios, suite)
4432
 
    return result, feature
4433
 
 
4434
 
 
4435
 
def _rmtree_temp_dir(dirname, test_id=None):
 
3812
def _rmtree_temp_dir(dirname):
4436
3813
    # If LANG=C we probably have created some bogus paths
4437
3814
    # which rmtree(unicode) will fail to delete
4438
3815
    # so make sure we are using rmtree(str) to delete everything
4450
3827
        # We don't want to fail here because some useful display will be lost
4451
3828
        # otherwise. Polluting the tmp dir is bad, but not giving all the
4452
3829
        # possible info to the test runner is even worse.
4453
 
        if test_id != None:
4454
 
            ui.ui_factory.clear_term()
4455
 
            sys.stderr.write('\nWhile running: %s\n' % (test_id,))
4456
 
        # Ugly, but the last thing we want here is fail, so bear with it.
4457
 
        printable_e = str(e).decode(osutils.get_user_encoding(), 'replace'
4458
 
                                    ).encode('ascii', 'replace')
4459
3830
        sys.stderr.write('Unable to remove testing dir %s\n%s'
4460
 
                         % (os.path.basename(dirname), printable_e))
 
3831
                         % (os.path.basename(dirname), e))
 
3832
 
 
3833
 
 
3834
class Feature(object):
 
3835
    """An operating system Feature."""
 
3836
 
 
3837
    def __init__(self):
 
3838
        self._available = None
 
3839
 
 
3840
    def available(self):
 
3841
        """Is the feature available?
 
3842
 
 
3843
        :return: True if the feature is available.
 
3844
        """
 
3845
        if self._available is None:
 
3846
            self._available = self._probe()
 
3847
        return self._available
 
3848
 
 
3849
    def _probe(self):
 
3850
        """Implement this method in concrete features.
 
3851
 
 
3852
        :return: True if the feature is available.
 
3853
        """
 
3854
        raise NotImplementedError
 
3855
 
 
3856
    def __str__(self):
 
3857
        if getattr(self, 'feature_name', None):
 
3858
            return self.feature_name()
 
3859
        return self.__class__.__name__
 
3860
 
 
3861
 
 
3862
class _SymlinkFeature(Feature):
 
3863
 
 
3864
    def _probe(self):
 
3865
        return osutils.has_symlinks()
 
3866
 
 
3867
    def feature_name(self):
 
3868
        return 'symlinks'
 
3869
 
 
3870
SymlinkFeature = _SymlinkFeature()
 
3871
 
 
3872
 
 
3873
class _HardlinkFeature(Feature):
 
3874
 
 
3875
    def _probe(self):
 
3876
        return osutils.has_hardlinks()
 
3877
 
 
3878
    def feature_name(self):
 
3879
        return 'hardlinks'
 
3880
 
 
3881
HardlinkFeature = _HardlinkFeature()
 
3882
 
 
3883
 
 
3884
class _OsFifoFeature(Feature):
 
3885
 
 
3886
    def _probe(self):
 
3887
        return getattr(os, 'mkfifo', None)
 
3888
 
 
3889
    def feature_name(self):
 
3890
        return 'filesystem fifos'
 
3891
 
 
3892
OsFifoFeature = _OsFifoFeature()
 
3893
 
 
3894
 
 
3895
class _UnicodeFilenameFeature(Feature):
 
3896
    """Does the filesystem support Unicode filenames?"""
 
3897
 
 
3898
    def _probe(self):
 
3899
        try:
 
3900
            # Check for character combinations unlikely to be covered by any
 
3901
            # single non-unicode encoding. We use the characters
 
3902
            # - greek small letter alpha (U+03B1) and
 
3903
            # - braille pattern dots-123456 (U+283F).
 
3904
            os.stat(u'\u03b1\u283f')
 
3905
        except UnicodeEncodeError:
 
3906
            return False
 
3907
        except (IOError, OSError):
 
3908
            # The filesystem allows the Unicode filename but the file doesn't
 
3909
            # exist.
 
3910
            return True
 
3911
        else:
 
3912
            # The filesystem allows the Unicode filename and the file exists,
 
3913
            # for some reason.
 
3914
            return True
 
3915
 
 
3916
UnicodeFilenameFeature = _UnicodeFilenameFeature()
4461
3917
 
4462
3918
 
4463
3919
def probe_unicode_in_user_encoding():
4493
3949
    return None
4494
3950
 
4495
3951
 
 
3952
class _HTTPSServerFeature(Feature):
 
3953
    """Some tests want an https Server, check if one is available.
 
3954
 
 
3955
    Right now, the only way this is available is under python2.6 which provides
 
3956
    an ssl module.
 
3957
    """
 
3958
 
 
3959
    def _probe(self):
 
3960
        try:
 
3961
            import ssl
 
3962
            return True
 
3963
        except ImportError:
 
3964
            return False
 
3965
 
 
3966
    def feature_name(self):
 
3967
        return 'HTTPSServer'
 
3968
 
 
3969
 
 
3970
HTTPSServerFeature = _HTTPSServerFeature()
 
3971
 
 
3972
 
 
3973
class _UnicodeFilename(Feature):
 
3974
    """Does the filesystem support Unicode filenames?"""
 
3975
 
 
3976
    def _probe(self):
 
3977
        try:
 
3978
            os.stat(u'\u03b1')
 
3979
        except UnicodeEncodeError:
 
3980
            return False
 
3981
        except (IOError, OSError):
 
3982
            # The filesystem allows the Unicode filename but the file doesn't
 
3983
            # exist.
 
3984
            return True
 
3985
        else:
 
3986
            # The filesystem allows the Unicode filename and the file exists,
 
3987
            # for some reason.
 
3988
            return True
 
3989
 
 
3990
UnicodeFilename = _UnicodeFilename()
 
3991
 
 
3992
 
 
3993
class _UTF8Filesystem(Feature):
 
3994
    """Is the filesystem UTF-8?"""
 
3995
 
 
3996
    def _probe(self):
 
3997
        if osutils._fs_enc.upper() in ('UTF-8', 'UTF8'):
 
3998
            return True
 
3999
        return False
 
4000
 
 
4001
UTF8Filesystem = _UTF8Filesystem()
 
4002
 
 
4003
 
 
4004
class _CaseInsCasePresFilenameFeature(Feature):
 
4005
    """Is the file-system case insensitive, but case-preserving?"""
 
4006
 
 
4007
    def _probe(self):
 
4008
        fileno, name = tempfile.mkstemp(prefix='MixedCase')
 
4009
        try:
 
4010
            # first check truly case-preserving for created files, then check
 
4011
            # case insensitive when opening existing files.
 
4012
            name = osutils.normpath(name)
 
4013
            base, rel = osutils.split(name)
 
4014
            found_rel = osutils.canonical_relpath(base, name)
 
4015
            return (found_rel == rel
 
4016
                    and os.path.isfile(name.upper())
 
4017
                    and os.path.isfile(name.lower()))
 
4018
        finally:
 
4019
            os.close(fileno)
 
4020
            os.remove(name)
 
4021
 
 
4022
    def feature_name(self):
 
4023
        return "case-insensitive case-preserving filesystem"
 
4024
 
 
4025
CaseInsCasePresFilenameFeature = _CaseInsCasePresFilenameFeature()
 
4026
 
 
4027
 
 
4028
class _CaseInsensitiveFilesystemFeature(Feature):
 
4029
    """Check if underlying filesystem is case-insensitive but *not* case
 
4030
    preserving.
 
4031
    """
 
4032
    # Note that on Windows, Cygwin, MacOS etc, the file-systems are far
 
4033
    # more likely to be case preserving, so this case is rare.
 
4034
 
 
4035
    def _probe(self):
 
4036
        if CaseInsCasePresFilenameFeature.available():
 
4037
            return False
 
4038
 
 
4039
        if TestCaseWithMemoryTransport.TEST_ROOT is None:
 
4040
            root = osutils.mkdtemp(prefix='testbzr-', suffix='.tmp')
 
4041
            TestCaseWithMemoryTransport.TEST_ROOT = root
 
4042
        else:
 
4043
            root = TestCaseWithMemoryTransport.TEST_ROOT
 
4044
        tdir = osutils.mkdtemp(prefix='case-sensitive-probe-', suffix='',
 
4045
            dir=root)
 
4046
        name_a = osutils.pathjoin(tdir, 'a')
 
4047
        name_A = osutils.pathjoin(tdir, 'A')
 
4048
        os.mkdir(name_a)
 
4049
        result = osutils.isdir(name_A)
 
4050
        _rmtree_temp_dir(tdir)
 
4051
        return result
 
4052
 
 
4053
    def feature_name(self):
 
4054
        return 'case-insensitive filesystem'
 
4055
 
 
4056
CaseInsensitiveFilesystemFeature = _CaseInsensitiveFilesystemFeature()
 
4057
 
 
4058
 
 
4059
class _SubUnitFeature(Feature):
 
4060
    """Check if subunit is available."""
 
4061
 
 
4062
    def _probe(self):
 
4063
        try:
 
4064
            import subunit
 
4065
            return True
 
4066
        except ImportError:
 
4067
            return False
 
4068
 
 
4069
    def feature_name(self):
 
4070
        return 'subunit'
 
4071
 
 
4072
SubUnitFeature = _SubUnitFeature()
4496
4073
# Only define SubUnitBzrRunner if subunit is available.
4497
4074
try:
4498
4075
    from subunit import TestProtocolClient
4499
 
    from subunit.test_results import AutoTimingTestResultDecorator
4500
 
    class SubUnitBzrProtocolClient(TestProtocolClient):
4501
 
 
4502
 
        def stopTest(self, test):
4503
 
            super(SubUnitBzrProtocolClient, self).stopTest(test)
4504
 
            _clear__type_equality_funcs(test)
4505
 
 
4506
 
        def addSuccess(self, test, details=None):
4507
 
            # The subunit client always includes the details in the subunit
4508
 
            # stream, but we don't want to include it in ours.
4509
 
            if details is not None and 'log' in details:
4510
 
                del details['log']
4511
 
            return super(SubUnitBzrProtocolClient, self).addSuccess(
4512
 
                test, details)
4513
 
 
 
4076
    try:
 
4077
        from subunit.test_results import AutoTimingTestResultDecorator
 
4078
    except ImportError:
 
4079
        AutoTimingTestResultDecorator = lambda x:x
4514
4080
    class SubUnitBzrRunner(TextTestRunner):
4515
4081
        def run(self, test):
4516
4082
            result = AutoTimingTestResultDecorator(
4517
 
                SubUnitBzrProtocolClient(self.stream))
 
4083
                TestProtocolClient(self.stream))
4518
4084
            test.run(result)
4519
4085
            return result
4520
4086
except ImportError:
4521
4087
    pass
4522
 
 
4523
 
 
4524
 
# API compatibility for old plugins; see bug 892622.
4525
 
for name in [
4526
 
    'Feature',
4527
 
    'HTTPServerFeature', 
4528
 
    'ModuleAvailableFeature',
4529
 
    'HTTPSServerFeature', 'SymlinkFeature', 'HardlinkFeature',
4530
 
    'OsFifoFeature', 'UnicodeFilenameFeature',
4531
 
    'ByteStringNamedFilesystem', 'UTF8Filesystem',
4532
 
    'BreakinFeature', 'CaseInsCasePresFilenameFeature',
4533
 
    'CaseInsensitiveFilesystemFeature', 'case_sensitive_filesystem_feature',
4534
 
    'posix_permissions_feature',
4535
 
    ]:
4536
 
    globals()[name] = _CompatabilityThunkFeature(
4537
 
        symbol_versioning.deprecated_in((2, 5, 0)),
4538
 
        'bzrlib.tests', name,
4539
 
        name, 'bzrlib.tests.features')
4540
 
 
4541
 
 
4542
 
for (old_name, new_name) in [
4543
 
    ('UnicodeFilename', 'UnicodeFilenameFeature'),
4544
 
    ]:
4545
 
    globals()[name] = _CompatabilityThunkFeature(
4546
 
        symbol_versioning.deprecated_in((2, 5, 0)),
4547
 
        'bzrlib.tests', old_name,
4548
 
        new_name, 'bzrlib.tests.features')