~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/__init__.py

  • Committer: John Arbash Meinel
  • Date: 2013-05-19 14:29:37 UTC
  • mfrom: (6437.63.9 2.5)
  • mto: (6437.63.10 2.5)
  • mto: This revision was merged to the branch mainline in revision 6575.
  • Revision ID: john@arbash-meinel.com-20130519142937-21ykz2n2y2f22za9
Merge in the actual 2.5 branch. It seems I failed before

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006, 2007 Canonical Ltd
 
1
# Copyright (C) 2005-2011 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
12
12
#
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
 
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
 
 
17
 
 
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)
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
16
 
 
17
"""Testing framework extensions"""
 
18
 
 
19
from __future__ import absolute_import
23
20
 
24
21
# NOTE: Some classes in here use camelCaseNaming() rather than
25
22
# underscore_naming().  That's for consistency with unittest; it's not the
26
23
# general style of bzrlib.  Please continue that consistency when adding e.g.
27
24
# new assertFoo() methods.
28
25
 
 
26
import atexit
29
27
import codecs
 
28
import copy
30
29
from cStringIO import StringIO
31
30
import difflib
32
31
import doctest
33
32
import errno
 
33
import itertools
34
34
import logging
35
35
import os
36
 
from pprint import pformat
 
36
import platform
 
37
import pprint
 
38
import random
37
39
import re
38
40
import shlex
 
41
import site
39
42
import stat
40
 
from subprocess import Popen, PIPE
 
43
import subprocess
41
44
import sys
42
45
import tempfile
 
46
import threading
 
47
import time
 
48
import traceback
43
49
import unittest
44
 
import time
45
 
 
46
 
 
 
50
import warnings
 
51
 
 
52
import testtools
 
53
# nb: check this before importing anything else from within it
 
54
_testtools_version = getattr(testtools, '__version__', ())
 
55
if _testtools_version < (0, 9, 5):
 
56
    raise ImportError("need at least testtools 0.9.5: %s is %r"
 
57
        % (testtools.__file__, _testtools_version))
 
58
from testtools import content
 
59
 
 
60
import bzrlib
47
61
from bzrlib import (
 
62
    branchbuilder,
48
63
    bzrdir,
 
64
    chk_map,
 
65
    commands as _mod_commands,
 
66
    config,
 
67
    i18n,
49
68
    debug,
50
69
    errors,
 
70
    hooks,
 
71
    lock as _mod_lock,
 
72
    lockdir,
51
73
    memorytree,
52
74
    osutils,
53
 
    progress,
 
75
    plugin as _mod_plugin,
 
76
    pyutils,
54
77
    ui,
55
78
    urlutils,
 
79
    registry,
 
80
    symbol_versioning,
 
81
    trace,
 
82
    transport as _mod_transport,
 
83
    workingtree,
56
84
    )
57
 
import bzrlib.branch
58
 
import bzrlib.commands
59
 
import bzrlib.timestamp
60
 
import bzrlib.export
61
 
import bzrlib.inventory
62
 
import bzrlib.iterablefile
63
 
import bzrlib.lockdir
64
85
try:
65
86
    import bzrlib.lsprof
66
87
except ImportError:
67
88
    # lsprof not available
68
89
    pass
69
 
from bzrlib.merge import merge_inner
70
 
import bzrlib.merge3
71
 
import bzrlib.osutils
72
 
import bzrlib.plugin
73
 
from bzrlib.revision import common_ancestor
74
 
import bzrlib.store
75
 
from bzrlib import symbol_versioning
76
 
import bzrlib.trace
77
 
from bzrlib.transport import get_transport
78
 
import bzrlib.transport
79
 
from bzrlib.transport.local import LocalURLServer
80
 
from bzrlib.transport.memory import MemoryServer
81
 
from bzrlib.transport.readonly import ReadonlyServer
82
 
from bzrlib.trace import mutter, note
83
 
from bzrlib.tests import TestUtil
84
 
from bzrlib.tests.HttpServer import HttpServer
85
 
from bzrlib.tests.TestUtil import (
86
 
                          TestSuite,
87
 
                          TestLoader,
88
 
                          )
89
 
from bzrlib.tests.treeshape import build_tree_contents
90
 
from bzrlib.workingtree import WorkingTree, WorkingTreeFormat2
91
 
 
92
 
default_transport = LocalURLServer
93
 
 
94
 
MODULES_TO_TEST = []
95
 
MODULES_TO_DOCTEST = [
96
 
                      bzrlib.timestamp,
97
 
                      bzrlib.errors,
98
 
                      bzrlib.export,
99
 
                      bzrlib.inventory,
100
 
                      bzrlib.iterablefile,
101
 
                      bzrlib.lockdir,
102
 
                      bzrlib.merge3,
103
 
                      bzrlib.option,
104
 
                      bzrlib.store,
105
 
                      ]
106
 
 
107
 
 
108
 
def packages_to_test():
109
 
    """Return a list of packages to test.
110
 
 
111
 
    The packages are not globally imported so that import failures are
112
 
    triggered when running selftest, not when importing the command.
113
 
    """
114
 
    import bzrlib.doc
115
 
    import bzrlib.tests.blackbox
116
 
    import bzrlib.tests.branch_implementations
117
 
    import bzrlib.tests.bzrdir_implementations
118
 
    import bzrlib.tests.interrepository_implementations
119
 
    import bzrlib.tests.interversionedfile_implementations
120
 
    import bzrlib.tests.intertree_implementations
121
 
    import bzrlib.tests.per_lock
122
 
    import bzrlib.tests.repository_implementations
123
 
    import bzrlib.tests.revisionstore_implementations
124
 
    import bzrlib.tests.tree_implementations
125
 
    import bzrlib.tests.workingtree_implementations
126
 
    return [
127
 
            bzrlib.doc,
128
 
            bzrlib.tests.blackbox,
129
 
            bzrlib.tests.branch_implementations,
130
 
            bzrlib.tests.bzrdir_implementations,
131
 
            bzrlib.tests.interrepository_implementations,
132
 
            bzrlib.tests.interversionedfile_implementations,
133
 
            bzrlib.tests.intertree_implementations,
134
 
            bzrlib.tests.per_lock,
135
 
            bzrlib.tests.repository_implementations,
136
 
            bzrlib.tests.revisionstore_implementations,
137
 
            bzrlib.tests.tree_implementations,
138
 
            bzrlib.tests.workingtree_implementations,
139
 
            ]
140
 
 
141
 
 
142
 
class ExtendedTestResult(unittest._TextTestResult):
 
90
from bzrlib.smart import client, request
 
91
from bzrlib.transport import (
 
92
    memory,
 
93
    pathfilter,
 
94
    )
 
95
from bzrlib.symbol_versioning import (
 
96
    deprecated_function,
 
97
    deprecated_in,
 
98
    )
 
99
from bzrlib.tests import (
 
100
    fixtures,
 
101
    test_server,
 
102
    TestUtil,
 
103
    treeshape,
 
104
    )
 
105
from bzrlib.ui import NullProgressView
 
106
from bzrlib.ui.text import TextUIFactory
 
107
from bzrlib.tests.features import _CompatabilityThunkFeature
 
108
 
 
109
# Mark this python module as being part of the implementation
 
110
# of unittest: this gives us better tracebacks where the last
 
111
# shown frame is the test code, not our assertXYZ.
 
112
__unittest = 1
 
113
 
 
114
default_transport = test_server.LocalURLServer
 
115
 
 
116
 
 
117
_unitialized_attr = object()
 
118
"""A sentinel needed to act as a default value in a method signature."""
 
119
 
 
120
 
 
121
# Subunit result codes, defined here to prevent a hard dependency on subunit.
 
122
SUBUNIT_SEEK_SET = 0
 
123
SUBUNIT_SEEK_CUR = 1
 
124
 
 
125
# These are intentionally brought into this namespace. That way plugins, etc
 
126
# can just "from bzrlib.tests import TestCase, TestLoader, etc"
 
127
TestSuite = TestUtil.TestSuite
 
128
TestLoader = TestUtil.TestLoader
 
129
 
 
130
# Tests should run in a clean and clearly defined environment. The goal is to
 
131
# keep them isolated from the running environment as mush as possible. The test
 
132
# framework ensures the variables defined below are set (or deleted if the
 
133
# value is None) before a test is run and reset to their original value after
 
134
# the test is run. Generally if some code depends on an environment variable,
 
135
# the tests should start without this variable in the environment. There are a
 
136
# few exceptions but you shouldn't violate this rule lightly.
 
137
isolated_environ = {
 
138
    'BZR_HOME': None,
 
139
    'HOME': None,
 
140
    'XDG_CONFIG_HOME': None,
 
141
    # bzr now uses the Win32 API and doesn't rely on APPDATA, but the
 
142
    # tests do check our impls match APPDATA
 
143
    'BZR_EDITOR': None, # test_msgeditor manipulates this variable
 
144
    'VISUAL': None,
 
145
    'EDITOR': None,
 
146
    'BZR_EMAIL': None,
 
147
    'BZREMAIL': None, # may still be present in the environment
 
148
    'EMAIL': 'jrandom@example.com', # set EMAIL as bzr does not guess
 
149
    'BZR_PROGRESS_BAR': None,
 
150
    # This should trap leaks to ~/.bzr.log. This occurs when tests use TestCase
 
151
    # as a base class instead of TestCaseInTempDir. Tests inheriting from
 
152
    # TestCase should not use disk resources, BZR_LOG is one.
 
153
    'BZR_LOG': '/you-should-use-TestCaseInTempDir-if-you-need-a-log-file',
 
154
    'BZR_PLUGIN_PATH': None,
 
155
    'BZR_DISABLE_PLUGINS': None,
 
156
    'BZR_PLUGINS_AT': None,
 
157
    'BZR_CONCURRENCY': None,
 
158
    # Make sure that any text ui tests are consistent regardless of
 
159
    # the environment the test case is run in; you may want tests that
 
160
    # test other combinations.  'dumb' is a reasonable guess for tests
 
161
    # going to a pipe or a StringIO.
 
162
    'TERM': 'dumb',
 
163
    'LINES': '25',
 
164
    'COLUMNS': '80',
 
165
    'BZR_COLUMNS': '80',
 
166
    # Disable SSH Agent
 
167
    'SSH_AUTH_SOCK': None,
 
168
    # Proxies
 
169
    'http_proxy': None,
 
170
    'HTTP_PROXY': None,
 
171
    'https_proxy': None,
 
172
    'HTTPS_PROXY': None,
 
173
    'no_proxy': None,
 
174
    'NO_PROXY': None,
 
175
    'all_proxy': None,
 
176
    'ALL_PROXY': None,
 
177
    # Nobody cares about ftp_proxy, FTP_PROXY AFAIK. So far at
 
178
    # least. If you do (care), please update this comment
 
179
    # -- vila 20080401
 
180
    'ftp_proxy': None,
 
181
    'FTP_PROXY': None,
 
182
    'BZR_REMOTE_PATH': None,
 
183
    # Generally speaking, we don't want apport reporting on crashes in
 
184
    # the test envirnoment unless we're specifically testing apport,
 
185
    # so that it doesn't leak into the real system environment.  We
 
186
    # use an env var so it propagates to subprocesses.
 
187
    'APPORT_DISABLE': '1',
 
188
    }
 
189
 
 
190
 
 
191
def override_os_environ(test, env=None):
 
192
    """Modify os.environ keeping a copy.
 
193
    
 
194
    :param test: A test instance
 
195
 
 
196
    :param env: A dict containing variable definitions to be installed
 
197
    """
 
198
    if env is None:
 
199
        env = isolated_environ
 
200
    test._original_os_environ = dict([(var, value)
 
201
                                      for var, value in os.environ.iteritems()])
 
202
    for var, value in env.iteritems():
 
203
        osutils.set_or_unset_env(var, value)
 
204
        if var not in test._original_os_environ:
 
205
            # The var is new, add it with a value of None, so
 
206
            # restore_os_environ will delete it
 
207
            test._original_os_environ[var] = None
 
208
 
 
209
 
 
210
def restore_os_environ(test):
 
211
    """Restore os.environ to its original state.
 
212
 
 
213
    :param test: A test instance previously passed to override_os_environ.
 
214
    """
 
215
    for var, value in test._original_os_environ.iteritems():
 
216
        # Restore the original value (or delete it if the value has been set to
 
217
        # None in override_os_environ).
 
218
        osutils.set_or_unset_env(var, value)
 
219
 
 
220
 
 
221
def _clear__type_equality_funcs(test):
 
222
    """Cleanup bound methods stored on TestCase instances
 
223
 
 
224
    Clear the dict breaking a few (mostly) harmless cycles in the affected
 
225
    unittests released with Python 2.6 and initial Python 2.7 versions.
 
226
 
 
227
    For a few revisions between Python 2.7.1 and Python 2.7.2 that annoyingly
 
228
    shipped in Oneiric, an object with no clear method was used, hence the
 
229
    extra complications, see bug 809048 for details.
 
230
    """
 
231
    type_equality_funcs = getattr(test, "_type_equality_funcs", None)
 
232
    if type_equality_funcs is not None:
 
233
        tef_clear = getattr(type_equality_funcs, "clear", None)
 
234
        if tef_clear is None:
 
235
            tef_instance_dict = getattr(type_equality_funcs, "__dict__", None)
 
236
            if tef_instance_dict is not None:
 
237
                tef_clear = tef_instance_dict.clear
 
238
        if tef_clear is not None:
 
239
            tef_clear()
 
240
 
 
241
 
 
242
class ExtendedTestResult(testtools.TextTestResult):
143
243
    """Accepts, reports and accumulates the results of running tests.
144
244
 
145
 
    Compared to this unittest version this class adds support for profiling,
146
 
    benchmarking, stopping as soon as a test fails,  and skipping tests.
147
 
    There are further-specialized subclasses for different types of display.
 
245
    Compared to the unittest version this class adds support for
 
246
    profiling, benchmarking, stopping as soon as a test fails,  and
 
247
    skipping tests.  There are further-specialized subclasses for
 
248
    different types of display.
 
249
 
 
250
    When a test finishes, in whatever way, it calls one of the addSuccess,
 
251
    addFailure or addError classes.  These in turn may redirect to a more
 
252
    specific case for the special test results supported by our extended
 
253
    tests.
 
254
 
 
255
    Note that just one of these objects is fed the results from many tests.
148
256
    """
149
257
 
150
258
    stop_early = False
151
 
    
 
259
 
152
260
    def __init__(self, stream, descriptions, verbosity,
153
261
                 bench_history=None,
154
 
                 num_tests=None,
155
 
                 use_numbered_dirs=False,
 
262
                 strict=False,
156
263
                 ):
157
264
        """Construct new TestResult.
158
265
 
159
266
        :param bench_history: Optionally, a writable file object to accumulate
160
267
            benchmark results.
161
268
        """
162
 
        unittest._TextTestResult.__init__(self, stream, descriptions, verbosity)
 
269
        testtools.TextTestResult.__init__(self, stream)
163
270
        if bench_history is not None:
164
271
            from bzrlib.version import _get_bzr_source_tree
165
272
            src_tree = _get_bzr_source_tree()
176
283
            bench_history.write("--date %s %s\n" % (time.time(), revision_id))
177
284
        self._bench_history = bench_history
178
285
        self.ui = ui.ui_factory
179
 
        self.num_tests = num_tests
 
286
        self.num_tests = 0
180
287
        self.error_count = 0
181
288
        self.failure_count = 0
182
289
        self.known_failure_count = 0
183
290
        self.skip_count = 0
 
291
        self.not_applicable_count = 0
184
292
        self.unsupported = {}
185
293
        self.count = 0
186
 
        self.use_numbered_dirs = use_numbered_dirs
187
294
        self._overall_start_time = time.time()
188
 
    
189
 
    def extractBenchmarkTime(self, testCase):
 
295
        self._strict = strict
 
296
        self._first_thread_leaker_id = None
 
297
        self._tests_leaking_threads_count = 0
 
298
        self._traceback_from_test = None
 
299
 
 
300
    def stopTestRun(self):
 
301
        run = self.testsRun
 
302
        actionTaken = "Ran"
 
303
        stopTime = time.time()
 
304
        timeTaken = stopTime - self.startTime
 
305
        # GZ 2010-07-19: Seems testtools has no printErrors method, and though
 
306
        #                the parent class method is similar have to duplicate
 
307
        self._show_list('ERROR', self.errors)
 
308
        self._show_list('FAIL', self.failures)
 
309
        self.stream.write(self.sep2)
 
310
        self.stream.write("%s %d test%s in %.3fs\n\n" % (actionTaken,
 
311
                            run, run != 1 and "s" or "", timeTaken))
 
312
        if not self.wasSuccessful():
 
313
            self.stream.write("FAILED (")
 
314
            failed, errored = map(len, (self.failures, self.errors))
 
315
            if failed:
 
316
                self.stream.write("failures=%d" % failed)
 
317
            if errored:
 
318
                if failed: self.stream.write(", ")
 
319
                self.stream.write("errors=%d" % errored)
 
320
            if self.known_failure_count:
 
321
                if failed or errored: self.stream.write(", ")
 
322
                self.stream.write("known_failure_count=%d" %
 
323
                    self.known_failure_count)
 
324
            self.stream.write(")\n")
 
325
        else:
 
326
            if self.known_failure_count:
 
327
                self.stream.write("OK (known_failures=%d)\n" %
 
328
                    self.known_failure_count)
 
329
            else:
 
330
                self.stream.write("OK\n")
 
331
        if self.skip_count > 0:
 
332
            skipped = self.skip_count
 
333
            self.stream.write('%d test%s skipped\n' %
 
334
                                (skipped, skipped != 1 and "s" or ""))
 
335
        if self.unsupported:
 
336
            for feature, count in sorted(self.unsupported.items()):
 
337
                self.stream.write("Missing feature '%s' skipped %d tests.\n" %
 
338
                    (feature, count))
 
339
        if self._strict:
 
340
            ok = self.wasStrictlySuccessful()
 
341
        else:
 
342
            ok = self.wasSuccessful()
 
343
        if self._first_thread_leaker_id:
 
344
            self.stream.write(
 
345
                '%s is leaking threads among %d leaking tests.\n' % (
 
346
                self._first_thread_leaker_id,
 
347
                self._tests_leaking_threads_count))
 
348
            # We don't report the main thread as an active one.
 
349
            self.stream.write(
 
350
                '%d non-main threads were left active in the end.\n'
 
351
                % (len(self._active_threads) - 1))
 
352
 
 
353
    def getDescription(self, test):
 
354
        return test.id()
 
355
 
 
356
    def _extractBenchmarkTime(self, testCase, details=None):
190
357
        """Add a benchmark time for the current test case."""
191
 
        self._benchmarkTime = getattr(testCase, "_benchtime", None)
192
 
    
 
358
        if details and 'benchtime' in details:
 
359
            return float(''.join(details['benchtime'].iter_bytes()))
 
360
        return getattr(testCase, "_benchtime", None)
 
361
 
193
362
    def _elapsedTestTimeString(self):
194
363
        """Return a time string for the overall time the current test has taken."""
195
 
        return self._formatTime(time.time() - self._start_time)
 
364
        return self._formatTime(self._delta_to_float(
 
365
            self._now() - self._start_datetime))
196
366
 
197
 
    def _testTimeString(self):
198
 
        if self._benchmarkTime is not None:
199
 
            return "%s/%s" % (
200
 
                self._formatTime(self._benchmarkTime),
201
 
                self._elapsedTestTimeString())
 
367
    def _testTimeString(self, testCase):
 
368
        benchmark_time = self._extractBenchmarkTime(testCase)
 
369
        if benchmark_time is not None:
 
370
            return self._formatTime(benchmark_time) + "*"
202
371
        else:
203
 
            return "           %s" % self._elapsedTestTimeString()
 
372
            return self._elapsedTestTimeString()
204
373
 
205
374
    def _formatTime(self, seconds):
206
375
        """Format seconds as milliseconds with leading spaces."""
210
379
 
211
380
    def _shortened_test_description(self, test):
212
381
        what = test.id()
213
 
        what = re.sub(r'^bzrlib\.(tests|benchmarks)\.', '', what)
 
382
        what = re.sub(r'^bzrlib\.tests\.', '', what)
214
383
        return what
215
384
 
 
385
    # GZ 2010-10-04: Cloned tests may end up harmlessly calling this method
 
386
    #                multiple times in a row, because the handler is added for
 
387
    #                each test but the container list is shared between cases.
 
388
    #                See lp:498869 lp:625574 and lp:637725 for background.
 
389
    def _record_traceback_from_test(self, exc_info):
 
390
        """Store the traceback from passed exc_info tuple till"""
 
391
        self._traceback_from_test = exc_info[2]
 
392
 
216
393
    def startTest(self, test):
217
 
        unittest.TestResult.startTest(self, test)
 
394
        super(ExtendedTestResult, self).startTest(test)
 
395
        if self.count == 0:
 
396
            self.startTests()
 
397
        self.count += 1
218
398
        self.report_test_start(test)
219
399
        test.number = self.count
220
400
        self._recordTestStartTime()
 
401
        # Make testtools cases give us the real traceback on failure
 
402
        addOnException = getattr(test, "addOnException", None)
 
403
        if addOnException is not None:
 
404
            addOnException(self._record_traceback_from_test)
 
405
        # Only check for thread leaks on bzrlib derived test cases
 
406
        if isinstance(test, TestCase):
 
407
            test.addCleanup(self._check_leaked_threads, test)
 
408
 
 
409
    def stopTest(self, test):
 
410
        super(ExtendedTestResult, self).stopTest(test)
 
411
        # Manually break cycles, means touching various private things but hey
 
412
        getDetails = getattr(test, "getDetails", None)
 
413
        if getDetails is not None:
 
414
            getDetails().clear()
 
415
        _clear__type_equality_funcs(test)
 
416
        self._traceback_from_test = None
 
417
 
 
418
    def startTests(self):
 
419
        self.report_tests_starting()
 
420
        self._active_threads = threading.enumerate()
 
421
 
 
422
    def _check_leaked_threads(self, test):
 
423
        """See if any threads have leaked since last call
 
424
 
 
425
        A sample of live threads is stored in the _active_threads attribute,
 
426
        when this method runs it compares the current live threads and any not
 
427
        in the previous sample are treated as having leaked.
 
428
        """
 
429
        now_active_threads = set(threading.enumerate())
 
430
        threads_leaked = now_active_threads.difference(self._active_threads)
 
431
        if threads_leaked:
 
432
            self._report_thread_leak(test, threads_leaked, now_active_threads)
 
433
            self._tests_leaking_threads_count += 1
 
434
            if self._first_thread_leaker_id is None:
 
435
                self._first_thread_leaker_id = test.id()
 
436
            self._active_threads = now_active_threads
221
437
 
222
438
    def _recordTestStartTime(self):
223
439
        """Record that a test has started."""
224
 
        self._start_time = time.time()
225
 
 
226
 
    def _cleanupLogFile(self, test):
227
 
        # We can only do this if we have one of our TestCases, not if
228
 
        # we have a doctest.
229
 
        setKeepLogfile = getattr(test, 'setKeepLogfile', None)
230
 
        if setKeepLogfile is not None:
231
 
            setKeepLogfile()
 
440
        self._start_datetime = self._now()
232
441
 
233
442
    def addError(self, test, err):
234
 
        self.extractBenchmarkTime(test)
235
 
        self._cleanupLogFile(test)
236
 
        if isinstance(err[1], TestSkipped):
237
 
            return self.addSkipped(test, err)
238
 
        elif isinstance(err[1], UnavailableFeature):
239
 
            return self.addNotSupported(test, err[1].args[0])
240
 
        unittest.TestResult.addError(self, test, err)
 
443
        """Tell result that test finished with an error.
 
444
 
 
445
        Called from the TestCase run() method when the test
 
446
        fails with an unexpected error.
 
447
        """
 
448
        self._post_mortem(self._traceback_from_test)
 
449
        super(ExtendedTestResult, self).addError(test, err)
241
450
        self.error_count += 1
242
451
        self.report_error(test, err)
243
452
        if self.stop_early:
244
453
            self.stop()
245
454
 
246
455
    def addFailure(self, test, err):
247
 
        self._cleanupLogFile(test)
248
 
        self.extractBenchmarkTime(test)
249
 
        if isinstance(err[1], KnownFailure):
250
 
            return self.addKnownFailure(test, err)
251
 
        unittest.TestResult.addFailure(self, test, err)
 
456
        """Tell result that test failed.
 
457
 
 
458
        Called from the TestCase run() method when the test
 
459
        fails because e.g. an assert() method failed.
 
460
        """
 
461
        self._post_mortem(self._traceback_from_test)
 
462
        super(ExtendedTestResult, self).addFailure(test, err)
252
463
        self.failure_count += 1
253
464
        self.report_failure(test, err)
254
465
        if self.stop_early:
255
466
            self.stop()
256
467
 
257
 
    def addKnownFailure(self, test, err):
 
468
    def addSuccess(self, test, details=None):
 
469
        """Tell result that test completed successfully.
 
470
 
 
471
        Called from the TestCase run()
 
472
        """
 
473
        if self._bench_history is not None:
 
474
            benchmark_time = self._extractBenchmarkTime(test, details)
 
475
            if benchmark_time is not None:
 
476
                self._bench_history.write("%s %s\n" % (
 
477
                    self._formatTime(benchmark_time),
 
478
                    test.id()))
 
479
        self.report_success(test)
 
480
        super(ExtendedTestResult, self).addSuccess(test)
 
481
        test._log_contents = ''
 
482
 
 
483
    def addExpectedFailure(self, test, err):
258
484
        self.known_failure_count += 1
259
485
        self.report_known_failure(test, err)
260
486
 
 
487
    def addUnexpectedSuccess(self, test, details=None):
 
488
        """Tell result the test unexpectedly passed, counting as a failure
 
489
 
 
490
        When the minimum version of testtools required becomes 0.9.8 this
 
491
        can be updated to use the new handling there.
 
492
        """
 
493
        super(ExtendedTestResult, self).addFailure(test, details=details)
 
494
        self.failure_count += 1
 
495
        self.report_unexpected_success(test,
 
496
            "".join(details["reason"].iter_text()))
 
497
        if self.stop_early:
 
498
            self.stop()
 
499
 
261
500
    def addNotSupported(self, test, feature):
 
501
        """The test will not be run because of a missing feature.
 
502
        """
 
503
        # this can be called in two different ways: it may be that the
 
504
        # test started running, and then raised (through requireFeature)
 
505
        # UnavailableFeature.  Alternatively this method can be called
 
506
        # while probing for features before running the test code proper; in
 
507
        # that case we will see startTest and stopTest, but the test will
 
508
        # never actually run.
262
509
        self.unsupported.setdefault(str(feature), 0)
263
510
        self.unsupported[str(feature)] += 1
264
511
        self.report_unsupported(test, feature)
265
512
 
266
 
    def addSuccess(self, test):
267
 
        self.extractBenchmarkTime(test)
268
 
        if self._bench_history is not None:
269
 
            if self._benchmarkTime is not None:
270
 
                self._bench_history.write("%s %s\n" % (
271
 
                    self._formatTime(self._benchmarkTime),
272
 
                    test.id()))
273
 
        self.report_success(test)
274
 
        unittest.TestResult.addSuccess(self, test)
275
 
 
276
 
    def addSkipped(self, test, skip_excinfo):
277
 
        self.report_skip(test, skip_excinfo)
278
 
        # seems best to treat this as success from point-of-view of unittest
279
 
        # -- it actually does nothing so it barely matters :)
280
 
        try:
281
 
            test.tearDown()
282
 
        except KeyboardInterrupt:
283
 
            raise
284
 
        except:
285
 
            self.addError(test, test.__exc_info())
286
 
        else:
287
 
            unittest.TestResult.addSuccess(self, test)
288
 
 
289
 
    def printErrorList(self, flavour, errors):
290
 
        for test, err in errors:
291
 
            self.stream.writeln(self.separator1)
292
 
            self.stream.write("%s: " % flavour)
293
 
            if self.use_numbered_dirs:
294
 
                self.stream.write('#%d ' % test.number)
295
 
            self.stream.writeln(self.getDescription(test))
296
 
            if getattr(test, '_get_log', None) is not None:
297
 
                print >>self.stream
298
 
                print >>self.stream, \
299
 
                        ('vvvv[log from %s]' % test.id()).ljust(78,'-')
300
 
                print >>self.stream, test._get_log()
301
 
                print >>self.stream, \
302
 
                        ('^^^^[log from %s]' % test.id()).ljust(78,'-')
303
 
            self.stream.writeln(self.separator2)
304
 
            self.stream.writeln("%s" % err)
305
 
 
306
 
    def finished(self):
307
 
        pass
308
 
 
309
 
    def report_cleaning_up(self):
310
 
        pass
 
513
    def addSkip(self, test, reason):
 
514
        """A test has not run for 'reason'."""
 
515
        self.skip_count += 1
 
516
        self.report_skip(test, reason)
 
517
 
 
518
    def addNotApplicable(self, test, reason):
 
519
        self.not_applicable_count += 1
 
520
        self.report_not_applicable(test, reason)
 
521
 
 
522
    def _count_stored_tests(self):
 
523
        """Count of tests instances kept alive due to not succeeding"""
 
524
        return self.error_count + self.failure_count + self.known_failure_count
 
525
 
 
526
    def _post_mortem(self, tb=None):
 
527
        """Start a PDB post mortem session."""
 
528
        if os.environ.get('BZR_TEST_PDB', None):
 
529
            import pdb
 
530
            pdb.post_mortem(tb)
 
531
 
 
532
    def progress(self, offset, whence):
 
533
        """The test is adjusting the count of tests to run."""
 
534
        if whence == SUBUNIT_SEEK_SET:
 
535
            self.num_tests = offset
 
536
        elif whence == SUBUNIT_SEEK_CUR:
 
537
            self.num_tests += offset
 
538
        else:
 
539
            raise errors.BzrError("Unknown whence %r" % whence)
 
540
 
 
541
    def report_tests_starting(self):
 
542
        """Display information before the test run begins"""
 
543
        if getattr(sys, 'frozen', None) is None:
 
544
            bzr_path = osutils.realpath(sys.argv[0])
 
545
        else:
 
546
            bzr_path = sys.executable
 
547
        self.stream.write(
 
548
            'bzr selftest: %s\n' % (bzr_path,))
 
549
        self.stream.write(
 
550
            '   %s\n' % (
 
551
                    bzrlib.__path__[0],))
 
552
        self.stream.write(
 
553
            '   bzr-%s python-%s %s\n' % (
 
554
                    bzrlib.version_string,
 
555
                    bzrlib._format_version_tuple(sys.version_info),
 
556
                    platform.platform(aliased=1),
 
557
                    ))
 
558
        self.stream.write('\n')
 
559
 
 
560
    def report_test_start(self, test):
 
561
        """Display information on the test just about to be run"""
 
562
 
 
563
    def _report_thread_leak(self, test, leaked_threads, active_threads):
 
564
        """Display information on a test that leaked one or more threads"""
 
565
        # GZ 2010-09-09: A leak summary reported separately from the general
 
566
        #                thread debugging would be nice. Tests under subunit
 
567
        #                need something not using stream, perhaps adding a
 
568
        #                testtools details object would be fitting.
 
569
        if 'threads' in selftest_debug_flags:
 
570
            self.stream.write('%s is leaking, active is now %d\n' %
 
571
                (test.id(), len(active_threads)))
 
572
 
 
573
    def startTestRun(self):
 
574
        self.startTime = time.time()
311
575
 
312
576
    def report_success(self, test):
313
577
        pass
314
578
 
 
579
    def wasStrictlySuccessful(self):
 
580
        if self.unsupported or self.known_failure_count:
 
581
            return False
 
582
        return self.wasSuccessful()
 
583
 
315
584
 
316
585
class TextTestResult(ExtendedTestResult):
317
586
    """Displays progress and results of tests in text form"""
318
587
 
319
588
    def __init__(self, stream, descriptions, verbosity,
320
589
                 bench_history=None,
321
 
                 num_tests=None,
322
590
                 pb=None,
323
 
                 use_numbered_dirs=False,
 
591
                 strict=None,
324
592
                 ):
325
593
        ExtendedTestResult.__init__(self, stream, descriptions, verbosity,
326
 
            bench_history, num_tests, use_numbered_dirs)
327
 
        if pb is None:
328
 
            self.pb = self.ui.nested_progress_bar()
329
 
            self._supplied_pb = False
330
 
        else:
331
 
            self.pb = pb
332
 
            self._supplied_pb = True
 
594
            bench_history, strict)
 
595
        # We no longer pass them around, but just rely on the UIFactory stack
 
596
        # for state
 
597
        if pb is not None:
 
598
            warnings.warn("Passing pb to TextTestResult is deprecated")
 
599
        self.pb = self.ui.nested_progress_bar()
333
600
        self.pb.show_pct = False
334
601
        self.pb.show_spinner = False
335
602
        self.pb.show_eta = False,
336
603
        self.pb.show_count = False
337
604
        self.pb.show_bar = False
338
 
 
339
 
    def report_starting(self):
340
 
        self.pb.update('[test 0/%d] starting...' % (self.num_tests))
 
605
        self.pb.update_latency = 0
 
606
        self.pb.show_transport_activity = False
 
607
 
 
608
    def stopTestRun(self):
 
609
        # called when the tests that are going to run have run
 
610
        self.pb.clear()
 
611
        self.pb.finished()
 
612
        super(TextTestResult, self).stopTestRun()
 
613
 
 
614
    def report_tests_starting(self):
 
615
        super(TextTestResult, self).report_tests_starting()
 
616
        self.pb.update('[test 0/%d] Starting' % (self.num_tests))
341
617
 
342
618
    def _progress_prefix_text(self):
343
 
        a = '[%d' % self.count
344
 
        if self.num_tests is not None:
 
619
        # the longer this text, the less space we have to show the test
 
620
        # name...
 
621
        a = '[%d' % self.count              # total that have been run
 
622
        # tests skipped as known not to be relevant are not important enough
 
623
        # to show here
 
624
        ## if self.skip_count:
 
625
        ##     a += ', %d skip' % self.skip_count
 
626
        ## if self.known_failure_count:
 
627
        ##     a += '+%dX' % self.known_failure_count
 
628
        if self.num_tests:
345
629
            a +='/%d' % self.num_tests
346
 
        a += ' in %ds' % (time.time() - self._overall_start_time)
347
 
        if self.error_count:
348
 
            a += ', %d errors' % self.error_count
349
 
        if self.failure_count:
350
 
            a += ', %d failed' % self.failure_count
351
 
        if self.known_failure_count:
352
 
            a += ', %d known failures' % self.known_failure_count
353
 
        if self.skip_count:
354
 
            a += ', %d skipped' % self.skip_count
355
 
        if self.unsupported:
356
 
            a += ', %d missing features' % len(self.unsupported)
 
630
        a += ' in '
 
631
        runtime = time.time() - self._overall_start_time
 
632
        if runtime >= 60:
 
633
            a += '%dm%ds' % (runtime / 60, runtime % 60)
 
634
        else:
 
635
            a += '%ds' % runtime
 
636
        total_fail_count = self.error_count + self.failure_count
 
637
        if total_fail_count:
 
638
            a += ', %d failed' % total_fail_count
 
639
        # if self.unsupported:
 
640
        #     a += ', %d missing' % len(self.unsupported)
357
641
        a += ']'
358
642
        return a
359
643
 
360
644
    def report_test_start(self, test):
361
 
        self.count += 1
362
645
        self.pb.update(
363
646
                self._progress_prefix_text()
364
 
                + ' ' 
 
647
                + ' '
365
648
                + self._shortened_test_description(test))
366
649
 
367
650
    def _test_description(self, test):
368
 
        if self.use_numbered_dirs:
369
 
            return '#%d %s' % (self.count,
370
 
                               self._shortened_test_description(test))
371
 
        else:
372
 
            return self._shortened_test_description(test)
 
651
        return self._shortened_test_description(test)
373
652
 
374
653
    def report_error(self, test, err):
375
 
        self.pb.note('ERROR: %s\n    %s\n', 
 
654
        self.stream.write('ERROR: %s\n    %s\n' % (
376
655
            self._test_description(test),
377
656
            err[1],
378
 
            )
 
657
            ))
379
658
 
380
659
    def report_failure(self, test, err):
381
 
        self.pb.note('FAIL: %s\n    %s\n', 
 
660
        self.stream.write('FAIL: %s\n    %s\n' % (
382
661
            self._test_description(test),
383
662
            err[1],
384
 
            )
 
663
            ))
385
664
 
386
665
    def report_known_failure(self, test, err):
387
 
        self.pb.note('XFAIL: %s\n%s\n',
388
 
            self._test_description(test), err[1])
389
 
 
390
 
    def report_skip(self, test, skip_excinfo):
391
 
        self.skip_count += 1
392
 
        if False:
393
 
            # at the moment these are mostly not things we can fix
394
 
            # and so they just produce stipple; use the verbose reporter
395
 
            # to see them.
396
 
            if False:
397
 
                # show test and reason for skip
398
 
                self.pb.note('SKIP: %s\n    %s\n', 
399
 
                    self._shortened_test_description(test),
400
 
                    skip_excinfo[1])
401
 
            else:
402
 
                # since the class name was left behind in the still-visible
403
 
                # progress bar...
404
 
                self.pb.note('SKIP: %s', skip_excinfo[1])
 
666
        pass
 
667
 
 
668
    def report_unexpected_success(self, test, reason):
 
669
        self.stream.write('FAIL: %s\n    %s: %s\n' % (
 
670
            self._test_description(test),
 
671
            "Unexpected success. Should have failed",
 
672
            reason,
 
673
            ))
 
674
 
 
675
    def report_skip(self, test, reason):
 
676
        pass
 
677
 
 
678
    def report_not_applicable(self, test, reason):
 
679
        pass
405
680
 
406
681
    def report_unsupported(self, test, feature):
407
682
        """test cannot be run because feature is missing."""
408
 
                  
409
 
    def report_cleaning_up(self):
410
 
        self.pb.update('cleaning up...')
411
 
 
412
 
    def finished(self):
413
 
        if not self._supplied_pb:
414
 
            self.pb.finished()
415
683
 
416
684
 
417
685
class VerboseTestResult(ExtendedTestResult):
425
693
            result = a_string
426
694
        return result.ljust(final_width)
427
695
 
428
 
    def report_starting(self):
 
696
    def report_tests_starting(self):
429
697
        self.stream.write('running %d tests...\n' % self.num_tests)
 
698
        super(VerboseTestResult, self).report_tests_starting()
430
699
 
431
700
    def report_test_start(self, test):
432
 
        self.count += 1
433
701
        name = self._shortened_test_description(test)
434
 
        # width needs space for 6 char status, plus 1 for slash, plus 2 10-char
435
 
        # numbers, plus a trailing blank
436
 
        # when NUMBERED_DIRS: plus 5 chars on test number, plus 1 char on space
437
 
        if self.use_numbered_dirs:
438
 
            self.stream.write('%5d ' % self.count)
439
 
            self.stream.write(self._ellipsize_to_right(name,
440
 
                                osutils.terminal_width()-36))
 
702
        width = osutils.terminal_width()
 
703
        if width is not None:
 
704
            # width needs space for 6 char status, plus 1 for slash, plus an
 
705
            # 11-char time string, plus a trailing blank
 
706
            # when NUMBERED_DIRS: plus 5 chars on test number, plus 1 char on
 
707
            # space
 
708
            self.stream.write(self._ellipsize_to_right(name, width-18))
441
709
        else:
442
 
            self.stream.write(self._ellipsize_to_right(name,
443
 
                                osutils.terminal_width()-30))
 
710
            self.stream.write(name)
444
711
        self.stream.flush()
445
712
 
446
713
    def _error_summary(self, err):
447
714
        indent = ' ' * 4
448
 
        if self.use_numbered_dirs:
449
 
            indent += ' ' * 6
450
715
        return '%s%s' % (indent, err[1])
451
716
 
452
717
    def report_error(self, test, err):
453
 
        self.stream.writeln('ERROR %s\n%s'
454
 
                % (self._testTimeString(),
 
718
        self.stream.write('ERROR %s\n%s\n'
 
719
                % (self._testTimeString(test),
455
720
                   self._error_summary(err)))
456
721
 
457
722
    def report_failure(self, test, err):
458
 
        self.stream.writeln(' FAIL %s\n%s'
459
 
                % (self._testTimeString(),
 
723
        self.stream.write(' FAIL %s\n%s\n'
 
724
                % (self._testTimeString(test),
460
725
                   self._error_summary(err)))
461
726
 
462
727
    def report_known_failure(self, test, err):
463
 
        self.stream.writeln('XFAIL %s\n%s'
464
 
                % (self._testTimeString(),
 
728
        self.stream.write('XFAIL %s\n%s\n'
 
729
                % (self._testTimeString(test),
465
730
                   self._error_summary(err)))
466
731
 
 
732
    def report_unexpected_success(self, test, reason):
 
733
        self.stream.write(' FAIL %s\n%s: %s\n'
 
734
                % (self._testTimeString(test),
 
735
                   "Unexpected success. Should have failed",
 
736
                   reason))
 
737
 
467
738
    def report_success(self, test):
468
 
        self.stream.writeln('   OK %s' % self._testTimeString())
 
739
        self.stream.write('   OK %s\n' % self._testTimeString(test))
469
740
        for bench_called, stats in getattr(test, '_benchcalls', []):
470
 
            self.stream.writeln('LSProf output for %s(%s, %s)' % bench_called)
 
741
            self.stream.write('LSProf output for %s(%s, %s)\n' % bench_called)
471
742
            stats.pprint(file=self.stream)
472
743
        # flush the stream so that we get smooth output. This verbose mode is
473
744
        # used to show the output in PQM.
474
745
        self.stream.flush()
475
746
 
476
 
    def report_skip(self, test, skip_excinfo):
477
 
        self.skip_count += 1
478
 
        self.stream.writeln(' SKIP %s\n%s'
479
 
                % (self._testTimeString(),
480
 
                   self._error_summary(skip_excinfo)))
 
747
    def report_skip(self, test, reason):
 
748
        self.stream.write(' SKIP %s\n%s\n'
 
749
                % (self._testTimeString(test), reason))
 
750
 
 
751
    def report_not_applicable(self, test, reason):
 
752
        self.stream.write('  N/A %s\n    %s\n'
 
753
                % (self._testTimeString(test), reason))
481
754
 
482
755
    def report_unsupported(self, test, feature):
483
756
        """test cannot be run because feature is missing."""
484
 
        self.stream.writeln("NODEP %s\n    The feature '%s' is not available."
485
 
                %(self._testTimeString(), feature))
486
 
                  
 
757
        self.stream.write("NODEP %s\n    The feature '%s' is not available.\n"
 
758
                %(self._testTimeString(test), feature))
487
759
 
488
760
 
489
761
class TextTestRunner(object):
493
765
                 stream=sys.stderr,
494
766
                 descriptions=0,
495
767
                 verbosity=1,
496
 
                 keep_output=False,
497
768
                 bench_history=None,
498
 
                 use_numbered_dirs=False,
 
769
                 strict=False,
 
770
                 result_decorators=None,
499
771
                 ):
500
 
        self.stream = unittest._WritelnDecorator(stream)
 
772
        """Create a TextTestRunner.
 
773
 
 
774
        :param result_decorators: An optional list of decorators to apply
 
775
            to the result object being used by the runner. Decorators are
 
776
            applied left to right - the first element in the list is the 
 
777
            innermost decorator.
 
778
        """
 
779
        # stream may know claim to know to write unicode strings, but in older
 
780
        # pythons this goes sufficiently wrong that it is a bad idea. (
 
781
        # specifically a built in file with encoding 'UTF-8' will still try
 
782
        # to encode using ascii.
 
783
        new_encoding = osutils.get_terminal_encoding()
 
784
        codec = codecs.lookup(new_encoding)
 
785
        if type(codec) is tuple:
 
786
            # Python 2.4
 
787
            encode = codec[0]
 
788
        else:
 
789
            encode = codec.encode
 
790
        # GZ 2010-09-08: Really we don't want to be writing arbitrary bytes,
 
791
        #                so should swap to the plain codecs.StreamWriter
 
792
        stream = osutils.UnicodeOrBytesToBytesWriter(encode, stream,
 
793
            "backslashreplace")
 
794
        stream.encoding = new_encoding
 
795
        self.stream = stream
501
796
        self.descriptions = descriptions
502
797
        self.verbosity = verbosity
503
 
        self.keep_output = keep_output
504
798
        self._bench_history = bench_history
505
 
        self.use_numbered_dirs = use_numbered_dirs
 
799
        self._strict = strict
 
800
        self._result_decorators = result_decorators or []
506
801
 
507
802
    def run(self, test):
508
803
        "Run the given test case or test suite."
509
 
        startTime = time.time()
510
804
        if self.verbosity == 1:
511
805
            result_class = TextTestResult
512
806
        elif self.verbosity >= 2:
513
807
            result_class = VerboseTestResult
514
 
        result = result_class(self.stream,
 
808
        original_result = result_class(self.stream,
515
809
                              self.descriptions,
516
810
                              self.verbosity,
517
811
                              bench_history=self._bench_history,
518
 
                              num_tests=test.countTestCases(),
519
 
                              use_numbered_dirs=self.use_numbered_dirs,
 
812
                              strict=self._strict,
520
813
                              )
521
 
        result.stop_early = self.stop_on_failure
522
 
        result.report_starting()
523
 
        test.run(result)
524
 
        stopTime = time.time()
525
 
        timeTaken = stopTime - startTime
526
 
        result.printErrors()
527
 
        self.stream.writeln(result.separator2)
528
 
        run = result.testsRun
529
 
        self.stream.writeln("Ran %d test%s in %.3fs" %
530
 
                            (run, run != 1 and "s" or "", timeTaken))
531
 
        self.stream.writeln()
532
 
        if not result.wasSuccessful():
533
 
            self.stream.write("FAILED (")
534
 
            failed, errored = map(len, (result.failures, result.errors))
535
 
            if failed:
536
 
                self.stream.write("failures=%d" % failed)
537
 
            if errored:
538
 
                if failed: self.stream.write(", ")
539
 
                self.stream.write("errors=%d" % errored)
540
 
            if result.known_failure_count:
541
 
                if failed or errored: self.stream.write(", ")
542
 
                self.stream.write("known_failure_count=%d" %
543
 
                    result.known_failure_count)
544
 
            self.stream.writeln(")")
545
 
        else:
546
 
            if result.known_failure_count:
547
 
                self.stream.writeln("OK (known_failures=%d)" %
548
 
                    result.known_failure_count)
549
 
            else:
550
 
                self.stream.writeln("OK")
551
 
        if result.skip_count > 0:
552
 
            skipped = result.skip_count
553
 
            self.stream.writeln('%d test%s skipped' %
554
 
                                (skipped, skipped != 1 and "s" or ""))
555
 
        if result.unsupported:
556
 
            for feature, count in sorted(result.unsupported.items()):
557
 
                self.stream.writeln("Missing feature '%s' skipped %d tests." %
558
 
                    (feature, count))
559
 
        result.report_cleaning_up()
560
 
        # This is still a little bogus, 
561
 
        # but only a little. Folk not using our testrunner will
562
 
        # have to delete their temp directories themselves.
563
 
        test_root = TestCaseWithMemoryTransport.TEST_ROOT
564
 
        if result.wasSuccessful() or not self.keep_output:
565
 
            if test_root is not None:
566
 
                # If LANG=C we probably have created some bogus paths
567
 
                # which rmtree(unicode) will fail to delete
568
 
                # so make sure we are using rmtree(str) to delete everything
569
 
                # except on win32, where rmtree(str) will fail
570
 
                # since it doesn't have the property of byte-stream paths
571
 
                # (they are either ascii or mbcs)
572
 
                if sys.platform == 'win32':
573
 
                    # make sure we are using the unicode win32 api
574
 
                    test_root = unicode(test_root)
575
 
                else:
576
 
                    test_root = test_root.encode(
577
 
                        sys.getfilesystemencoding())
578
 
                _rmtree_temp_dir(test_root)
579
 
        else:
580
 
            note("Failed tests working directories are in '%s'\n", test_root)
581
 
        TestCaseWithMemoryTransport.TEST_ROOT = None
582
 
        result.finished()
583
 
        return result
 
814
        # Signal to result objects that look at stop early policy to stop,
 
815
        original_result.stop_early = self.stop_on_failure
 
816
        result = original_result
 
817
        for decorator in self._result_decorators:
 
818
            result = decorator(result)
 
819
            result.stop_early = self.stop_on_failure
 
820
        result.startTestRun()
 
821
        try:
 
822
            test.run(result)
 
823
        finally:
 
824
            result.stopTestRun()
 
825
        # higher level code uses our extended protocol to determine
 
826
        # what exit code to give.
 
827
        return original_result
584
828
 
585
829
 
586
830
def iter_suite_tests(suite):
587
831
    """Return all tests in a suite, recursing through nested suites"""
588
 
    for item in suite._tests:
589
 
        if isinstance(item, unittest.TestCase):
590
 
            yield item
591
 
        elif isinstance(item, unittest.TestSuite):
 
832
    if isinstance(suite, unittest.TestCase):
 
833
        yield suite
 
834
    elif isinstance(suite, unittest.TestSuite):
 
835
        for item in suite:
592
836
            for r in iter_suite_tests(item):
593
837
                yield r
594
 
        else:
595
 
            raise Exception('unknown object %r inside test suite %r'
596
 
                            % (item, suite))
597
 
 
598
 
 
599
 
class TestSkipped(Exception):
600
 
    """Indicates that a test was intentionally skipped, rather than failing."""
601
 
 
602
 
 
603
 
class KnownFailure(AssertionError):
604
 
    """Indicates that a test failed in a precisely expected manner.
605
 
 
606
 
    Such failures dont block the whole test suite from passing because they are
607
 
    indicators of partially completed code or of future work. We have an
608
 
    explicit error for them so that we can ensure that they are always visible:
609
 
    KnownFailures are always shown in the output of bzr selftest.
 
838
    else:
 
839
        raise Exception('unknown type %r for object %r'
 
840
                        % (type(suite), suite))
 
841
 
 
842
 
 
843
TestSkipped = testtools.testcase.TestSkipped
 
844
 
 
845
 
 
846
class TestNotApplicable(TestSkipped):
 
847
    """A test is not applicable to the situation where it was run.
 
848
 
 
849
    This is only normally raised by parameterized tests, if they find that
 
850
    the instance they're constructed upon does not support one aspect
 
851
    of its interface.
610
852
    """
611
853
 
612
854
 
 
855
# traceback._some_str fails to format exceptions that have the default
 
856
# __str__ which does an implicit ascii conversion. However, repr() on those
 
857
# objects works, for all that its not quite what the doctor may have ordered.
 
858
def _clever_some_str(value):
 
859
    try:
 
860
        return str(value)
 
861
    except:
 
862
        try:
 
863
            return repr(value).replace('\\n', '\n')
 
864
        except:
 
865
            return '<unprintable %s object>' % type(value).__name__
 
866
 
 
867
traceback._some_str = _clever_some_str
 
868
 
 
869
 
 
870
# deprecated - use self.knownFailure(), or self.expectFailure.
 
871
KnownFailure = testtools.testcase._ExpectedFailure
 
872
 
 
873
 
613
874
class UnavailableFeature(Exception):
614
875
    """A feature required for this test was not available.
615
876
 
 
877
    This can be considered a specialised form of SkippedTest.
 
878
 
616
879
    The feature should be used to construct the exception.
617
880
    """
618
881
 
619
882
 
620
 
class CommandFailed(Exception):
621
 
    pass
622
 
 
623
 
 
624
883
class StringIOWrapper(object):
625
884
    """A wrapper around cStringIO which just adds an encoding attribute.
626
 
    
 
885
 
627
886
    Internally we can check sys.stdout to see what the output encoding
628
887
    should be. However, cStringIO has no encoding attribute that we can
629
888
    set. So we wrap it instead.
647
906
            return setattr(self._cstring, name, val)
648
907
 
649
908
 
650
 
class TestUIFactory(ui.CLIUIFactory):
 
909
class TestUIFactory(TextUIFactory):
651
910
    """A UI Factory for testing.
652
911
 
653
912
    Hide the progress bar but emit note()s.
654
913
    Redirect stdin.
655
914
    Allows get_password to be tested without real tty attached.
 
915
 
 
916
    See also CannedInputUIFactory which lets you provide programmatic input in
 
917
    a structured way.
656
918
    """
 
919
    # TODO: Capture progress events at the model level and allow them to be
 
920
    # observed by tests that care.
 
921
    #
 
922
    # XXX: Should probably unify more with CannedInputUIFactory or a
 
923
    # particular configuration of TextUIFactory, or otherwise have a clearer
 
924
    # idea of how they're supposed to be different.
 
925
    # See https://bugs.launchpad.net/bzr/+bug/408213
657
926
 
658
 
    def __init__(self,
659
 
                 stdout=None,
660
 
                 stderr=None,
661
 
                 stdin=None):
662
 
        super(TestUIFactory, self).__init__()
 
927
    def __init__(self, stdout=None, stderr=None, stdin=None):
663
928
        if stdin is not None:
664
929
            # We use a StringIOWrapper to be able to test various
665
930
            # encodings, but the user is still responsible to
666
931
            # encode the string and to set the encoding attribute
667
932
            # of StringIOWrapper.
668
 
            self.stdin = StringIOWrapper(stdin)
669
 
        if stdout is None:
670
 
            self.stdout = sys.stdout
671
 
        else:
672
 
            self.stdout = stdout
673
 
        if stderr is None:
674
 
            self.stderr = sys.stderr
675
 
        else:
676
 
            self.stderr = stderr
677
 
 
678
 
    def clear(self):
679
 
        """See progress.ProgressBar.clear()."""
680
 
 
681
 
    def clear_term(self):
682
 
        """See progress.ProgressBar.clear_term()."""
683
 
 
684
 
    def clear_term(self):
685
 
        """See progress.ProgressBar.clear_term()."""
686
 
 
687
 
    def finished(self):
688
 
        """See progress.ProgressBar.finished()."""
689
 
 
690
 
    def note(self, fmt_string, *args, **kwargs):
691
 
        """See progress.ProgressBar.note()."""
692
 
        self.stdout.write((fmt_string + "\n") % args)
693
 
 
694
 
    def progress_bar(self):
695
 
        return self
696
 
 
697
 
    def nested_progress_bar(self):
698
 
        return self
699
 
 
700
 
    def update(self, message, count=None, total=None):
701
 
        """See progress.ProgressBar.update()."""
702
 
 
703
 
    def get_non_echoed_password(self, prompt):
 
933
            stdin = StringIOWrapper(stdin)
 
934
        super(TestUIFactory, self).__init__(stdin, stdout, stderr)
 
935
 
 
936
    def get_non_echoed_password(self):
704
937
        """Get password from stdin without trying to handle the echo mode"""
705
 
        if prompt:
706
 
            self.stdout.write(prompt)
707
938
        password = self.stdin.readline()
708
939
        if not password:
709
940
            raise EOFError
711
942
            password = password[:-1]
712
943
        return password
713
944
 
714
 
 
715
 
class TestCase(unittest.TestCase):
 
945
    def make_progress_view(self):
 
946
        return NullProgressView()
 
947
 
 
948
 
 
949
def isolated_doctest_setUp(test):
 
950
    override_os_environ(test)
 
951
 
 
952
 
 
953
def isolated_doctest_tearDown(test):
 
954
    restore_os_environ(test)
 
955
 
 
956
 
 
957
def IsolatedDocTestSuite(*args, **kwargs):
 
958
    """Overrides doctest.DocTestSuite to handle isolation.
 
959
 
 
960
    The method is really a factory and users are expected to use it as such.
 
961
    """
 
962
 
 
963
    kwargs['setUp'] = isolated_doctest_setUp
 
964
    kwargs['tearDown'] = isolated_doctest_tearDown
 
965
    return doctest.DocTestSuite(*args, **kwargs)
 
966
 
 
967
 
 
968
class TestCase(testtools.TestCase):
716
969
    """Base class for bzr unit tests.
717
 
    
718
 
    Tests that need access to disk resources should subclass 
 
970
 
 
971
    Tests that need access to disk resources should subclass
719
972
    TestCaseInTempDir not TestCase.
720
973
 
721
974
    Error and debug log messages are redirected from their usual
723
976
    retrieved by _get_log().  We use a real OS file, not an in-memory object,
724
977
    so that it can also capture file IO.  When the test completes this file
725
978
    is read into memory and removed from disk.
726
 
       
 
979
 
727
980
    There are also convenience functions to invoke bzr's command-line
728
981
    routine, and to build and check bzr trees.
729
 
   
 
982
 
730
983
    In addition to the usual method of overriding tearDown(), this class also
731
 
    allows subclasses to register functions into the _cleanups list, which is
 
984
    allows subclasses to register cleanup functions via addCleanup, which are
732
985
    run in order as the object is torn down.  It's less likely this will be
733
986
    accidentally overlooked.
734
987
    """
735
988
 
736
 
    _log_file_name = None
737
 
    _log_contents = ''
738
 
    _keep_log_file = False
 
989
    _log_file = None
739
990
    # record lsprof data when performing benchmark calls.
740
991
    _gather_lsprof_in_benchmarks = False
741
992
 
742
993
    def __init__(self, methodName='testMethod'):
743
994
        super(TestCase, self).__init__(methodName)
744
 
        self._cleanups = []
 
995
        self._directory_isolation = True
 
996
        self.exception_handlers.insert(0,
 
997
            (UnavailableFeature, self._do_unsupported_or_skip))
 
998
        self.exception_handlers.insert(0,
 
999
            (TestNotApplicable, self._do_not_applicable))
745
1000
 
746
1001
    def setUp(self):
747
 
        unittest.TestCase.setUp(self)
 
1002
        super(TestCase, self).setUp()
 
1003
 
 
1004
        timeout = config.GlobalStack().get('selftest.timeout')
 
1005
        if timeout:
 
1006
            timeout_fixture = fixtures.TimeoutFixture(timeout)
 
1007
            timeout_fixture.setUp()
 
1008
            self.addCleanup(timeout_fixture.cleanUp)
 
1009
 
 
1010
        for feature in getattr(self, '_test_needs_features', []):
 
1011
            self.requireFeature(feature)
748
1012
        self._cleanEnvironment()
749
 
        bzrlib.trace.disable_default_logging()
 
1013
 
 
1014
        if bzrlib.global_state is not None:
 
1015
            self.overrideAttr(bzrlib.global_state, 'cmdline_overrides',
 
1016
                              config.CommandLineStore())
 
1017
 
750
1018
        self._silenceUI()
751
1019
        self._startLogFile()
752
1020
        self._benchcalls = []
753
1021
        self._benchtime = None
754
1022
        self._clear_hooks()
 
1023
        self._track_transports()
 
1024
        self._track_locks()
 
1025
        self._clear_debug_flags()
 
1026
        # Isolate global verbosity level, to make sure it's reproducible
 
1027
        # between tests.  We should get rid of this altogether: bug 656694. --
 
1028
        # mbp 20101008
 
1029
        self.overrideAttr(bzrlib.trace, '_verbosity_level', 0)
 
1030
        # Isolate config option expansion until its default value for bzrlib is
 
1031
        # settled on or a the FIXME associated with _get_expand_default_value
 
1032
        # is addressed -- vila 20110219
 
1033
        self.overrideAttr(config, '_expand_default_value', None)
 
1034
        self._log_files = set()
 
1035
        # Each key in the ``_counters`` dict holds a value for a different
 
1036
        # counter. When the test ends, addDetail() should be used to output the
 
1037
        # counter values. This happens in install_counter_hook().
 
1038
        self._counters = {}
 
1039
        if 'config_stats' in selftest_debug_flags:
 
1040
            self._install_config_stats_hooks()
 
1041
        # Do not use i18n for tests (unless the test reverses this)
 
1042
        i18n.disable_i18n()
 
1043
 
 
1044
    def debug(self):
 
1045
        # debug a frame up.
 
1046
        import pdb
 
1047
        # The sys preserved stdin/stdout should allow blackbox tests debugging
 
1048
        pdb.Pdb(stdin=sys.__stdin__, stdout=sys.__stdout__
 
1049
                ).set_trace(sys._getframe().f_back)
 
1050
 
 
1051
    def discardDetail(self, name):
 
1052
        """Extend the addDetail, getDetails api so we can remove a detail.
 
1053
 
 
1054
        eg. bzr always adds the 'log' detail at startup, but we don't want to
 
1055
        include it for skipped, xfail, etc tests.
 
1056
 
 
1057
        It is safe to call this for a detail that doesn't exist, in case this
 
1058
        gets called multiple times.
 
1059
        """
 
1060
        # We cheat. details is stored in __details which means we shouldn't
 
1061
        # touch it. but getDetails() returns the dict directly, so we can
 
1062
        # mutate it.
 
1063
        details = self.getDetails()
 
1064
        if name in details:
 
1065
            del details[name]
 
1066
 
 
1067
    def install_counter_hook(self, hooks, name, counter_name=None):
 
1068
        """Install a counting hook.
 
1069
 
 
1070
        Any hook can be counted as long as it doesn't need to return a value.
 
1071
 
 
1072
        :param hooks: Where the hook should be installed.
 
1073
 
 
1074
        :param name: The hook name that will be counted.
 
1075
 
 
1076
        :param counter_name: The counter identifier in ``_counters``, defaults
 
1077
            to ``name``.
 
1078
        """
 
1079
        _counters = self._counters # Avoid closing over self
 
1080
        if counter_name is None:
 
1081
            counter_name = name
 
1082
        if _counters.has_key(counter_name):
 
1083
            raise AssertionError('%s is already used as a counter name'
 
1084
                                  % (counter_name,))
 
1085
        _counters[counter_name] = 0
 
1086
        self.addDetail(counter_name, content.Content(content.UTF8_TEXT,
 
1087
            lambda: ['%d' % (_counters[counter_name],)]))
 
1088
        def increment_counter(*args, **kwargs):
 
1089
            _counters[counter_name] += 1
 
1090
        label = 'count %s calls' % (counter_name,)
 
1091
        hooks.install_named_hook(name, increment_counter, label)
 
1092
        self.addCleanup(hooks.uninstall_named_hook, name, label)
 
1093
 
 
1094
    def _install_config_stats_hooks(self):
 
1095
        """Install config hooks to count hook calls.
 
1096
 
 
1097
        """
 
1098
        for hook_name in ('get', 'set', 'remove', 'load', 'save'):
 
1099
            self.install_counter_hook(config.ConfigHooks, hook_name,
 
1100
                                       'config.%s' % (hook_name,))
 
1101
 
 
1102
        # The OldConfigHooks are private and need special handling to protect
 
1103
        # against recursive tests (tests that run other tests), so we just do
 
1104
        # manually what registering them into _builtin_known_hooks will provide
 
1105
        # us.
 
1106
        self.overrideAttr(config, 'OldConfigHooks', config._OldConfigHooks())
 
1107
        for hook_name in ('get', 'set', 'remove', 'load', 'save'):
 
1108
            self.install_counter_hook(config.OldConfigHooks, hook_name,
 
1109
                                      'old_config.%s' % (hook_name,))
 
1110
 
 
1111
    def _clear_debug_flags(self):
 
1112
        """Prevent externally set debug flags affecting tests.
 
1113
 
 
1114
        Tests that want to use debug flags can just set them in the
 
1115
        debug_flags set during setup/teardown.
 
1116
        """
 
1117
        # Start with a copy of the current debug flags we can safely modify.
 
1118
        self.overrideAttr(debug, 'debug_flags', set(debug.debug_flags))
 
1119
        if 'allow_debug' not in selftest_debug_flags:
 
1120
            debug.debug_flags.clear()
 
1121
        if 'disable_lock_checks' not in selftest_debug_flags:
 
1122
            debug.debug_flags.add('strict_locks')
755
1123
 
756
1124
    def _clear_hooks(self):
757
1125
        # prevent hooks affecting tests
758
 
        import bzrlib.branch
759
 
        import bzrlib.smart.server
760
 
        self._preserved_hooks = {
761
 
            bzrlib.branch.Branch: bzrlib.branch.Branch.hooks,
762
 
            bzrlib.smart.server.SmartTCPServer: bzrlib.smart.server.SmartTCPServer.hooks,
763
 
            }
 
1126
        known_hooks = hooks.known_hooks
 
1127
        self._preserved_hooks = {}
 
1128
        for key, (parent, name) in known_hooks.iter_parent_objects():
 
1129
            current_hooks = getattr(parent, name)
 
1130
            self._preserved_hooks[parent] = (name, current_hooks)
 
1131
        self._preserved_lazy_hooks = hooks._lazy_hooks
 
1132
        hooks._lazy_hooks = {}
764
1133
        self.addCleanup(self._restoreHooks)
765
 
        # this list of hooks must be kept in sync with the defaults
766
 
        # in branch.py
767
 
        bzrlib.branch.Branch.hooks = bzrlib.branch.BranchHooks()
768
 
        bzrlib.smart.server.SmartTCPServer.hooks = \
769
 
            bzrlib.smart.server.SmartServerHooks()
 
1134
        for key, (parent, name) in known_hooks.iter_parent_objects():
 
1135
            factory = known_hooks.get(key)
 
1136
            setattr(parent, name, factory())
 
1137
        # this hook should always be installed
 
1138
        request._install_hook()
 
1139
 
 
1140
    def disable_directory_isolation(self):
 
1141
        """Turn off directory isolation checks."""
 
1142
        self._directory_isolation = False
 
1143
 
 
1144
    def enable_directory_isolation(self):
 
1145
        """Enable directory isolation checks."""
 
1146
        self._directory_isolation = True
770
1147
 
771
1148
    def _silenceUI(self):
772
1149
        """Turn off UI for duration of test"""
773
1150
        # by default the UI is off; tests can turn it on if they want it.
774
 
        saved = ui.ui_factory
775
 
        def _restore():
776
 
            ui.ui_factory = saved
777
 
        ui.ui_factory = ui.SilentUIFactory()
778
 
        self.addCleanup(_restore)
 
1151
        self.overrideAttr(ui, 'ui_factory', ui.SilentUIFactory())
 
1152
 
 
1153
    def _check_locks(self):
 
1154
        """Check that all lock take/release actions have been paired."""
 
1155
        # We always check for mismatched locks. If a mismatch is found, we
 
1156
        # fail unless -Edisable_lock_checks is supplied to selftest, in which
 
1157
        # case we just print a warning.
 
1158
        # unhook:
 
1159
        acquired_locks = [lock for action, lock in self._lock_actions
 
1160
                          if action == 'acquired']
 
1161
        released_locks = [lock for action, lock in self._lock_actions
 
1162
                          if action == 'released']
 
1163
        broken_locks = [lock for action, lock in self._lock_actions
 
1164
                        if action == 'broken']
 
1165
        # trivially, given the tests for lock acquistion and release, if we
 
1166
        # have as many in each list, it should be ok. Some lock tests also
 
1167
        # break some locks on purpose and should be taken into account by
 
1168
        # considering that breaking a lock is just a dirty way of releasing it.
 
1169
        if len(acquired_locks) != (len(released_locks) + len(broken_locks)):
 
1170
            message = (
 
1171
                'Different number of acquired and '
 
1172
                'released or broken locks.\n'
 
1173
                'acquired=%s\n'
 
1174
                'released=%s\n'
 
1175
                'broken=%s\n' %
 
1176
                (acquired_locks, released_locks, broken_locks))
 
1177
            if not self._lock_check_thorough:
 
1178
                # Rather than fail, just warn
 
1179
                print "Broken test %s: %s" % (self, message)
 
1180
                return
 
1181
            self.fail(message)
 
1182
 
 
1183
    def _track_locks(self):
 
1184
        """Track lock activity during tests."""
 
1185
        self._lock_actions = []
 
1186
        if 'disable_lock_checks' in selftest_debug_flags:
 
1187
            self._lock_check_thorough = False
 
1188
        else:
 
1189
            self._lock_check_thorough = True
 
1190
 
 
1191
        self.addCleanup(self._check_locks)
 
1192
        _mod_lock.Lock.hooks.install_named_hook('lock_acquired',
 
1193
                                                self._lock_acquired, None)
 
1194
        _mod_lock.Lock.hooks.install_named_hook('lock_released',
 
1195
                                                self._lock_released, None)
 
1196
        _mod_lock.Lock.hooks.install_named_hook('lock_broken',
 
1197
                                                self._lock_broken, None)
 
1198
 
 
1199
    def _lock_acquired(self, result):
 
1200
        self._lock_actions.append(('acquired', result))
 
1201
 
 
1202
    def _lock_released(self, result):
 
1203
        self._lock_actions.append(('released', result))
 
1204
 
 
1205
    def _lock_broken(self, result):
 
1206
        self._lock_actions.append(('broken', result))
 
1207
 
 
1208
    def permit_dir(self, name):
 
1209
        """Permit a directory to be used by this test. See permit_url."""
 
1210
        name_transport = _mod_transport.get_transport_from_path(name)
 
1211
        self.permit_url(name)
 
1212
        self.permit_url(name_transport.base)
 
1213
 
 
1214
    def permit_url(self, url):
 
1215
        """Declare that url is an ok url to use in this test.
 
1216
        
 
1217
        Do this for memory transports, temporary test directory etc.
 
1218
        
 
1219
        Do not do this for the current working directory, /tmp, or any other
 
1220
        preexisting non isolated url.
 
1221
        """
 
1222
        if not url.endswith('/'):
 
1223
            url += '/'
 
1224
        self._bzr_selftest_roots.append(url)
 
1225
 
 
1226
    def permit_source_tree_branch_repo(self):
 
1227
        """Permit the source tree bzr is running from to be opened.
 
1228
 
 
1229
        Some code such as bzrlib.version attempts to read from the bzr branch
 
1230
        that bzr is executing from (if any). This method permits that directory
 
1231
        to be used in the test suite.
 
1232
        """
 
1233
        path = self.get_source_path()
 
1234
        self.record_directory_isolation()
 
1235
        try:
 
1236
            try:
 
1237
                workingtree.WorkingTree.open(path)
 
1238
            except (errors.NotBranchError, errors.NoWorkingTree):
 
1239
                raise TestSkipped('Needs a working tree of bzr sources')
 
1240
        finally:
 
1241
            self.enable_directory_isolation()
 
1242
 
 
1243
    def _preopen_isolate_transport(self, transport):
 
1244
        """Check that all transport openings are done in the test work area."""
 
1245
        while isinstance(transport, pathfilter.PathFilteringTransport):
 
1246
            # Unwrap pathfiltered transports
 
1247
            transport = transport.server.backing_transport.clone(
 
1248
                transport._filter('.'))
 
1249
        url = transport.base
 
1250
        # ReadonlySmartTCPServer_for_testing decorates the backing transport
 
1251
        # urls it is given by prepending readonly+. This is appropriate as the
 
1252
        # client shouldn't know that the server is readonly (or not readonly).
 
1253
        # We could register all servers twice, with readonly+ prepending, but
 
1254
        # that makes for a long list; this is about the same but easier to
 
1255
        # read.
 
1256
        if url.startswith('readonly+'):
 
1257
            url = url[len('readonly+'):]
 
1258
        self._preopen_isolate_url(url)
 
1259
 
 
1260
    def _preopen_isolate_url(self, url):
 
1261
        if not self._directory_isolation:
 
1262
            return
 
1263
        if self._directory_isolation == 'record':
 
1264
            self._bzr_selftest_roots.append(url)
 
1265
            return
 
1266
        # This prevents all transports, including e.g. sftp ones backed on disk
 
1267
        # from working unless they are explicitly granted permission. We then
 
1268
        # depend on the code that sets up test transports to check that they are
 
1269
        # appropriately isolated and enable their use by calling
 
1270
        # self.permit_transport()
 
1271
        if not osutils.is_inside_any(self._bzr_selftest_roots, url):
 
1272
            raise errors.BzrError("Attempt to escape test isolation: %r %r"
 
1273
                % (url, self._bzr_selftest_roots))
 
1274
 
 
1275
    def record_directory_isolation(self):
 
1276
        """Gather accessed directories to permit later access.
 
1277
        
 
1278
        This is used for tests that access the branch bzr is running from.
 
1279
        """
 
1280
        self._directory_isolation = "record"
 
1281
 
 
1282
    def start_server(self, transport_server, backing_server=None):
 
1283
        """Start transport_server for this test.
 
1284
 
 
1285
        This starts the server, registers a cleanup for it and permits the
 
1286
        server's urls to be used.
 
1287
        """
 
1288
        if backing_server is None:
 
1289
            transport_server.start_server()
 
1290
        else:
 
1291
            transport_server.start_server(backing_server)
 
1292
        self.addCleanup(transport_server.stop_server)
 
1293
        # Obtain a real transport because if the server supplies a password, it
 
1294
        # will be hidden from the base on the client side.
 
1295
        t = _mod_transport.get_transport_from_url(transport_server.get_url())
 
1296
        # Some transport servers effectively chroot the backing transport;
 
1297
        # others like SFTPServer don't - users of the transport can walk up the
 
1298
        # transport to read the entire backing transport. This wouldn't matter
 
1299
        # except that the workdir tests are given - and that they expect the
 
1300
        # server's url to point at - is one directory under the safety net. So
 
1301
        # Branch operations into the transport will attempt to walk up one
 
1302
        # directory. Chrooting all servers would avoid this but also mean that
 
1303
        # we wouldn't be testing directly against non-root urls. Alternatively
 
1304
        # getting the test framework to start the server with a backing server
 
1305
        # at the actual safety net directory would work too, but this then
 
1306
        # means that the self.get_url/self.get_transport methods would need
 
1307
        # to transform all their results. On balance its cleaner to handle it
 
1308
        # here, and permit a higher url when we have one of these transports.
 
1309
        if t.base.endswith('/work/'):
 
1310
            # we have safety net/test root/work
 
1311
            t = t.clone('../..')
 
1312
        elif isinstance(transport_server,
 
1313
                        test_server.SmartTCPServer_for_testing):
 
1314
            # The smart server adds a path similar to work, which is traversed
 
1315
            # up from by the client. But the server is chrooted - the actual
 
1316
            # backing transport is not escaped from, and VFS requests to the
 
1317
            # root will error (because they try to escape the chroot).
 
1318
            t2 = t.clone('..')
 
1319
            while t2.base != t.base:
 
1320
                t = t2
 
1321
                t2 = t.clone('..')
 
1322
        self.permit_url(t.base)
 
1323
 
 
1324
    def _track_transports(self):
 
1325
        """Install checks for transport usage."""
 
1326
        # TestCase has no safe place it can write to.
 
1327
        self._bzr_selftest_roots = []
 
1328
        # Currently the easiest way to be sure that nothing is going on is to
 
1329
        # hook into bzr dir opening. This leaves a small window of error for
 
1330
        # transport tests, but they are well known, and we can improve on this
 
1331
        # step.
 
1332
        bzrdir.BzrDir.hooks.install_named_hook("pre_open",
 
1333
            self._preopen_isolate_transport, "Check bzr directories are safe.")
779
1334
 
780
1335
    def _ndiff_strings(self, a, b):
781
1336
        """Return ndiff between two strings containing lines.
782
 
        
 
1337
 
783
1338
        A trailing newline is added if missing to make the strings
784
1339
        print properly."""
785
1340
        if b and b[-1] != '\n':
799
1354
        except UnicodeError, e:
800
1355
            # If we can't compare without getting a UnicodeError, then
801
1356
            # obviously they are different
802
 
            mutter('UnicodeError: %s', e)
 
1357
            trace.mutter('UnicodeError: %s', e)
803
1358
        if message:
804
1359
            message += '\n'
805
1360
        raise AssertionError("%snot equal:\na = %s\nb = %s\n"
806
1361
            % (message,
807
 
               pformat(a, indent=4), pformat(b, indent=4)))
 
1362
               pprint.pformat(a), pprint.pformat(b)))
808
1363
 
809
1364
    assertEquals = assertEqual
810
1365
 
811
1366
    def assertEqualDiff(self, a, b, message=None):
812
1367
        """Assert two texts are equal, if not raise an exception.
813
 
        
814
 
        This is intended for use with multi-line strings where it can 
 
1368
 
 
1369
        This is intended for use with multi-line strings where it can
815
1370
        be hard to find the differences by eye.
816
1371
        """
817
1372
        # TODO: perhaps override assertEquals to call this for strings?
819
1374
            return
820
1375
        if message is None:
821
1376
            message = "texts not equal:\n"
822
 
        raise AssertionError(message + 
823
 
                             self._ndiff_strings(a, b))      
824
 
        
 
1377
        if a + '\n' == b:
 
1378
            message = 'first string is missing a final newline.\n'
 
1379
        if a == b + '\n':
 
1380
            message = 'second string is missing a final newline.\n'
 
1381
        raise AssertionError(message +
 
1382
                             self._ndiff_strings(a, b))
 
1383
 
825
1384
    def assertEqualMode(self, mode, mode_test):
826
1385
        self.assertEqual(mode, mode_test,
827
1386
                         'mode mismatch %o != %o' % (mode, mode_test))
828
1387
 
 
1388
    def assertEqualStat(self, expected, actual):
 
1389
        """assert that expected and actual are the same stat result.
 
1390
 
 
1391
        :param expected: A stat result.
 
1392
        :param actual: A stat result.
 
1393
        :raises AssertionError: If the expected and actual stat values differ
 
1394
            other than by atime.
 
1395
        """
 
1396
        self.assertEqual(expected.st_size, actual.st_size,
 
1397
                         'st_size did not match')
 
1398
        self.assertEqual(expected.st_mtime, actual.st_mtime,
 
1399
                         'st_mtime did not match')
 
1400
        self.assertEqual(expected.st_ctime, actual.st_ctime,
 
1401
                         'st_ctime did not match')
 
1402
        if sys.platform == 'win32':
 
1403
            # On Win32 both 'dev' and 'ino' cannot be trusted. In python2.4 it
 
1404
            # is 'dev' that varies, in python 2.5 (6?) it is st_ino that is
 
1405
            # odd. We just force it to always be 0 to avoid any problems.
 
1406
            self.assertEqual(0, expected.st_dev)
 
1407
            self.assertEqual(0, actual.st_dev)
 
1408
            self.assertEqual(0, expected.st_ino)
 
1409
            self.assertEqual(0, actual.st_ino)
 
1410
        else:
 
1411
            self.assertEqual(expected.st_dev, actual.st_dev,
 
1412
                             'st_dev did not match')
 
1413
            self.assertEqual(expected.st_ino, actual.st_ino,
 
1414
                             'st_ino did not match')
 
1415
        self.assertEqual(expected.st_mode, actual.st_mode,
 
1416
                         'st_mode did not match')
 
1417
 
 
1418
    def assertLength(self, length, obj_with_len):
 
1419
        """Assert that obj_with_len is of length length."""
 
1420
        if len(obj_with_len) != length:
 
1421
            self.fail("Incorrect length: wanted %d, got %d for %r" % (
 
1422
                length, len(obj_with_len), obj_with_len))
 
1423
 
 
1424
    def assertLogsError(self, exception_class, func, *args, **kwargs):
 
1425
        """Assert that `func(*args, **kwargs)` quietly logs a specific error.
 
1426
        """
 
1427
        captured = []
 
1428
        orig_log_exception_quietly = trace.log_exception_quietly
 
1429
        try:
 
1430
            def capture():
 
1431
                orig_log_exception_quietly()
 
1432
                captured.append(sys.exc_info()[1])
 
1433
            trace.log_exception_quietly = capture
 
1434
            func(*args, **kwargs)
 
1435
        finally:
 
1436
            trace.log_exception_quietly = orig_log_exception_quietly
 
1437
        self.assertLength(1, captured)
 
1438
        err = captured[0]
 
1439
        self.assertIsInstance(err, exception_class)
 
1440
        return err
 
1441
 
 
1442
    def assertPositive(self, val):
 
1443
        """Assert that val is greater than 0."""
 
1444
        self.assertTrue(val > 0, 'expected a positive value, but got %s' % val)
 
1445
 
 
1446
    def assertNegative(self, val):
 
1447
        """Assert that val is less than 0."""
 
1448
        self.assertTrue(val < 0, 'expected a negative value, but got %s' % val)
 
1449
 
829
1450
    def assertStartsWith(self, s, prefix):
830
1451
        if not s.startswith(prefix):
831
1452
            raise AssertionError('string %r does not start with %r' % (s, prefix))
835
1456
        if not s.endswith(suffix):
836
1457
            raise AssertionError('string %r does not end with %r' % (s, suffix))
837
1458
 
838
 
    def assertContainsRe(self, haystack, needle_re):
 
1459
    def assertContainsRe(self, haystack, needle_re, flags=0):
839
1460
        """Assert that a contains something matching a regular expression."""
840
 
        if not re.search(needle_re, haystack):
841
 
            raise AssertionError('pattern "%r" not found in "%r"'
842
 
                    % (needle_re, haystack))
 
1461
        if not re.search(needle_re, haystack, flags):
 
1462
            if '\n' in haystack or len(haystack) > 60:
 
1463
                # a long string, format it in a more readable way
 
1464
                raise AssertionError(
 
1465
                        'pattern "%s" not found in\n"""\\\n%s"""\n'
 
1466
                        % (needle_re, haystack))
 
1467
            else:
 
1468
                raise AssertionError('pattern "%s" not found in "%s"'
 
1469
                        % (needle_re, haystack))
843
1470
 
844
 
    def assertNotContainsRe(self, haystack, needle_re):
 
1471
    def assertNotContainsRe(self, haystack, needle_re, flags=0):
845
1472
        """Assert that a does not match a regular expression"""
846
 
        if re.search(needle_re, haystack):
 
1473
        if re.search(needle_re, haystack, flags):
847
1474
            raise AssertionError('pattern "%s" found in "%s"'
848
1475
                    % (needle_re, haystack))
849
1476
 
 
1477
    def assertContainsString(self, haystack, needle):
 
1478
        if haystack.find(needle) == -1:
 
1479
            self.fail("string %r not found in '''%s'''" % (needle, haystack))
 
1480
 
 
1481
    def assertNotContainsString(self, haystack, needle):
 
1482
        if haystack.find(needle) != -1:
 
1483
            self.fail("string %r found in '''%s'''" % (needle, haystack))
 
1484
 
850
1485
    def assertSubset(self, sublist, superlist):
851
1486
        """Assert that every entry in sublist is present in superlist."""
852
 
        missing = []
853
 
        for entry in sublist:
854
 
            if entry not in superlist:
855
 
                missing.append(entry)
 
1487
        missing = set(sublist) - set(superlist)
856
1488
        if len(missing) > 0:
857
 
            raise AssertionError("value(s) %r not present in container %r" % 
 
1489
            raise AssertionError("value(s) %r not present in container %r" %
858
1490
                                 (missing, superlist))
859
1491
 
860
1492
    def assertListRaises(self, excClass, func, *args, **kwargs):
861
1493
        """Fail unless excClass is raised when the iterator from func is used.
862
 
        
 
1494
 
863
1495
        Many functions can return generators this makes sure
864
1496
        to wrap them in a list() call to make sure the whole generator
865
1497
        is run, and that the proper exception is raised.
866
1498
        """
867
1499
        try:
868
1500
            list(func(*args, **kwargs))
869
 
        except excClass:
870
 
            return
 
1501
        except excClass, e:
 
1502
            return e
871
1503
        else:
872
1504
            if getattr(excClass,'__name__', None) is not None:
873
1505
                excName = excClass.__name__
875
1507
                excName = str(excClass)
876
1508
            raise self.failureException, "%s not raised" % excName
877
1509
 
878
 
    def assertRaises(self, excClass, func, *args, **kwargs):
 
1510
    def assertRaises(self, excClass, callableObj, *args, **kwargs):
879
1511
        """Assert that a callable raises a particular exception.
880
1512
 
881
1513
        :param excClass: As for the except statement, this may be either an
882
 
        exception class, or a tuple of classes.
 
1514
            exception class, or a tuple of classes.
 
1515
        :param callableObj: A callable, will be passed ``*args`` and
 
1516
            ``**kwargs``.
883
1517
 
884
1518
        Returns the exception so that you can examine it.
885
1519
        """
886
1520
        try:
887
 
            func(*args, **kwargs)
 
1521
            callableObj(*args, **kwargs)
888
1522
        except excClass, e:
889
1523
            return e
890
1524
        else:
910
1544
                raise AssertionError("%r is %r." % (left, right))
911
1545
 
912
1546
    def assertTransportMode(self, transport, path, mode):
913
 
        """Fail if a path does not have mode mode.
914
 
        
 
1547
        """Fail if a path does not have mode "mode".
 
1548
 
915
1549
        If modes are not supported on this transport, the assertion is ignored.
916
1550
        """
917
1551
        if not transport._can_roundtrip_unix_modebits():
919
1553
        path_stat = transport.stat(path)
920
1554
        actual_mode = stat.S_IMODE(path_stat.st_mode)
921
1555
        self.assertEqual(mode, actual_mode,
922
 
            'mode of %r incorrect (%o != %o)' % (path, mode, actual_mode))
923
 
 
924
 
    def assertIsInstance(self, obj, kls):
925
 
        """Fail if obj is not an instance of kls"""
 
1556
                         'mode of %r incorrect (%s != %s)'
 
1557
                         % (path, oct(mode), oct(actual_mode)))
 
1558
 
 
1559
    def assertIsSameRealPath(self, path1, path2):
 
1560
        """Fail if path1 and path2 points to different files"""
 
1561
        self.assertEqual(osutils.realpath(path1),
 
1562
                         osutils.realpath(path2),
 
1563
                         "apparent paths:\na = %s\nb = %s\n," % (path1, path2))
 
1564
 
 
1565
    def assertIsInstance(self, obj, kls, msg=None):
 
1566
        """Fail if obj is not an instance of kls
 
1567
        
 
1568
        :param msg: Supplementary message to show if the assertion fails.
 
1569
        """
926
1570
        if not isinstance(obj, kls):
927
 
            self.fail("%r is an instance of %s rather than %s" % (
928
 
                obj, obj.__class__, kls))
929
 
 
930
 
    def expectFailure(self, reason, assertion, *args, **kwargs):
931
 
        """Invoke a test, expecting it to fail for the given reason.
932
 
 
933
 
        This is for assertions that ought to succeed, but currently fail.
934
 
        (The failure is *expected* but not *wanted*.)  Please be very precise
935
 
        about the failure you're expecting.  If a new bug is introduced,
936
 
        AssertionError should be raised, not KnownFailure.
937
 
 
938
 
        Frequently, expectFailure should be followed by an opposite assertion.
939
 
        See example below.
940
 
 
941
 
        Intended to be used with a callable that raises AssertionError as the
942
 
        'assertion' parameter.  args and kwargs are passed to the 'assertion'.
943
 
 
944
 
        Raises KnownFailure if the test fails.  Raises AssertionError if the
945
 
        test succeeds.
946
 
 
947
 
        example usage::
948
 
 
949
 
          self.expectFailure('Math is broken', self.assertNotEqual, 54,
950
 
                             dynamic_val)
951
 
          self.assertEqual(42, dynamic_val)
952
 
 
953
 
          This means that a dynamic_val of 54 will cause the test to raise
954
 
          a KnownFailure.  Once math is fixed and the expectFailure is removed,
955
 
          only a dynamic_val of 42 will allow the test to pass.  Anything other
956
 
          than 54 or 42 will cause an AssertionError.
957
 
        """
 
1571
            m = "%r is an instance of %s rather than %s" % (
 
1572
                obj, obj.__class__, kls)
 
1573
            if msg:
 
1574
                m += ": " + msg
 
1575
            self.fail(m)
 
1576
 
 
1577
    def assertFileEqual(self, content, path):
 
1578
        """Fail if path does not contain 'content'."""
 
1579
        self.assertPathExists(path)
 
1580
        f = file(path, 'rb')
958
1581
        try:
959
 
            assertion(*args, **kwargs)
960
 
        except AssertionError:
961
 
            raise KnownFailure(reason)
962
 
        else:
963
 
            self.fail('Unexpected success.  Should have failed: %s' % reason)
964
 
 
965
 
    def _capture_warnings(self, a_callable, *args, **kwargs):
 
1582
            s = f.read()
 
1583
        finally:
 
1584
            f.close()
 
1585
        self.assertEqualDiff(content, s)
 
1586
 
 
1587
    def assertDocstring(self, expected_docstring, obj):
 
1588
        """Fail if obj does not have expected_docstring"""
 
1589
        if __doc__ is None:
 
1590
            # With -OO the docstring should be None instead
 
1591
            self.assertIs(obj.__doc__, None)
 
1592
        else:
 
1593
            self.assertEqual(expected_docstring, obj.__doc__)
 
1594
 
 
1595
    @symbol_versioning.deprecated_method(symbol_versioning.deprecated_in((2, 4)))
 
1596
    def failUnlessExists(self, path):
 
1597
        return self.assertPathExists(path)
 
1598
 
 
1599
    def assertPathExists(self, path):
 
1600
        """Fail unless path or paths, which may be abs or relative, exist."""
 
1601
        if not isinstance(path, basestring):
 
1602
            for p in path:
 
1603
                self.assertPathExists(p)
 
1604
        else:
 
1605
            self.assertTrue(osutils.lexists(path),
 
1606
                path + " does not exist")
 
1607
 
 
1608
    @symbol_versioning.deprecated_method(symbol_versioning.deprecated_in((2, 4)))
 
1609
    def failIfExists(self, path):
 
1610
        return self.assertPathDoesNotExist(path)
 
1611
 
 
1612
    def assertPathDoesNotExist(self, path):
 
1613
        """Fail if path or paths, which may be abs or relative, exist."""
 
1614
        if not isinstance(path, basestring):
 
1615
            for p in path:
 
1616
                self.assertPathDoesNotExist(p)
 
1617
        else:
 
1618
            self.assertFalse(osutils.lexists(path),
 
1619
                path + " exists")
 
1620
 
 
1621
    def _capture_deprecation_warnings(self, a_callable, *args, **kwargs):
966
1622
        """A helper for callDeprecated and applyDeprecated.
967
1623
 
968
1624
        :param a_callable: A callable to call.
969
1625
        :param args: The positional arguments for the callable
970
1626
        :param kwargs: The keyword arguments for the callable
971
1627
        :return: A tuple (warnings, result). result is the result of calling
972
 
            a_callable(*args, **kwargs).
 
1628
            a_callable(``*args``, ``**kwargs``).
973
1629
        """
974
1630
        local_warnings = []
975
1631
        def capture_warnings(msg, cls=None, stacklevel=None):
988
1644
    def applyDeprecated(self, deprecation_format, a_callable, *args, **kwargs):
989
1645
        """Call a deprecated callable without warning the user.
990
1646
 
 
1647
        Note that this only captures warnings raised by symbol_versioning.warn,
 
1648
        not other callers that go direct to the warning module.
 
1649
 
 
1650
        To test that a deprecated method raises an error, do something like
 
1651
        this (remember that both assertRaises and applyDeprecated delays *args
 
1652
        and **kwargs passing)::
 
1653
 
 
1654
            self.assertRaises(errors.ReservedId,
 
1655
                self.applyDeprecated,
 
1656
                deprecated_in((1, 5, 0)),
 
1657
                br.append_revision,
 
1658
                'current:')
 
1659
 
991
1660
        :param deprecation_format: The deprecation format that the callable
992
 
            should have been deprecated with. This is the same type as the 
993
 
            parameter to deprecated_method/deprecated_function. If the 
 
1661
            should have been deprecated with. This is the same type as the
 
1662
            parameter to deprecated_method/deprecated_function. If the
994
1663
            callable is not deprecated with this format, an assertion error
995
1664
            will be raised.
996
1665
        :param a_callable: A callable to call. This may be a bound method or
997
 
            a regular function. It will be called with *args and **kwargs.
 
1666
            a regular function. It will be called with ``*args`` and
 
1667
            ``**kwargs``.
998
1668
        :param args: The positional arguments for the callable
999
1669
        :param kwargs: The keyword arguments for the callable
1000
 
        :return: The result of a_callable(*args, **kwargs)
 
1670
        :return: The result of a_callable(``*args``, ``**kwargs``)
1001
1671
        """
1002
 
        call_warnings, result = self._capture_warnings(a_callable,
 
1672
        call_warnings, result = self._capture_deprecation_warnings(a_callable,
1003
1673
            *args, **kwargs)
1004
1674
        expected_first_warning = symbol_versioning.deprecation_string(
1005
1675
            a_callable, deprecation_format)
1009
1679
        self.assertEqual(expected_first_warning, call_warnings[0])
1010
1680
        return result
1011
1681
 
 
1682
    def callCatchWarnings(self, fn, *args, **kw):
 
1683
        """Call a callable that raises python warnings.
 
1684
 
 
1685
        The caller's responsible for examining the returned warnings.
 
1686
 
 
1687
        If the callable raises an exception, the exception is not
 
1688
        caught and propagates up to the caller.  In that case, the list
 
1689
        of warnings is not available.
 
1690
 
 
1691
        :returns: ([warning_object, ...], fn_result)
 
1692
        """
 
1693
        # XXX: This is not perfect, because it completely overrides the
 
1694
        # warnings filters, and some code may depend on suppressing particular
 
1695
        # warnings.  It's the easiest way to insulate ourselves from -Werror,
 
1696
        # though.  -- Andrew, 20071062
 
1697
        wlist = []
 
1698
        def _catcher(message, category, filename, lineno, file=None, line=None):
 
1699
            # despite the name, 'message' is normally(?) a Warning subclass
 
1700
            # instance
 
1701
            wlist.append(message)
 
1702
        saved_showwarning = warnings.showwarning
 
1703
        saved_filters = warnings.filters
 
1704
        try:
 
1705
            warnings.showwarning = _catcher
 
1706
            warnings.filters = []
 
1707
            result = fn(*args, **kw)
 
1708
        finally:
 
1709
            warnings.showwarning = saved_showwarning
 
1710
            warnings.filters = saved_filters
 
1711
        return wlist, result
 
1712
 
1012
1713
    def callDeprecated(self, expected, callable, *args, **kwargs):
1013
1714
        """Assert that a callable is deprecated in a particular way.
1014
1715
 
1015
 
        This is a very precise test for unusual requirements. The 
 
1716
        This is a very precise test for unusual requirements. The
1016
1717
        applyDeprecated helper function is probably more suited for most tests
1017
1718
        as it allows you to simply specify the deprecation format being used
1018
1719
        and will ensure that that is issued for the function being called.
1019
1720
 
 
1721
        Note that this only captures warnings raised by symbol_versioning.warn,
 
1722
        not other callers that go direct to the warning module.  To catch
 
1723
        general warnings, use callCatchWarnings.
 
1724
 
1020
1725
        :param expected: a list of the deprecation warnings expected, in order
1021
1726
        :param callable: The callable to call
1022
1727
        :param args: The positional arguments for the callable
1023
1728
        :param kwargs: The keyword arguments for the callable
1024
1729
        """
1025
 
        call_warnings, result = self._capture_warnings(callable,
 
1730
        call_warnings, result = self._capture_deprecation_warnings(callable,
1026
1731
            *args, **kwargs)
1027
1732
        self.assertEqual(expected, call_warnings)
1028
1733
        return result
1029
1734
 
1030
1735
    def _startLogFile(self):
1031
 
        """Send bzr and test log messages to a temporary file.
1032
 
 
1033
 
        The file is removed as the test is torn down.
1034
 
        """
1035
 
        fileno, name = tempfile.mkstemp(suffix='.log', prefix='testbzr')
1036
 
        self._log_file = os.fdopen(fileno, 'w+')
1037
 
        self._log_nonce = bzrlib.trace.enable_test_log(self._log_file)
1038
 
        self._log_file_name = name
 
1736
        """Setup a in-memory target for bzr and testcase log messages"""
 
1737
        pseudo_log_file = StringIO()
 
1738
        def _get_log_contents_for_weird_testtools_api():
 
1739
            return [pseudo_log_file.getvalue().decode(
 
1740
                "utf-8", "replace").encode("utf-8")]
 
1741
        self.addDetail("log", content.Content(content.ContentType("text",
 
1742
            "plain", {"charset": "utf8"}),
 
1743
            _get_log_contents_for_weird_testtools_api))
 
1744
        self._log_file = pseudo_log_file
 
1745
        self._log_memento = trace.push_log_file(self._log_file)
1039
1746
        self.addCleanup(self._finishLogFile)
1040
1747
 
1041
1748
    def _finishLogFile(self):
1042
 
        """Finished with the log file.
1043
 
 
1044
 
        Close the file and delete it, unless setKeepLogfile was called.
1045
 
        """
1046
 
        if self._log_file is None:
1047
 
            return
1048
 
        bzrlib.trace.disable_test_log(self._log_nonce)
1049
 
        self._log_file.close()
1050
 
        self._log_file = None
1051
 
        if not self._keep_log_file:
1052
 
            os.remove(self._log_file_name)
1053
 
            self._log_file_name = None
1054
 
 
1055
 
    def setKeepLogfile(self):
1056
 
        """Make the logfile not be deleted when _finishLogFile is called."""
1057
 
        self._keep_log_file = True
1058
 
 
1059
 
    def addCleanup(self, callable):
1060
 
        """Arrange to run a callable when this case is torn down.
1061
 
 
1062
 
        Callables are run in the reverse of the order they are registered, 
1063
 
        ie last-in first-out.
1064
 
        """
1065
 
        if callable in self._cleanups:
1066
 
            raise ValueError("cleanup function %r already registered on %s" 
1067
 
                    % (callable, self))
1068
 
        self._cleanups.append(callable)
 
1749
        """Flush and dereference the in-memory log for this testcase"""
 
1750
        if trace._trace_file:
 
1751
            # flush the log file, to get all content
 
1752
            trace._trace_file.flush()
 
1753
        trace.pop_log_file(self._log_memento)
 
1754
        # The logging module now tracks references for cleanup so discard ours
 
1755
        del self._log_memento
 
1756
 
 
1757
    def thisFailsStrictLockCheck(self):
 
1758
        """It is known that this test would fail with -Dstrict_locks.
 
1759
 
 
1760
        By default, all tests are run with strict lock checking unless
 
1761
        -Edisable_lock_checks is supplied. However there are some tests which
 
1762
        we know fail strict locks at this point that have not been fixed.
 
1763
        They should call this function to disable the strict checking.
 
1764
 
 
1765
        This should be used sparingly, it is much better to fix the locking
 
1766
        issues rather than papering over the problem by calling this function.
 
1767
        """
 
1768
        debug.debug_flags.discard('strict_locks')
 
1769
 
 
1770
    def overrideAttr(self, obj, attr_name, new=_unitialized_attr):
 
1771
        """Overrides an object attribute restoring it after the test.
 
1772
 
 
1773
        :note: This should be used with discretion; you should think about
 
1774
        whether it's better to make the code testable without monkey-patching.
 
1775
 
 
1776
        :param obj: The object that will be mutated.
 
1777
 
 
1778
        :param attr_name: The attribute name we want to preserve/override in
 
1779
            the object.
 
1780
 
 
1781
        :param new: The optional value we want to set the attribute to.
 
1782
 
 
1783
        :returns: The actual attr value.
 
1784
        """
 
1785
        # The actual value is captured by the call below
 
1786
        value = getattr(obj, attr_name, _unitialized_attr)
 
1787
        if value is _unitialized_attr:
 
1788
            # When the test completes, the attribute should not exist, but if
 
1789
            # we aren't setting a value, we don't need to do anything.
 
1790
            if new is not _unitialized_attr:
 
1791
                self.addCleanup(delattr, obj, attr_name)
 
1792
        else:
 
1793
            self.addCleanup(setattr, obj, attr_name, value)
 
1794
        if new is not _unitialized_attr:
 
1795
            setattr(obj, attr_name, new)
 
1796
        return value
 
1797
 
 
1798
    def overrideEnv(self, name, new):
 
1799
        """Set an environment variable, and reset it after the test.
 
1800
 
 
1801
        :param name: The environment variable name.
 
1802
 
 
1803
        :param new: The value to set the variable to. If None, the 
 
1804
            variable is deleted from the environment.
 
1805
 
 
1806
        :returns: The actual variable value.
 
1807
        """
 
1808
        value = osutils.set_or_unset_env(name, new)
 
1809
        self.addCleanup(osutils.set_or_unset_env, name, value)
 
1810
        return value
 
1811
 
 
1812
    def recordCalls(self, obj, attr_name):
 
1813
        """Monkeypatch in a wrapper that will record calls.
 
1814
 
 
1815
        The monkeypatch is automatically removed when the test concludes.
 
1816
 
 
1817
        :param obj: The namespace holding the reference to be replaced;
 
1818
            typically a module, class, or object.
 
1819
        :param attr_name: A string for the name of the attribute to 
 
1820
            patch.
 
1821
        :returns: A list that will be extended with one item every time the
 
1822
            function is called, with a tuple of (args, kwargs).
 
1823
        """
 
1824
        calls = []
 
1825
 
 
1826
        def decorator(*args, **kwargs):
 
1827
            calls.append((args, kwargs))
 
1828
            return orig(*args, **kwargs)
 
1829
        orig = self.overrideAttr(obj, attr_name, decorator)
 
1830
        return calls
1069
1831
 
1070
1832
    def _cleanEnvironment(self):
1071
 
        new_env = {
1072
 
            'BZR_HOME': None, # Don't inherit BZR_HOME to all the tests.
1073
 
            'HOME': os.getcwd(),
1074
 
            'APPDATA': None,  # bzr now use Win32 API and don't rely on APPDATA
1075
 
            'BZR_EMAIL': None,
1076
 
            'BZREMAIL': None, # may still be present in the environment
1077
 
            'EMAIL': None,
1078
 
            'BZR_PROGRESS_BAR': None,
1079
 
            # Proxies
1080
 
            'http_proxy': None,
1081
 
            'HTTP_PROXY': None,
1082
 
            'https_proxy': None,
1083
 
            'HTTPS_PROXY': None,
1084
 
            'no_proxy': None,
1085
 
            'NO_PROXY': None,
1086
 
            'all_proxy': None,
1087
 
            'ALL_PROXY': None,
1088
 
            # Nobody cares about these ones AFAIK. So far at
1089
 
            # least. If you do (care), please update this comment
1090
 
            # -- vila 20061212
1091
 
            'ftp_proxy': None,
1092
 
            'FTP_PROXY': None,
1093
 
        }
1094
 
        self.__old_env = {}
1095
 
        self.addCleanup(self._restoreEnvironment)
1096
 
        for name, value in new_env.iteritems():
1097
 
            self._captureVar(name, value)
1098
 
 
1099
 
    def _captureVar(self, name, newvalue):
1100
 
        """Set an environment variable, and reset it when finished."""
1101
 
        self.__old_env[name] = osutils.set_or_unset_env(name, newvalue)
1102
 
 
1103
 
    def _restoreEnvironment(self):
1104
 
        for name, value in self.__old_env.iteritems():
1105
 
            osutils.set_or_unset_env(name, value)
 
1833
        for name, value in isolated_environ.iteritems():
 
1834
            self.overrideEnv(name, value)
1106
1835
 
1107
1836
    def _restoreHooks(self):
1108
 
        for klass, hooks in self._preserved_hooks.items():
1109
 
            setattr(klass, 'hooks', hooks)
 
1837
        for klass, (name, hooks) in self._preserved_hooks.items():
 
1838
            setattr(klass, name, hooks)
 
1839
        self._preserved_hooks.clear()
 
1840
        bzrlib.hooks._lazy_hooks = self._preserved_lazy_hooks
 
1841
        self._preserved_lazy_hooks.clear()
1110
1842
 
1111
1843
    def knownFailure(self, reason):
1112
 
        """This test has failed for some known reason."""
1113
 
        raise KnownFailure(reason)
1114
 
 
1115
 
    def run(self, result=None):
1116
 
        if result is None: result = self.defaultTestResult()
1117
 
        for feature in getattr(self, '_test_needs_features', []):
1118
 
            if not feature.available():
1119
 
                result.startTest(self)
1120
 
                if getattr(result, 'addNotSupported', None):
1121
 
                    result.addNotSupported(self, feature)
1122
 
                else:
1123
 
                    result.addSuccess(self)
1124
 
                result.stopTest(self)
1125
 
                return
1126
 
        return unittest.TestCase.run(self, result)
1127
 
 
1128
 
    def tearDown(self):
1129
 
        self._runCleanups()
1130
 
        unittest.TestCase.tearDown(self)
 
1844
        """Declare that this test fails for a known reason
 
1845
 
 
1846
        Tests that are known to fail should generally be using expectedFailure
 
1847
        with an appropriate reverse assertion if a change could cause the test
 
1848
        to start passing. Conversely if the test has no immediate prospect of
 
1849
        succeeding then using skip is more suitable.
 
1850
 
 
1851
        When this method is called while an exception is being handled, that
 
1852
        traceback will be used, otherwise a new exception will be thrown to
 
1853
        provide one but won't be reported.
 
1854
        """
 
1855
        self._add_reason(reason)
 
1856
        try:
 
1857
            exc_info = sys.exc_info()
 
1858
            if exc_info != (None, None, None):
 
1859
                self._report_traceback(exc_info)
 
1860
            else:
 
1861
                try:
 
1862
                    raise self.failureException(reason)
 
1863
                except self.failureException:
 
1864
                    exc_info = sys.exc_info()
 
1865
            # GZ 02-08-2011: Maybe cleanup this err.exc_info attribute too?
 
1866
            raise testtools.testcase._ExpectedFailure(exc_info)
 
1867
        finally:
 
1868
            del exc_info
 
1869
 
 
1870
    def _suppress_log(self):
 
1871
        """Remove the log info from details."""
 
1872
        self.discardDetail('log')
 
1873
 
 
1874
    def _do_skip(self, result, reason):
 
1875
        self._suppress_log()
 
1876
        addSkip = getattr(result, 'addSkip', None)
 
1877
        if not callable(addSkip):
 
1878
            result.addSuccess(result)
 
1879
        else:
 
1880
            addSkip(self, reason)
 
1881
 
 
1882
    @staticmethod
 
1883
    def _do_known_failure(self, result, e):
 
1884
        self._suppress_log()
 
1885
        err = sys.exc_info()
 
1886
        addExpectedFailure = getattr(result, 'addExpectedFailure', None)
 
1887
        if addExpectedFailure is not None:
 
1888
            addExpectedFailure(self, err)
 
1889
        else:
 
1890
            result.addSuccess(self)
 
1891
 
 
1892
    @staticmethod
 
1893
    def _do_not_applicable(self, result, e):
 
1894
        if not e.args:
 
1895
            reason = 'No reason given'
 
1896
        else:
 
1897
            reason = e.args[0]
 
1898
        self._suppress_log ()
 
1899
        addNotApplicable = getattr(result, 'addNotApplicable', None)
 
1900
        if addNotApplicable is not None:
 
1901
            result.addNotApplicable(self, reason)
 
1902
        else:
 
1903
            self._do_skip(result, reason)
 
1904
 
 
1905
    @staticmethod
 
1906
    def _report_skip(self, result, err):
 
1907
        """Override the default _report_skip.
 
1908
 
 
1909
        We want to strip the 'log' detail. If we waint until _do_skip, it has
 
1910
        already been formatted into the 'reason' string, and we can't pull it
 
1911
        out again.
 
1912
        """
 
1913
        self._suppress_log()
 
1914
        super(TestCase, self)._report_skip(self, result, err)
 
1915
 
 
1916
    @staticmethod
 
1917
    def _report_expected_failure(self, result, err):
 
1918
        """Strip the log.
 
1919
 
 
1920
        See _report_skip for motivation.
 
1921
        """
 
1922
        self._suppress_log()
 
1923
        super(TestCase, self)._report_expected_failure(self, result, err)
 
1924
 
 
1925
    @staticmethod
 
1926
    def _do_unsupported_or_skip(self, result, e):
 
1927
        reason = e.args[0]
 
1928
        self._suppress_log()
 
1929
        addNotSupported = getattr(result, 'addNotSupported', None)
 
1930
        if addNotSupported is not None:
 
1931
            result.addNotSupported(self, reason)
 
1932
        else:
 
1933
            self._do_skip(result, reason)
1131
1934
 
1132
1935
    def time(self, callable, *args, **kwargs):
1133
1936
        """Run callable and accrue the time it takes to the benchmark time.
1134
 
        
 
1937
 
1135
1938
        If lsprofiling is enabled (i.e. by --lsprof-time to bzr selftest) then
1136
1939
        this will cause lsprofile statistics to be gathered and stored in
1137
1940
        self._benchcalls.
1138
1941
        """
1139
1942
        if self._benchtime is None:
 
1943
            self.addDetail('benchtime', content.Content(content.ContentType(
 
1944
                "text", "plain"), lambda:[str(self._benchtime)]))
1140
1945
            self._benchtime = 0
1141
1946
        start = time.time()
1142
1947
        try:
1151
1956
        finally:
1152
1957
            self._benchtime += time.time() - start
1153
1958
 
1154
 
    def _runCleanups(self):
1155
 
        """Run registered cleanup functions. 
1156
 
 
1157
 
        This should only be called from TestCase.tearDown.
1158
 
        """
1159
 
        # TODO: Perhaps this should keep running cleanups even if 
1160
 
        # one of them fails?
1161
 
 
1162
 
        # Actually pop the cleanups from the list so tearDown running
1163
 
        # twice is safe (this happens for skipped tests).
1164
 
        while self._cleanups:
1165
 
            self._cleanups.pop()()
1166
 
 
1167
1959
    def log(self, *args):
1168
 
        mutter(*args)
1169
 
 
1170
 
    def _get_log(self, keep_log_file=False):
1171
 
        """Return as a string the log for this test. If the file is still
1172
 
        on disk and keep_log_file=False, delete the log file and store the
1173
 
        content in self._log_contents."""
1174
 
        # flush the log file, to get all content
1175
 
        import bzrlib.trace
1176
 
        bzrlib.trace._trace_file.flush()
1177
 
        if self._log_contents:
1178
 
            return self._log_contents
1179
 
        if self._log_file_name is not None:
1180
 
            logfile = open(self._log_file_name)
1181
 
            try:
1182
 
                log_contents = logfile.read()
1183
 
            finally:
1184
 
                logfile.close()
1185
 
            if not keep_log_file:
1186
 
                self._log_contents = log_contents
1187
 
                try:
1188
 
                    os.remove(self._log_file_name)
1189
 
                except OSError, e:
1190
 
                    if sys.platform == 'win32' and e.errno == errno.EACCES:
1191
 
                        print >>sys.stderr, ('Unable to delete log file '
1192
 
                                             ' %r' % self._log_file_name)
1193
 
                    else:
1194
 
                        raise
1195
 
            return log_contents
1196
 
        else:
1197
 
            return "DELETED log file to reduce memory footprint"
1198
 
 
1199
 
    def capture(self, cmd, retcode=0):
1200
 
        """Shortcut that splits cmd into words, runs, and returns stdout"""
1201
 
        return self.run_bzr_captured(cmd.split(), retcode=retcode)[0]
 
1960
        trace.mutter(*args)
 
1961
 
 
1962
    def get_log(self):
 
1963
        """Get a unicode string containing the log from bzrlib.trace.
 
1964
 
 
1965
        Undecodable characters are replaced.
 
1966
        """
 
1967
        return u"".join(self.getDetails()['log'].iter_text())
1202
1968
 
1203
1969
    def requireFeature(self, feature):
1204
1970
        """This test requires a specific feature is available.
1208
1974
        if not feature.available():
1209
1975
            raise UnavailableFeature(feature)
1210
1976
 
1211
 
    def run_bzr_captured(self, argv, retcode=0, encoding=None, stdin=None,
1212
 
                         working_dir=None):
1213
 
        """Invoke bzr and return (stdout, stderr).
1214
 
 
1215
 
        Useful for code that wants to check the contents of the
1216
 
        output, the way error messages are presented, etc.
1217
 
 
1218
 
        This should be the main method for tests that want to exercise the
1219
 
        overall behavior of the bzr application (rather than a unit test
1220
 
        or a functional test of the library.)
1221
 
 
1222
 
        Much of the old code runs bzr by forking a new copy of Python, but
1223
 
        that is slower, harder to debug, and generally not necessary.
1224
 
 
1225
 
        This runs bzr through the interface that catches and reports
1226
 
        errors, and with logging set to something approximating the
1227
 
        default, so that error reporting can be checked.
1228
 
 
1229
 
        :param argv: arguments to invoke bzr
1230
 
        :param retcode: expected return code, or None for don't-care.
1231
 
        :param encoding: encoding for sys.stdout and sys.stderr
1232
 
        :param stdin: A string to be used as stdin for the command.
1233
 
        :param working_dir: Change to this directory before running
1234
 
        """
 
1977
    def _run_bzr_autosplit(self, args, retcode, encoding, stdin,
 
1978
            working_dir):
 
1979
        """Run bazaar command line, splitting up a string command line."""
 
1980
        if isinstance(args, basestring):
 
1981
            # shlex don't understand unicode strings,
 
1982
            # so args should be plain string (bialix 20070906)
 
1983
            args = list(shlex.split(str(args)))
 
1984
        return self._run_bzr_core(args, retcode=retcode,
 
1985
                encoding=encoding, stdin=stdin, working_dir=working_dir,
 
1986
                )
 
1987
 
 
1988
    def _run_bzr_core(self, args, retcode, encoding, stdin,
 
1989
            working_dir):
 
1990
        # Clear chk_map page cache, because the contents are likely to mask
 
1991
        # locking errors.
 
1992
        chk_map.clear_cache()
1235
1993
        if encoding is None:
1236
 
            encoding = bzrlib.user_encoding
 
1994
            encoding = osutils.get_user_encoding()
1237
1995
        stdout = StringIOWrapper()
1238
1996
        stderr = StringIOWrapper()
1239
1997
        stdout.encoding = encoding
1240
1998
        stderr.encoding = encoding
1241
1999
 
1242
 
        self.log('run bzr: %r', argv)
 
2000
        self.log('run bzr: %r', args)
1243
2001
        # FIXME: don't call into logging here
1244
 
        handler = logging.StreamHandler(stderr)
1245
 
        handler.setLevel(logging.INFO)
 
2002
        handler = trace.EncodedStreamHandler(stderr, errors="replace",
 
2003
            level=logging.INFO)
1246
2004
        logger = logging.getLogger('')
1247
2005
        logger.addHandler(handler)
1248
2006
        old_ui_factory = ui.ui_factory
1254
2012
            os.chdir(working_dir)
1255
2013
 
1256
2014
        try:
1257
 
            saved_debug_flags = frozenset(debug.debug_flags)
1258
 
            debug.debug_flags.clear()
1259
2015
            try:
1260
 
                result = self.apply_redirected(ui.ui_factory.stdin,
1261
 
                                               stdout, stderr,
1262
 
                                               bzrlib.commands.run_bzr_catch_errors,
1263
 
                                               argv)
1264
 
            finally:
1265
 
                debug.debug_flags.update(saved_debug_flags)
 
2016
                result = self.apply_redirected(
 
2017
                    ui.ui_factory.stdin,
 
2018
                    stdout, stderr,
 
2019
                    _mod_commands.run_bzr_catch_user_errors,
 
2020
                    args)
 
2021
            except KeyboardInterrupt:
 
2022
                # Reraise KeyboardInterrupt with contents of redirected stdout
 
2023
                # and stderr as arguments, for tests which are interested in
 
2024
                # stdout and stderr and are expecting the exception.
 
2025
                out = stdout.getvalue()
 
2026
                err = stderr.getvalue()
 
2027
                if out:
 
2028
                    self.log('output:\n%r', out)
 
2029
                if err:
 
2030
                    self.log('errors:\n%r', err)
 
2031
                raise KeyboardInterrupt(out, err)
1266
2032
        finally:
1267
2033
            logger.removeHandler(handler)
1268
2034
            ui.ui_factory = old_ui_factory
1276
2042
        if err:
1277
2043
            self.log('errors:\n%r', err)
1278
2044
        if retcode is not None:
1279
 
            self.assertEquals(retcode, result)
1280
 
        return out, err
 
2045
            self.assertEquals(retcode, result,
 
2046
                              message='Unexpected return code')
 
2047
        return result, out, err
1281
2048
 
1282
 
    def run_bzr(self, *args, **kwargs):
 
2049
    def run_bzr(self, args, retcode=0, encoding=None, stdin=None,
 
2050
                working_dir=None, error_regexes=[], output_encoding=None):
1283
2051
        """Invoke bzr, as if it were run from the command line.
1284
2052
 
 
2053
        The argument list should not include the bzr program name - the
 
2054
        first argument is normally the bzr command.  Arguments may be
 
2055
        passed in three ways:
 
2056
 
 
2057
        1- A list of strings, eg ["commit", "a"].  This is recommended
 
2058
        when the command contains whitespace or metacharacters, or
 
2059
        is built up at run time.
 
2060
 
 
2061
        2- A single string, eg "add a".  This is the most convenient
 
2062
        for hardcoded commands.
 
2063
 
 
2064
        This runs bzr through the interface that catches and reports
 
2065
        errors, and with logging set to something approximating the
 
2066
        default, so that error reporting can be checked.
 
2067
 
1285
2068
        This should be the main method for tests that want to exercise the
1286
2069
        overall behavior of the bzr application (rather than a unit test
1287
2070
        or a functional test of the library.)
1289
2072
        This sends the stdout/stderr results into the test's log,
1290
2073
        where it may be useful for debugging.  See also run_captured.
1291
2074
 
1292
 
        :param stdin: A string to be used as stdin for the command.
1293
 
        :param retcode: The status code the command should return
1294
 
        :param working_dir: The directory to run the command in
 
2075
        :keyword stdin: A string to be used as stdin for the command.
 
2076
        :keyword retcode: The status code the command should return;
 
2077
            default 0.
 
2078
        :keyword working_dir: The directory to run the command in
 
2079
        :keyword error_regexes: A list of expected error messages.  If
 
2080
            specified they must be seen in the error output of the command.
1295
2081
        """
1296
 
        retcode = kwargs.pop('retcode', 0)
1297
 
        encoding = kwargs.pop('encoding', None)
1298
 
        stdin = kwargs.pop('stdin', None)
1299
 
        working_dir = kwargs.pop('working_dir', None)
1300
 
        return self.run_bzr_captured(args, retcode=retcode, encoding=encoding,
1301
 
                                     stdin=stdin, working_dir=working_dir)
1302
 
 
1303
 
    def run_bzr_decode(self, *args, **kwargs):
1304
 
        if 'encoding' in kwargs:
1305
 
            encoding = kwargs['encoding']
1306
 
        else:
1307
 
            encoding = bzrlib.user_encoding
1308
 
        return self.run_bzr(*args, **kwargs)[0].decode(encoding)
 
2082
        retcode, out, err = self._run_bzr_autosplit(
 
2083
            args=args,
 
2084
            retcode=retcode,
 
2085
            encoding=encoding,
 
2086
            stdin=stdin,
 
2087
            working_dir=working_dir,
 
2088
            )
 
2089
        self.assertIsInstance(error_regexes, (list, tuple))
 
2090
        for regex in error_regexes:
 
2091
            self.assertContainsRe(err, regex)
 
2092
        return out, err
1309
2093
 
1310
2094
    def run_bzr_error(self, error_regexes, *args, **kwargs):
1311
2095
        """Run bzr, and check that stderr contains the supplied regexes
1312
 
        
1313
 
        :param error_regexes: Sequence of regular expressions which 
 
2096
 
 
2097
        :param error_regexes: Sequence of regular expressions which
1314
2098
            must each be found in the error output. The relative ordering
1315
2099
            is not enforced.
1316
2100
        :param args: command-line arguments for bzr
1317
2101
        :param kwargs: Keyword arguments which are interpreted by run_bzr
1318
2102
            This function changes the default value of retcode to be 3,
1319
2103
            since in most cases this is run when you expect bzr to fail.
1320
 
        :return: (out, err) The actual output of running the command (in case you
1321
 
                 want to do more inspection)
1322
 
 
1323
 
        Examples of use:
 
2104
 
 
2105
        :return: (out, err) The actual output of running the command (in case
 
2106
            you want to do more inspection)
 
2107
 
 
2108
        Examples of use::
 
2109
 
1324
2110
            # Make sure that commit is failing because there is nothing to do
1325
2111
            self.run_bzr_error(['no changes to commit'],
1326
 
                               'commit', '-m', 'my commit comment')
 
2112
                               ['commit', '-m', 'my commit comment'])
1327
2113
            # Make sure --strict is handling an unknown file, rather than
1328
2114
            # giving us the 'nothing to do' error
1329
2115
            self.build_tree(['unknown'])
1330
2116
            self.run_bzr_error(['Commit refused because there are unknown files'],
1331
 
                               'commit', '--strict', '-m', 'my commit comment')
 
2117
                               ['commit', --strict', '-m', 'my commit comment'])
1332
2118
        """
1333
2119
        kwargs.setdefault('retcode', 3)
 
2120
        kwargs['error_regexes'] = error_regexes
1334
2121
        out, err = self.run_bzr(*args, **kwargs)
1335
 
        for regex in error_regexes:
1336
 
            self.assertContainsRe(err, regex)
1337
2122
        return out, err
1338
2123
 
1339
2124
    def run_bzr_subprocess(self, *args, **kwargs):
1340
2125
        """Run bzr in a subprocess for testing.
1341
2126
 
1342
 
        This starts a new Python interpreter and runs bzr in there. 
 
2127
        This starts a new Python interpreter and runs bzr in there.
1343
2128
        This should only be used for tests that have a justifiable need for
1344
2129
        this isolation: e.g. they are testing startup time, or signal
1345
 
        handling, or early startup code, etc.  Subprocess code can't be 
 
2130
        handling, or early startup code, etc.  Subprocess code can't be
1346
2131
        profiled or debugged so easily.
1347
2132
 
1348
 
        :param retcode: The status code that is expected.  Defaults to 0.  If
 
2133
        :keyword retcode: The status code that is expected.  Defaults to 0.  If
1349
2134
            None is supplied, the status code is not checked.
1350
 
        :param env_changes: A dictionary which lists changes to environment
 
2135
        :keyword env_changes: A dictionary which lists changes to environment
1351
2136
            variables. A value of None will unset the env variable.
1352
2137
            The values must be strings. The change will only occur in the
1353
2138
            child, so you don't need to fix the environment after running.
1354
 
        :param universal_newlines: Convert CRLF => LF
1355
 
        :param allow_plugins: By default the subprocess is run with
 
2139
        :keyword universal_newlines: Convert CRLF => LF
 
2140
        :keyword allow_plugins: By default the subprocess is run with
1356
2141
            --no-plugins to ensure test reproducibility. Also, it is possible
1357
2142
            for system-wide plugins to create unexpected output on stderr,
1358
2143
            which can cause unnecessary test failures.
1360
2145
        env_changes = kwargs.get('env_changes', {})
1361
2146
        working_dir = kwargs.get('working_dir', None)
1362
2147
        allow_plugins = kwargs.get('allow_plugins', False)
 
2148
        if len(args) == 1:
 
2149
            if isinstance(args[0], list):
 
2150
                args = args[0]
 
2151
            elif isinstance(args[0], basestring):
 
2152
                args = list(shlex.split(args[0]))
 
2153
        else:
 
2154
            raise ValueError("passing varargs to run_bzr_subprocess")
1363
2155
        process = self.start_bzr_subprocess(args, env_changes=env_changes,
1364
2156
                                            working_dir=working_dir,
1365
2157
                                            allow_plugins=allow_plugins)
1372
2164
    def start_bzr_subprocess(self, process_args, env_changes=None,
1373
2165
                             skip_if_plan_to_signal=False,
1374
2166
                             working_dir=None,
1375
 
                             allow_plugins=False):
 
2167
                             allow_plugins=False, stderr=subprocess.PIPE):
1376
2168
        """Start bzr in a subprocess for testing.
1377
2169
 
1378
2170
        This starts a new Python interpreter and runs bzr in there.
1382
2174
        profiled or debugged so easily.
1383
2175
 
1384
2176
        :param process_args: a list of arguments to pass to the bzr executable,
1385
 
            for example `['--version']`.
 
2177
            for example ``['--version']``.
1386
2178
        :param env_changes: A dictionary which lists changes to environment
1387
2179
            variables. A value of None will unset the env variable.
1388
2180
            The values must be strings. The change will only occur in the
1389
2181
            child, so you don't need to fix the environment after running.
1390
 
        :param skip_if_plan_to_signal: raise TestSkipped when true and os.kill
1391
 
            is not available.
 
2182
        :param skip_if_plan_to_signal: raise TestSkipped when true and system
 
2183
            doesn't support signalling subprocesses.
1392
2184
        :param allow_plugins: If False (default) pass --no-plugins to bzr.
 
2185
        :param stderr: file to use for the subprocess's stderr.  Valid values
 
2186
            are those valid for the stderr argument of `subprocess.Popen`.
 
2187
            Default value is ``subprocess.PIPE``.
1393
2188
 
1394
2189
        :returns: Popen object for the started process.
1395
2190
        """
1396
2191
        if skip_if_plan_to_signal:
1397
 
            if not getattr(os, 'kill', None):
1398
 
                raise TestSkipped("os.kill not available.")
 
2192
            if os.name != "posix":
 
2193
                raise TestSkipped("Sending signals not supported")
1399
2194
 
1400
2195
        if env_changes is None:
1401
2196
            env_changes = {}
 
2197
        # Because $HOME is set to a tempdir for the context of a test, modules
 
2198
        # installed in the user dir will not be found unless $PYTHONUSERBASE
 
2199
        # gets set to the computed directory of this parent process.
 
2200
        if site.USER_BASE is not None:
 
2201
            env_changes["PYTHONUSERBASE"] = site.USER_BASE
1402
2202
        old_env = {}
1403
2203
 
1404
2204
        def cleanup_environment():
1421
2221
            # so we will avoid using it on all platforms, just to
1422
2222
            # make sure the code path is used, and we don't break on win32
1423
2223
            cleanup_environment()
1424
 
            command = [sys.executable, bzr_path]
 
2224
            # Include the subprocess's log file in the test details, in case
 
2225
            # the test fails due to an error in the subprocess.
 
2226
            self._add_subprocess_log(trace._get_bzr_log_filename())
 
2227
            command = [sys.executable]
 
2228
            # frozen executables don't need the path to bzr
 
2229
            if getattr(sys, "frozen", None) is None:
 
2230
                command.append(bzr_path)
1425
2231
            if not allow_plugins:
1426
2232
                command.append('--no-plugins')
1427
2233
            command.extend(process_args)
1428
 
            process = self._popen(command, stdin=PIPE, stdout=PIPE, stderr=PIPE)
 
2234
            process = self._popen(command, stdin=subprocess.PIPE,
 
2235
                                  stdout=subprocess.PIPE,
 
2236
                                  stderr=stderr)
1429
2237
        finally:
1430
2238
            restore_environment()
1431
2239
            if cwd is not None:
1433
2241
 
1434
2242
        return process
1435
2243
 
 
2244
    def _add_subprocess_log(self, log_file_path):
 
2245
        if len(self._log_files) == 0:
 
2246
            # Register an addCleanup func.  We do this on the first call to
 
2247
            # _add_subprocess_log rather than in TestCase.setUp so that this
 
2248
            # addCleanup is registered after any cleanups for tempdirs that
 
2249
            # subclasses might create, which will probably remove the log file
 
2250
            # we want to read.
 
2251
            self.addCleanup(self._subprocess_log_cleanup)
 
2252
        # self._log_files is a set, so if a log file is reused we won't grab it
 
2253
        # twice.
 
2254
        self._log_files.add(log_file_path)
 
2255
 
 
2256
    def _subprocess_log_cleanup(self):
 
2257
        for count, log_file_path in enumerate(self._log_files):
 
2258
            # We use buffer_now=True to avoid holding the file open beyond
 
2259
            # the life of this function, which might interfere with e.g.
 
2260
            # cleaning tempdirs on Windows.
 
2261
            # XXX: Testtools 0.9.5 doesn't have the content_from_file helper
 
2262
            #detail_content = content.content_from_file(
 
2263
            #    log_file_path, buffer_now=True)
 
2264
            with open(log_file_path, 'rb') as log_file:
 
2265
                log_file_bytes = log_file.read()
 
2266
            detail_content = content.Content(content.ContentType("text",
 
2267
                "plain", {"charset": "utf8"}), lambda: [log_file_bytes])
 
2268
            self.addDetail("start_bzr_subprocess-log-%d" % (count,),
 
2269
                detail_content)
 
2270
 
1436
2271
    def _popen(self, *args, **kwargs):
1437
2272
        """Place a call to Popen.
1438
2273
 
1439
2274
        Allows tests to override this method to intercept the calls made to
1440
2275
        Popen for introspection.
1441
2276
        """
1442
 
        return Popen(*args, **kwargs)
 
2277
        return subprocess.Popen(*args, **kwargs)
 
2278
 
 
2279
    def get_source_path(self):
 
2280
        """Return the path of the directory containing bzrlib."""
 
2281
        return os.path.dirname(os.path.dirname(bzrlib.__file__))
1443
2282
 
1444
2283
    def get_bzr_path(self):
1445
2284
        """Return the path of the 'bzr' executable for this test suite."""
1446
 
        bzr_path = os.path.dirname(os.path.dirname(bzrlib.__file__))+'/bzr'
 
2285
        bzr_path = os.path.join(self.get_source_path(), "bzr")
1447
2286
        if not os.path.isfile(bzr_path):
1448
2287
            # We are probably installed. Assume sys.argv is the right file
1449
2288
            bzr_path = sys.argv[0]
1471
2310
        if retcode is not None and retcode != process.returncode:
1472
2311
            if process_args is None:
1473
2312
                process_args = "(unknown args)"
1474
 
            mutter('Output of bzr %s:\n%s', process_args, out)
1475
 
            mutter('Error for bzr %s:\n%s', process_args, err)
 
2313
            trace.mutter('Output of bzr %s:\n%s', process_args, out)
 
2314
            trace.mutter('Error for bzr %s:\n%s', process_args, err)
1476
2315
            self.fail('Command bzr %s failed with retcode %s != %s'
1477
2316
                      % (process_args, retcode, process.returncode))
1478
2317
        return [out, err]
1479
2318
 
1480
 
    def check_inventory_shape(self, inv, shape):
1481
 
        """Compare an inventory to a list of expected names.
 
2319
    def check_tree_shape(self, tree, shape):
 
2320
        """Compare a tree to a list of expected names.
1482
2321
 
1483
2322
        Fail if they are not precisely equal.
1484
2323
        """
1485
2324
        extras = []
1486
2325
        shape = list(shape)             # copy
1487
 
        for path, ie in inv.entries():
 
2326
        for path, ie in tree.iter_entries_by_dir():
1488
2327
            name = path.replace('\\', '/')
1489
 
            if ie.kind == 'dir':
 
2328
            if ie.kind == 'directory':
1490
2329
                name = name + '/'
1491
 
            if name in shape:
 
2330
            if name == "/":
 
2331
                pass # ignore root entry
 
2332
            elif name in shape:
1492
2333
                shape.remove(name)
1493
2334
            else:
1494
2335
                extras.append(name)
1529
2370
            sys.stderr = real_stderr
1530
2371
            sys.stdin = real_stdin
1531
2372
 
1532
 
    @symbol_versioning.deprecated_method(symbol_versioning.zero_eleven)
1533
 
    def merge(self, branch_from, wt_to):
1534
 
        """A helper for tests to do a ui-less merge.
1535
 
 
1536
 
        This should move to the main library when someone has time to integrate
1537
 
        it in.
1538
 
        """
1539
 
        # minimal ui-less merge.
1540
 
        wt_to.branch.fetch(branch_from)
1541
 
        base_rev = common_ancestor(branch_from.last_revision(),
1542
 
                                   wt_to.branch.last_revision(),
1543
 
                                   wt_to.branch.repository)
1544
 
        merge_inner(wt_to.branch, branch_from.basis_tree(),
1545
 
                    wt_to.branch.repository.revision_tree(base_rev),
1546
 
                    this_tree=wt_to)
1547
 
        wt_to.add_parent_tree_id(branch_from.last_revision())
1548
 
 
1549
2373
    def reduceLockdirTimeout(self):
1550
2374
        """Reduce the default lock timeout for the duration of the test, so that
1551
2375
        if LockContention occurs during a test, it does so quickly.
1552
2376
 
1553
2377
        Tests that expect to provoke LockContention errors should call this.
1554
2378
        """
1555
 
        orig_timeout = bzrlib.lockdir._DEFAULT_TIMEOUT_SECONDS
1556
 
        def resetTimeout():
1557
 
            bzrlib.lockdir._DEFAULT_TIMEOUT_SECONDS = orig_timeout
1558
 
        self.addCleanup(resetTimeout)
1559
 
        bzrlib.lockdir._DEFAULT_TIMEOUT_SECONDS = 0
1560
 
 
1561
 
BzrTestBase = TestCase
 
2379
        self.overrideAttr(lockdir, '_DEFAULT_TIMEOUT_SECONDS', 0)
 
2380
 
 
2381
    def make_utf8_encoded_stringio(self, encoding_type=None):
 
2382
        """Return a StringIOWrapper instance, that will encode Unicode
 
2383
        input to UTF-8.
 
2384
        """
 
2385
        if encoding_type is None:
 
2386
            encoding_type = 'strict'
 
2387
        sio = StringIO()
 
2388
        output_encoding = 'utf-8'
 
2389
        sio = codecs.getwriter(output_encoding)(sio, errors=encoding_type)
 
2390
        sio.encoding = output_encoding
 
2391
        return sio
 
2392
 
 
2393
    def disable_verb(self, verb):
 
2394
        """Disable a smart server verb for one test."""
 
2395
        from bzrlib.smart import request
 
2396
        request_handlers = request.request_handlers
 
2397
        orig_method = request_handlers.get(verb)
 
2398
        orig_info = request_handlers.get_info(verb)
 
2399
        request_handlers.remove(verb)
 
2400
        self.addCleanup(request_handlers.register, verb, orig_method,
 
2401
            info=orig_info)
 
2402
 
 
2403
 
 
2404
class CapturedCall(object):
 
2405
    """A helper for capturing smart server calls for easy debug analysis."""
 
2406
 
 
2407
    def __init__(self, params, prefix_length):
 
2408
        """Capture the call with params and skip prefix_length stack frames."""
 
2409
        self.call = params
 
2410
        import traceback
 
2411
        # The last 5 frames are the __init__, the hook frame, and 3 smart
 
2412
        # client frames. Beyond this we could get more clever, but this is good
 
2413
        # enough for now.
 
2414
        stack = traceback.extract_stack()[prefix_length:-5]
 
2415
        self.stack = ''.join(traceback.format_list(stack))
 
2416
 
 
2417
    def __str__(self):
 
2418
        return self.call.method
 
2419
 
 
2420
    def __repr__(self):
 
2421
        return self.call.method
 
2422
 
 
2423
    def stack(self):
 
2424
        return self.stack
1562
2425
 
1563
2426
 
1564
2427
class TestCaseWithMemoryTransport(TestCase):
1565
2428
    """Common test class for tests that do not need disk resources.
1566
2429
 
1567
 
    Tests that need disk resources should derive from TestCaseWithTransport.
 
2430
    Tests that need disk resources should derive from TestCaseInTempDir
 
2431
    orTestCaseWithTransport.
1568
2432
 
1569
2433
    TestCaseWithMemoryTransport sets the TEST_ROOT variable for all bzr tests.
1570
2434
 
1571
 
    For TestCaseWithMemoryTransport the test_home_dir is set to the name of
 
2435
    For TestCaseWithMemoryTransport the ``test_home_dir`` is set to the name of
1572
2436
    a directory which does not exist. This serves to help ensure test isolation
1573
 
    is preserved. test_dir is set to the TEST_ROOT, as is cwd, because they
1574
 
    must exist. However, TestCaseWithMemoryTransport does not offer local
1575
 
    file defaults for the transport in tests, nor does it obey the command line
 
2437
    is preserved. ``test_dir`` is set to the TEST_ROOT, as is cwd, because they
 
2438
    must exist. However, TestCaseWithMemoryTransport does not offer local file
 
2439
    defaults for the transport in tests, nor does it obey the command line
1576
2440
    override, so tests that accidentally write to the common directory should
1577
2441
    be rare.
 
2442
 
 
2443
    :cvar TEST_ROOT: Directory containing all temporary directories, plus a
 
2444
        ``.bzr`` directory that stops us ascending higher into the filesystem.
1578
2445
    """
1579
2446
 
1580
2447
    TEST_ROOT = None
1581
2448
    _TEST_NAME = 'test'
1582
2449
 
1583
 
 
1584
2450
    def __init__(self, methodName='runTest'):
1585
 
        # allow test parameterisation after test construction and before test
1586
 
        # execution. Variables that the parameteriser sets need to be 
 
2451
        # allow test parameterization after test construction and before test
 
2452
        # execution. Variables that the parameterizer sets need to be
1587
2453
        # ones that are not set by setUp, or setUp will trash them.
1588
2454
        super(TestCaseWithMemoryTransport, self).__init__(methodName)
1589
2455
        self.vfs_transport_factory = default_transport
1591
2457
        self.transport_readonly_server = None
1592
2458
        self.__vfs_server = None
1593
2459
 
1594
 
    def get_transport(self):
1595
 
        """Return a writeable transport for the test scratch space"""
1596
 
        t = get_transport(self.get_url())
 
2460
    def get_transport(self, relpath=None):
 
2461
        """Return a writeable transport.
 
2462
 
 
2463
        This transport is for the test scratch space relative to
 
2464
        "self._test_root"
 
2465
 
 
2466
        :param relpath: a path relative to the base url.
 
2467
        """
 
2468
        t = _mod_transport.get_transport_from_url(self.get_url(relpath))
1597
2469
        self.assertFalse(t.is_readonly())
1598
2470
        return t
1599
2471
 
1600
 
    def get_readonly_transport(self):
 
2472
    def get_readonly_transport(self, relpath=None):
1601
2473
        """Return a readonly transport for the test scratch space
1602
 
        
 
2474
 
1603
2475
        This can be used to test that operations which should only need
1604
2476
        readonly access in fact do not try to write.
 
2477
 
 
2478
        :param relpath: a path relative to the base url.
1605
2479
        """
1606
 
        t = get_transport(self.get_readonly_url())
 
2480
        t = _mod_transport.get_transport_from_url(
 
2481
            self.get_readonly_url(relpath))
1607
2482
        self.assertTrue(t.is_readonly())
1608
2483
        return t
1609
2484
 
1622
2497
        if self.__readonly_server is None:
1623
2498
            if self.transport_readonly_server is None:
1624
2499
                # readonly decorator requested
1625
 
                # bring up the server
1626
 
                self.__readonly_server = ReadonlyServer()
1627
 
                self.__readonly_server.setUp(self.get_vfs_only_server())
 
2500
                self.__readonly_server = test_server.ReadonlyServer()
1628
2501
            else:
 
2502
                # explicit readonly transport.
1629
2503
                self.__readonly_server = self.create_transport_readonly_server()
1630
 
                self.__readonly_server.setUp(self.get_vfs_only_server())
1631
 
            self.addCleanup(self.__readonly_server.tearDown)
 
2504
            self.start_server(self.__readonly_server,
 
2505
                self.get_vfs_only_server())
1632
2506
        return self.__readonly_server
1633
2507
 
1634
2508
    def get_readonly_url(self, relpath=None):
1635
2509
        """Get a URL for the readonly transport.
1636
2510
 
1637
 
        This will either be backed by '.' or a decorator to the transport 
 
2511
        This will either be backed by '.' or a decorator to the transport
1638
2512
        used by self.get_url()
1639
2513
        relpath provides for clients to get a path relative to the base url.
1640
2514
        These should only be downwards relative, not upwards.
1641
2515
        """
1642
2516
        base = self.get_readonly_server().get_url()
1643
 
        if relpath is not None:
1644
 
            if not base.endswith('/'):
1645
 
                base = base + '/'
1646
 
            base = base + relpath
1647
 
        return base
 
2517
        return self._adjust_url(base, relpath)
1648
2518
 
1649
2519
    def get_vfs_only_server(self):
1650
2520
        """Get the vfs only read/write server instance.
1656
2526
        is no means to override it.
1657
2527
        """
1658
2528
        if self.__vfs_server is None:
1659
 
            self.__vfs_server = MemoryServer()
1660
 
            self.__vfs_server.setUp()
1661
 
            self.addCleanup(self.__vfs_server.tearDown)
 
2529
            self.__vfs_server = memory.MemoryServer()
 
2530
            self.start_server(self.__vfs_server)
1662
2531
        return self.__vfs_server
1663
2532
 
1664
2533
    def get_server(self):
1671
2540
        then the self.get_vfs_server is returned.
1672
2541
        """
1673
2542
        if self.__server is None:
1674
 
            if self.transport_server is None or self.transport_server is self.vfs_transport_factory:
1675
 
                return self.get_vfs_only_server()
 
2543
            if (self.transport_server is None or self.transport_server is
 
2544
                self.vfs_transport_factory):
 
2545
                self.__server = self.get_vfs_only_server()
1676
2546
            else:
1677
2547
                # bring up a decorated means of access to the vfs only server.
1678
2548
                self.__server = self.transport_server()
1679
 
                try:
1680
 
                    self.__server.setUp(self.get_vfs_only_server())
1681
 
                except TypeError, e:
1682
 
                    # This should never happen; the try:Except here is to assist
1683
 
                    # developers having to update code rather than seeing an
1684
 
                    # uninformative TypeError.
1685
 
                    raise Exception, "Old server API in use: %s, %s" % (self.__server, e)
1686
 
            self.addCleanup(self.__server.tearDown)
 
2549
                self.start_server(self.__server, self.get_vfs_only_server())
1687
2550
        return self.__server
1688
2551
 
1689
2552
    def _adjust_url(self, base, relpath):
1721
2584
    def get_vfs_only_url(self, relpath=None):
1722
2585
        """Get a URL (or maybe a path for the plain old vfs transport.
1723
2586
 
1724
 
        This will never be a smart protocol.
 
2587
        This will never be a smart protocol.  It always has all the
 
2588
        capabilities of the local filesystem, but it might actually be a
 
2589
        MemoryTransport or some other similar virtual filesystem.
 
2590
 
 
2591
        This is the backing transport (if any) of the server returned by
 
2592
        get_url and get_readonly_url.
 
2593
 
1725
2594
        :param relpath: provides for clients to get a path relative to the base
1726
2595
            url.  These should only be downwards relative, not upwards.
 
2596
        :return: A URL
1727
2597
        """
1728
2598
        base = self.get_vfs_only_server().get_url()
1729
2599
        return self._adjust_url(base, relpath)
1730
2600
 
 
2601
    def _create_safety_net(self):
 
2602
        """Make a fake bzr directory.
 
2603
 
 
2604
        This prevents any tests propagating up onto the TEST_ROOT directory's
 
2605
        real branch.
 
2606
        """
 
2607
        root = TestCaseWithMemoryTransport.TEST_ROOT
 
2608
        # Make sure we get a readable and accessible home for .bzr.log
 
2609
        # and/or config files, and not fallback to weird defaults (see
 
2610
        # http://pad.lv/825027).
 
2611
        self.assertIs(None, os.environ.get('BZR_HOME', None))
 
2612
        os.environ['BZR_HOME'] = root
 
2613
        wt = bzrdir.BzrDir.create_standalone_workingtree(root)
 
2614
        del os.environ['BZR_HOME']
 
2615
        # Hack for speed: remember the raw bytes of the dirstate file so that
 
2616
        # we don't need to re-open the wt to check it hasn't changed.
 
2617
        TestCaseWithMemoryTransport._SAFETY_NET_PRISTINE_DIRSTATE = (
 
2618
            wt.control_transport.get_bytes('dirstate'))
 
2619
 
 
2620
    def _check_safety_net(self):
 
2621
        """Check that the safety .bzr directory have not been touched.
 
2622
 
 
2623
        _make_test_root have created a .bzr directory to prevent tests from
 
2624
        propagating. This method ensures than a test did not leaked.
 
2625
        """
 
2626
        root = TestCaseWithMemoryTransport.TEST_ROOT
 
2627
        t = _mod_transport.get_transport_from_path(root)
 
2628
        self.permit_url(t.base)
 
2629
        if (t.get_bytes('.bzr/checkout/dirstate') != 
 
2630
                TestCaseWithMemoryTransport._SAFETY_NET_PRISTINE_DIRSTATE):
 
2631
            # The current test have modified the /bzr directory, we need to
 
2632
            # recreate a new one or all the followng tests will fail.
 
2633
            # If you need to inspect its content uncomment the following line
 
2634
            # import pdb; pdb.set_trace()
 
2635
            _rmtree_temp_dir(root + '/.bzr', test_id=self.id())
 
2636
            self._create_safety_net()
 
2637
            raise AssertionError('%s/.bzr should not be modified' % root)
 
2638
 
1731
2639
    def _make_test_root(self):
1732
 
        if TestCaseWithMemoryTransport.TEST_ROOT is not None:
1733
 
            return
1734
 
        i = 0
1735
 
        while True:
1736
 
            root = u'test%04d.tmp' % i
1737
 
            try:
1738
 
                os.mkdir(root)
1739
 
            except OSError, e:
1740
 
                if e.errno == errno.EEXIST:
1741
 
                    i += 1
1742
 
                    continue
1743
 
                else:
1744
 
                    raise
1745
 
            # successfully created
1746
 
            TestCaseWithMemoryTransport.TEST_ROOT = osutils.abspath(root)
1747
 
            break
1748
 
        # make a fake bzr directory there to prevent any tests propagating
1749
 
        # up onto the source directory's real branch
1750
 
        bzrdir.BzrDir.create_standalone_workingtree(
1751
 
            TestCaseWithMemoryTransport.TEST_ROOT)
 
2640
        if TestCaseWithMemoryTransport.TEST_ROOT is None:
 
2641
            # Watch out for tricky test dir (on OSX /tmp -> /private/tmp)
 
2642
            root = osutils.realpath(osutils.mkdtemp(prefix='testbzr-',
 
2643
                                                    suffix='.tmp'))
 
2644
            TestCaseWithMemoryTransport.TEST_ROOT = root
 
2645
 
 
2646
            self._create_safety_net()
 
2647
 
 
2648
            # The same directory is used by all tests, and we're not
 
2649
            # specifically told when all tests are finished.  This will do.
 
2650
            atexit.register(_rmtree_temp_dir, root)
 
2651
 
 
2652
        self.permit_dir(TestCaseWithMemoryTransport.TEST_ROOT)
 
2653
        self.addCleanup(self._check_safety_net)
1752
2654
 
1753
2655
    def makeAndChdirToTestDir(self):
1754
2656
        """Create a temporary directories for this one test.
1755
 
        
 
2657
 
1756
2658
        This must set self.test_home_dir and self.test_dir and chdir to
1757
2659
        self.test_dir.
1758
 
        
 
2660
 
1759
2661
        For TestCaseWithMemoryTransport we chdir to the TEST_ROOT for this test.
1760
2662
        """
1761
2663
        os.chdir(TestCaseWithMemoryTransport.TEST_ROOT)
1762
2664
        self.test_dir = TestCaseWithMemoryTransport.TEST_ROOT
1763
2665
        self.test_home_dir = self.test_dir + "/MemoryTransportMissingHomeDir"
1764
 
        
1765
 
    def make_branch(self, relpath, format=None):
 
2666
        self.permit_dir(self.test_dir)
 
2667
 
 
2668
    def make_branch(self, relpath, format=None, name=None):
1766
2669
        """Create a branch on the transport at relpath."""
1767
2670
        repo = self.make_repository(relpath, format=format)
1768
 
        return repo.bzrdir.create_branch()
 
2671
        return repo.bzrdir.create_branch(append_revisions_only=False,
 
2672
                                         name=name)
 
2673
 
 
2674
    def get_default_format(self):
 
2675
        return 'default'
 
2676
 
 
2677
    def resolve_format(self, format):
 
2678
        """Resolve an object to a ControlDir format object.
 
2679
 
 
2680
        The initial format object can either already be
 
2681
        a ControlDirFormat, None (for the default format),
 
2682
        or a string with the name of the control dir format.
 
2683
 
 
2684
        :param format: Object to resolve
 
2685
        :return A ControlDirFormat instance
 
2686
        """
 
2687
        if format is None:
 
2688
            format = self.get_default_format()
 
2689
        if isinstance(format, basestring):
 
2690
            format = bzrdir.format_registry.make_bzrdir(format)
 
2691
        return format
1769
2692
 
1770
2693
    def make_bzrdir(self, relpath, format=None):
1771
2694
        try:
1772
2695
            # might be a relative or absolute path
1773
2696
            maybe_a_url = self.get_url(relpath)
1774
2697
            segments = maybe_a_url.rsplit('/', 1)
1775
 
            t = get_transport(maybe_a_url)
 
2698
            t = _mod_transport.get_transport(maybe_a_url)
1776
2699
            if len(segments) > 1 and segments[-1] not in ('', '.'):
1777
 
                try:
1778
 
                    t.mkdir('.')
1779
 
                except errors.FileExists:
1780
 
                    pass
1781
 
            if format is None:
1782
 
                format = 'default'
1783
 
            if isinstance(format, basestring):
1784
 
                format = bzrdir.format_registry.make_bzrdir(format)
 
2700
                t.ensure_base()
 
2701
            format = self.resolve_format(format)
1785
2702
            return format.initialize_on_transport(t)
1786
2703
        except errors.UninitializableFormat:
1787
2704
            raise TestSkipped("Format %s is not initializable." % format)
1788
2705
 
1789
 
    def make_repository(self, relpath, shared=False, format=None):
1790
 
        """Create a repository on our default transport at relpath."""
 
2706
    def make_repository(self, relpath, shared=None, format=None):
 
2707
        """Create a repository on our default transport at relpath.
 
2708
 
 
2709
        Note that relpath must be a relative path, not a full url.
 
2710
        """
 
2711
        # FIXME: If you create a remoterepository this returns the underlying
 
2712
        # real format, which is incorrect.  Actually we should make sure that
 
2713
        # RemoteBzrDir returns a RemoteRepository.
 
2714
        # maybe  mbp 20070410
1791
2715
        made_control = self.make_bzrdir(relpath, format=format)
1792
2716
        return made_control.create_repository(shared=shared)
1793
2717
 
 
2718
    def make_smart_server(self, path, backing_server=None):
 
2719
        if backing_server is None:
 
2720
            backing_server = self.get_server()
 
2721
        smart_server = test_server.SmartTCPServer_for_testing()
 
2722
        self.start_server(smart_server, backing_server)
 
2723
        remote_transport = _mod_transport.get_transport_from_url(smart_server.get_url()
 
2724
                                                   ).clone(path)
 
2725
        return remote_transport
 
2726
 
1794
2727
    def make_branch_and_memory_tree(self, relpath, format=None):
1795
2728
        """Create a branch on the default transport and a MemoryTree for it."""
1796
2729
        b = self.make_branch(relpath, format=format)
1797
2730
        return memorytree.MemoryTree.create_on_branch(b)
1798
2731
 
 
2732
    def make_branch_builder(self, relpath, format=None):
 
2733
        branch = self.make_branch(relpath, format=format)
 
2734
        return branchbuilder.BranchBuilder(branch=branch)
 
2735
 
1799
2736
    def overrideEnvironmentForTesting(self):
1800
 
        os.environ['HOME'] = self.test_home_dir
1801
 
        os.environ['BZR_HOME'] = self.test_home_dir
1802
 
        
 
2737
        test_home_dir = self.test_home_dir
 
2738
        if isinstance(test_home_dir, unicode):
 
2739
            test_home_dir = test_home_dir.encode(sys.getfilesystemencoding())
 
2740
        self.overrideEnv('HOME', test_home_dir)
 
2741
        self.overrideEnv('BZR_HOME', test_home_dir)
 
2742
 
1803
2743
    def setUp(self):
1804
2744
        super(TestCaseWithMemoryTransport, self).setUp()
 
2745
 
 
2746
        def _add_disconnect_cleanup(transport):
 
2747
            """Schedule disconnection of given transport at test cleanup
 
2748
 
 
2749
            This needs to happen for all connected transports or leaks occur.
 
2750
 
 
2751
            Note reconnections may mean we call disconnect multiple times per
 
2752
            transport which is suboptimal but seems harmless.
 
2753
            """
 
2754
            self.addCleanup(transport.disconnect)
 
2755
 
 
2756
        _mod_transport.Transport.hooks.install_named_hook('post_connect',
 
2757
            _add_disconnect_cleanup, None)
 
2758
 
1805
2759
        self._make_test_root()
1806
 
        _currentdir = os.getcwdu()
1807
 
        def _leaveDirectory():
1808
 
            os.chdir(_currentdir)
1809
 
        self.addCleanup(_leaveDirectory)
 
2760
        self.addCleanup(os.chdir, os.getcwdu())
1810
2761
        self.makeAndChdirToTestDir()
1811
2762
        self.overrideEnvironmentForTesting()
1812
2763
        self.__readonly_server = None
1813
2764
        self.__server = None
1814
2765
        self.reduceLockdirTimeout()
1815
2766
 
1816
 
     
 
2767
    def setup_smart_server_with_call_log(self):
 
2768
        """Sets up a smart server as the transport server with a call log."""
 
2769
        self.transport_server = test_server.SmartTCPServer_for_testing
 
2770
        self.hpss_connections = []
 
2771
        self.hpss_calls = []
 
2772
        import traceback
 
2773
        # Skip the current stack down to the caller of
 
2774
        # setup_smart_server_with_call_log
 
2775
        prefix_length = len(traceback.extract_stack()) - 2
 
2776
        def capture_hpss_call(params):
 
2777
            self.hpss_calls.append(
 
2778
                CapturedCall(params, prefix_length))
 
2779
        def capture_connect(transport):
 
2780
            self.hpss_connections.append(transport)
 
2781
        client._SmartClient.hooks.install_named_hook(
 
2782
            'call', capture_hpss_call, None)
 
2783
        _mod_transport.Transport.hooks.install_named_hook(
 
2784
            'post_connect', capture_connect, None)
 
2785
 
 
2786
    def reset_smart_call_log(self):
 
2787
        self.hpss_calls = []
 
2788
        self.hpss_connections = []
 
2789
 
 
2790
 
1817
2791
class TestCaseInTempDir(TestCaseWithMemoryTransport):
1818
2792
    """Derived class that runs a test within a temporary directory.
1819
2793
 
1824
2798
    All test cases create their own directory within that.  If the
1825
2799
    tests complete successfully, the directory is removed.
1826
2800
 
1827
 
    InTempDir is an old alias for FunctionalTestCase.
 
2801
    :ivar test_base_dir: The path of the top-level directory for this
 
2802
    test, which contains a home directory and a work directory.
 
2803
 
 
2804
    :ivar test_home_dir: An initially empty directory under test_base_dir
 
2805
    which is used as $HOME for this test.
 
2806
 
 
2807
    :ivar test_dir: A directory under test_base_dir used as the current
 
2808
    directory when the test proper is run.
1828
2809
    """
1829
2810
 
1830
2811
    OVERRIDE_PYTHON = 'python'
1831
 
    use_numbered_dirs = False
 
2812
 
 
2813
    def setUp(self):
 
2814
        super(TestCaseInTempDir, self).setUp()
 
2815
        # Remove the protection set in isolated_environ, we have a proper
 
2816
        # access to disk resources now.
 
2817
        self.overrideEnv('BZR_LOG', None)
1832
2818
 
1833
2819
    def check_file_contents(self, filename, expect):
1834
2820
        self.log("check contents of file %s" % filename)
1835
 
        contents = file(filename, 'r').read()
 
2821
        f = file(filename)
 
2822
        try:
 
2823
            contents = f.read()
 
2824
        finally:
 
2825
            f.close()
1836
2826
        if contents != expect:
1837
2827
            self.log("expected: %r" % expect)
1838
2828
            self.log("actually: %r" % contents)
1839
2829
            self.fail("contents of %s not as expected" % filename)
1840
2830
 
 
2831
    def _getTestDirPrefix(self):
 
2832
        # create a directory within the top level test directory
 
2833
        if sys.platform in ('win32', 'cygwin'):
 
2834
            name_prefix = re.sub('[<>*=+",:;_/\\-]', '_', self.id())
 
2835
            # windows is likely to have path-length limits so use a short name
 
2836
            name_prefix = name_prefix[-30:]
 
2837
        else:
 
2838
            name_prefix = re.sub('[/]', '_', self.id())
 
2839
        return name_prefix
 
2840
 
1841
2841
    def makeAndChdirToTestDir(self):
1842
2842
        """See TestCaseWithMemoryTransport.makeAndChdirToTestDir().
1843
 
        
 
2843
 
1844
2844
        For TestCaseInTempDir we create a temporary directory based on the test
1845
2845
        name and then create two subdirs - test and home under it.
1846
2846
        """
1847
 
        if self.use_numbered_dirs:  # strongly recommended on Windows
1848
 
                                    # due the path length limitation (260 ch.)
1849
 
            candidate_dir = '%s/%dK/%05d' % (self.TEST_ROOT,
1850
 
                                             int(self.number/1000),
1851
 
                                             self.number)
1852
 
            os.makedirs(candidate_dir)
1853
 
            self.test_home_dir = candidate_dir + '/home'
1854
 
            os.mkdir(self.test_home_dir)
1855
 
            self.test_dir = candidate_dir + '/work'
1856
 
            os.mkdir(self.test_dir)
1857
 
            os.chdir(self.test_dir)
1858
 
            # put name of test inside
1859
 
            f = file(candidate_dir + '/name', 'w')
 
2847
        name_prefix = osutils.pathjoin(TestCaseWithMemoryTransport.TEST_ROOT,
 
2848
            self._getTestDirPrefix())
 
2849
        name = name_prefix
 
2850
        for i in range(100):
 
2851
            if os.path.exists(name):
 
2852
                name = name_prefix + '_' + str(i)
 
2853
            else:
 
2854
                # now create test and home directories within this dir
 
2855
                self.test_base_dir = name
 
2856
                self.addCleanup(self.deleteTestDir)
 
2857
                os.mkdir(self.test_base_dir)
 
2858
                break
 
2859
        self.permit_dir(self.test_base_dir)
 
2860
        # 'sprouting' and 'init' of a branch both walk up the tree to find
 
2861
        # stacking policy to honour; create a bzr dir with an unshared
 
2862
        # repository (but not a branch - our code would be trying to escape
 
2863
        # then!) to stop them, and permit it to be read.
 
2864
        # control = bzrdir.BzrDir.create(self.test_base_dir)
 
2865
        # control.create_repository()
 
2866
        self.test_home_dir = self.test_base_dir + '/home'
 
2867
        os.mkdir(self.test_home_dir)
 
2868
        self.test_dir = self.test_base_dir + '/work'
 
2869
        os.mkdir(self.test_dir)
 
2870
        os.chdir(self.test_dir)
 
2871
        # put name of test inside
 
2872
        f = file(self.test_base_dir + '/name', 'w')
 
2873
        try:
1860
2874
            f.write(self.id())
 
2875
        finally:
1861
2876
            f.close()
1862
 
            return
1863
 
        # Else NAMED DIRS
1864
 
        # shorten the name, to avoid test failures due to path length
1865
 
        short_id = self.id().replace('bzrlib.tests.', '') \
1866
 
                   .replace('__main__.', '')[-100:]
1867
 
        # it's possible the same test class is run several times for
1868
 
        # parameterized tests, so make sure the names don't collide.  
1869
 
        i = 0
1870
 
        while True:
1871
 
            if i > 0:
1872
 
                candidate_dir = '%s/%s.%d' % (self.TEST_ROOT, short_id, i)
1873
 
            else:
1874
 
                candidate_dir = '%s/%s' % (self.TEST_ROOT, short_id)
1875
 
            if os.path.exists(candidate_dir):
1876
 
                i = i + 1
1877
 
                continue
1878
 
            else:
1879
 
                os.mkdir(candidate_dir)
1880
 
                self.test_home_dir = candidate_dir + '/home'
1881
 
                os.mkdir(self.test_home_dir)
1882
 
                self.test_dir = candidate_dir + '/work'
1883
 
                os.mkdir(self.test_dir)
1884
 
                os.chdir(self.test_dir)
1885
 
                break
 
2877
 
 
2878
    def deleteTestDir(self):
 
2879
        os.chdir(TestCaseWithMemoryTransport.TEST_ROOT)
 
2880
        _rmtree_temp_dir(self.test_base_dir, test_id=self.id())
1886
2881
 
1887
2882
    def build_tree(self, shape, line_endings='binary', transport=None):
1888
2883
        """Build a test tree according to a pattern.
1893
2888
        This assumes that all the elements in the tree being built are new.
1894
2889
 
1895
2890
        This doesn't add anything to a branch.
 
2891
 
 
2892
        :type shape:    list or tuple.
1896
2893
        :param line_endings: Either 'binary' or 'native'
1897
 
                             in binary mode, exact contents are written
1898
 
                             in native mode, the line endings match the
1899
 
                             default platform endings.
1900
 
 
1901
 
        :param transport: A transport to write to, for building trees on 
1902
 
                          VFS's. If the transport is readonly or None,
1903
 
                          "." is opened automatically.
 
2894
            in binary mode, exact contents are written in native mode, the
 
2895
            line endings match the default platform endings.
 
2896
        :param transport: A transport to write to, for building trees on VFS's.
 
2897
            If the transport is readonly or None, "." is opened automatically.
 
2898
        :return: None
1904
2899
        """
 
2900
        if type(shape) not in (list, tuple):
 
2901
            raise AssertionError("Parameter 'shape' should be "
 
2902
                "a list or a tuple. Got %r instead" % (shape,))
1905
2903
        # It's OK to just create them using forward slashes on windows.
1906
2904
        if transport is None or transport.is_readonly():
1907
 
            transport = get_transport(".")
 
2905
            transport = _mod_transport.get_transport_from_path(".")
1908
2906
        for name in shape:
1909
 
            self.assert_(isinstance(name, basestring))
 
2907
            self.assertIsInstance(name, basestring)
1910
2908
            if name[-1] == '/':
1911
2909
                transport.mkdir(urlutils.escape(name[:-1]))
1912
2910
            else:
1920
2918
                content = "contents of %s%s" % (name.encode('utf-8'), end)
1921
2919
                transport.put_bytes_non_atomic(urlutils.escape(name), content)
1922
2920
 
1923
 
    def build_tree_contents(self, shape):
1924
 
        build_tree_contents(shape)
1925
 
 
1926
 
    def assertFileEqual(self, content, path):
1927
 
        """Fail if path does not contain 'content'."""
1928
 
        self.failUnlessExists(path)
1929
 
        # TODO: jam 20060427 Shouldn't this be 'rb'?
1930
 
        f = file(path, 'r')
1931
 
        try:
1932
 
            s = f.read()
1933
 
        finally:
1934
 
            f.close()
1935
 
        self.assertEqualDiff(content, s)
1936
 
 
1937
 
    def failUnlessExists(self, path):
1938
 
        """Fail unless path, which may be abs or relative, exists."""
1939
 
        self.failUnless(osutils.lexists(path),path+" does not exist")
1940
 
 
1941
 
    def failIfExists(self, path):
1942
 
        """Fail if path, which may be abs or relative, exists."""
1943
 
        self.failIf(osutils.lexists(path),path+" exists")
 
2921
    build_tree_contents = staticmethod(treeshape.build_tree_contents)
 
2922
 
 
2923
    def assertInWorkingTree(self, path, root_path='.', tree=None):
 
2924
        """Assert whether path or paths are in the WorkingTree"""
 
2925
        if tree is None:
 
2926
            tree = workingtree.WorkingTree.open(root_path)
 
2927
        if not isinstance(path, basestring):
 
2928
            for p in path:
 
2929
                self.assertInWorkingTree(p, tree=tree)
 
2930
        else:
 
2931
            self.assertIsNot(tree.path2id(path), None,
 
2932
                path+' not in working tree.')
 
2933
 
 
2934
    def assertNotInWorkingTree(self, path, root_path='.', tree=None):
 
2935
        """Assert whether path or paths are not in the WorkingTree"""
 
2936
        if tree is None:
 
2937
            tree = workingtree.WorkingTree.open(root_path)
 
2938
        if not isinstance(path, basestring):
 
2939
            for p in path:
 
2940
                self.assertNotInWorkingTree(p,tree=tree)
 
2941
        else:
 
2942
            self.assertIs(tree.path2id(path), None, path+' in working tree.')
1944
2943
 
1945
2944
 
1946
2945
class TestCaseWithTransport(TestCaseInTempDir):
1953
2952
    ReadonlyTransportDecorator is used instead which allows the use of non disk
1954
2953
    based read write transports.
1955
2954
 
1956
 
    If an explicit class is provided for readonly access, that server and the 
 
2955
    If an explicit class is provided for readonly access, that server and the
1957
2956
    readwrite one must both define get_url() as resolving to os.getcwd().
1958
2957
    """
1959
2958
 
1965
2964
        """
1966
2965
        if self.__vfs_server is None:
1967
2966
            self.__vfs_server = self.vfs_transport_factory()
1968
 
            self.__vfs_server.setUp()
1969
 
            self.addCleanup(self.__vfs_server.tearDown)
 
2967
            self.start_server(self.__vfs_server)
1970
2968
        return self.__vfs_server
1971
2969
 
1972
2970
    def make_branch_and_tree(self, relpath, format=None):
1979
2977
        repository will also be accessed locally. Otherwise a lightweight
1980
2978
        checkout is created and returned.
1981
2979
 
 
2980
        We do this because we can't physically create a tree in the local
 
2981
        path, with a branch reference to the transport_factory url, and
 
2982
        a branch + repository in the vfs_transport, unless the vfs_transport
 
2983
        namespace is distinct from the local disk - the two branch objects
 
2984
        would collide. While we could construct a tree with its branch object
 
2985
        pointing at the transport_factory transport in memory, reopening it
 
2986
        would behaving unexpectedly, and has in the past caused testing bugs
 
2987
        when we tried to do it that way.
 
2988
 
1982
2989
        :param format: The BzrDirFormat.
1983
2990
        :returns: the WorkingTree.
1984
2991
        """
1986
2993
        # this obviously requires a format that supports branch references
1987
2994
        # so check for that by checking bzrdir.BzrDirFormat.get_default_format()
1988
2995
        # RBC 20060208
 
2996
        format = self.resolve_format(format=format)
 
2997
        if not format.supports_workingtrees:
 
2998
            b = self.make_branch(relpath+'.branch', format=format)
 
2999
            return b.create_checkout(relpath, lightweight=True)
1989
3000
        b = self.make_branch(relpath, format=format)
1990
3001
        try:
1991
3002
            return b.bzrdir.create_workingtree()
1993
3004
            # We can only make working trees locally at the moment.  If the
1994
3005
            # transport can't support them, then we keep the non-disk-backed
1995
3006
            # branch and create a local checkout.
1996
 
            if self.vfs_transport_factory is LocalURLServer:
 
3007
            if self.vfs_transport_factory is test_server.LocalURLServer:
1997
3008
                # the branch is colocated on disk, we cannot create a checkout.
1998
3009
                # hopefully callers will expect this.
1999
3010
                local_controldir= bzrdir.BzrDir.open(self.get_vfs_only_url(relpath))
2000
 
                return local_controldir.create_workingtree()
 
3011
                wt = local_controldir.create_workingtree()
 
3012
                if wt.branch._format != b._format:
 
3013
                    wt._branch = b
 
3014
                    # Make sure that assigning to wt._branch fixes wt.branch,
 
3015
                    # in case the implementation details of workingtree objects
 
3016
                    # change.
 
3017
                    self.assertIs(b, wt.branch)
 
3018
                return wt
2001
3019
            else:
2002
3020
                return b.create_checkout(relpath, lightweight=True)
2003
3021
 
2029
3047
        super(TestCaseWithTransport, self).setUp()
2030
3048
        self.__vfs_server = None
2031
3049
 
 
3050
    def disable_missing_extensions_warning(self):
 
3051
        """Some tests expect a precise stderr content.
 
3052
 
 
3053
        There is no point in forcing them to duplicate the extension related
 
3054
        warning.
 
3055
        """
 
3056
        config.GlobalConfig().set_user_option('ignore_missing_extensions', True)
 
3057
 
2032
3058
 
2033
3059
class ChrootedTestCase(TestCaseWithTransport):
2034
3060
    """A support class that provides readonly urls outside the local namespace.
2038
3064
    for readonly urls.
2039
3065
 
2040
3066
    TODO RBC 20060127: make this an option to TestCaseWithTransport so it can
2041
 
                       be used without needed to redo it when a different 
 
3067
                       be used without needed to redo it when a different
2042
3068
                       subclass is in use ?
2043
3069
    """
2044
3070
 
2045
3071
    def setUp(self):
 
3072
        from bzrlib.tests import http_server
2046
3073
        super(ChrootedTestCase, self).setUp()
2047
 
        if not self.vfs_transport_factory == MemoryServer:
2048
 
            self.transport_readonly_server = HttpServer
 
3074
        if not self.vfs_transport_factory == memory.MemoryServer:
 
3075
            self.transport_readonly_server = http_server.HttpServer
 
3076
 
 
3077
 
 
3078
def condition_id_re(pattern):
 
3079
    """Create a condition filter which performs a re check on a test's id.
 
3080
 
 
3081
    :param pattern: A regular expression string.
 
3082
    :return: A callable that returns True if the re matches.
 
3083
    """
 
3084
    filter_re = re.compile(pattern, 0)
 
3085
    def condition(test):
 
3086
        test_id = test.id()
 
3087
        return filter_re.search(test_id)
 
3088
    return condition
 
3089
 
 
3090
 
 
3091
def condition_isinstance(klass_or_klass_list):
 
3092
    """Create a condition filter which returns isinstance(param, klass).
 
3093
 
 
3094
    :return: A callable which when called with one parameter obj return the
 
3095
        result of isinstance(obj, klass_or_klass_list).
 
3096
    """
 
3097
    def condition(obj):
 
3098
        return isinstance(obj, klass_or_klass_list)
 
3099
    return condition
 
3100
 
 
3101
 
 
3102
def condition_id_in_list(id_list):
 
3103
    """Create a condition filter which verify that test's id in a list.
 
3104
 
 
3105
    :param id_list: A TestIdList object.
 
3106
    :return: A callable that returns True if the test's id appears in the list.
 
3107
    """
 
3108
    def condition(test):
 
3109
        return id_list.includes(test.id())
 
3110
    return condition
 
3111
 
 
3112
 
 
3113
def condition_id_startswith(starts):
 
3114
    """Create a condition filter verifying that test's id starts with a string.
 
3115
 
 
3116
    :param starts: A list of string.
 
3117
    :return: A callable that returns True if the test's id starts with one of
 
3118
        the given strings.
 
3119
    """
 
3120
    def condition(test):
 
3121
        for start in starts:
 
3122
            if test.id().startswith(start):
 
3123
                return True
 
3124
        return False
 
3125
    return condition
 
3126
 
 
3127
 
 
3128
def exclude_tests_by_condition(suite, condition):
 
3129
    """Create a test suite which excludes some tests from suite.
 
3130
 
 
3131
    :param suite: The suite to get tests from.
 
3132
    :param condition: A callable whose result evaluates True when called with a
 
3133
        test case which should be excluded from the result.
 
3134
    :return: A suite which contains the tests found in suite that fail
 
3135
        condition.
 
3136
    """
 
3137
    result = []
 
3138
    for test in iter_suite_tests(suite):
 
3139
        if not condition(test):
 
3140
            result.append(test)
 
3141
    return TestUtil.TestSuite(result)
 
3142
 
 
3143
 
 
3144
def filter_suite_by_condition(suite, condition):
 
3145
    """Create a test suite by filtering another one.
 
3146
 
 
3147
    :param suite: The source suite.
 
3148
    :param condition: A callable whose result evaluates True when called with a
 
3149
        test case which should be included in the result.
 
3150
    :return: A suite which contains the tests found in suite that pass
 
3151
        condition.
 
3152
    """
 
3153
    result = []
 
3154
    for test in iter_suite_tests(suite):
 
3155
        if condition(test):
 
3156
            result.append(test)
 
3157
    return TestUtil.TestSuite(result)
2049
3158
 
2050
3159
 
2051
3160
def filter_suite_by_re(suite, pattern):
2052
 
    result = TestUtil.TestSuite()
2053
 
    filter_re = re.compile(pattern)
2054
 
    for test in iter_suite_tests(suite):
2055
 
        if filter_re.search(test.id()):
2056
 
            result.addTest(test)
2057
 
    return result
2058
 
 
2059
 
 
2060
 
def sort_suite_by_re(suite, pattern):
2061
 
    first = []
2062
 
    second = []
2063
 
    filter_re = re.compile(pattern)
2064
 
    for test in iter_suite_tests(suite):
2065
 
        if filter_re.search(test.id()):
2066
 
            first.append(test)
 
3161
    """Create a test suite by filtering another one.
 
3162
 
 
3163
    :param suite:           the source suite
 
3164
    :param pattern:         pattern that names must match
 
3165
    :returns: the newly created suite
 
3166
    """
 
3167
    condition = condition_id_re(pattern)
 
3168
    result_suite = filter_suite_by_condition(suite, condition)
 
3169
    return result_suite
 
3170
 
 
3171
 
 
3172
def filter_suite_by_id_list(suite, test_id_list):
 
3173
    """Create a test suite by filtering another one.
 
3174
 
 
3175
    :param suite: The source suite.
 
3176
    :param test_id_list: A list of the test ids to keep as strings.
 
3177
    :returns: the newly created suite
 
3178
    """
 
3179
    condition = condition_id_in_list(test_id_list)
 
3180
    result_suite = filter_suite_by_condition(suite, condition)
 
3181
    return result_suite
 
3182
 
 
3183
 
 
3184
def filter_suite_by_id_startswith(suite, start):
 
3185
    """Create a test suite by filtering another one.
 
3186
 
 
3187
    :param suite: The source suite.
 
3188
    :param start: A list of string the test id must start with one of.
 
3189
    :returns: the newly created suite
 
3190
    """
 
3191
    condition = condition_id_startswith(start)
 
3192
    result_suite = filter_suite_by_condition(suite, condition)
 
3193
    return result_suite
 
3194
 
 
3195
 
 
3196
def exclude_tests_by_re(suite, pattern):
 
3197
    """Create a test suite which excludes some tests from suite.
 
3198
 
 
3199
    :param suite: The suite to get tests from.
 
3200
    :param pattern: A regular expression string. Test ids that match this
 
3201
        pattern will be excluded from the result.
 
3202
    :return: A TestSuite that contains all the tests from suite without the
 
3203
        tests that matched pattern. The order of tests is the same as it was in
 
3204
        suite.
 
3205
    """
 
3206
    return exclude_tests_by_condition(suite, condition_id_re(pattern))
 
3207
 
 
3208
 
 
3209
def preserve_input(something):
 
3210
    """A helper for performing test suite transformation chains.
 
3211
 
 
3212
    :param something: Anything you want to preserve.
 
3213
    :return: Something.
 
3214
    """
 
3215
    return something
 
3216
 
 
3217
 
 
3218
def randomize_suite(suite):
 
3219
    """Return a new TestSuite with suite's tests in random order.
 
3220
 
 
3221
    The tests in the input suite are flattened into a single suite in order to
 
3222
    accomplish this. Any nested TestSuites are removed to provide global
 
3223
    randomness.
 
3224
    """
 
3225
    tests = list(iter_suite_tests(suite))
 
3226
    random.shuffle(tests)
 
3227
    return TestUtil.TestSuite(tests)
 
3228
 
 
3229
 
 
3230
def split_suite_by_condition(suite, condition):
 
3231
    """Split a test suite into two by a condition.
 
3232
 
 
3233
    :param suite: The suite to split.
 
3234
    :param condition: The condition to match on. Tests that match this
 
3235
        condition are returned in the first test suite, ones that do not match
 
3236
        are in the second suite.
 
3237
    :return: A tuple of two test suites, where the first contains tests from
 
3238
        suite matching the condition, and the second contains the remainder
 
3239
        from suite. The order within each output suite is the same as it was in
 
3240
        suite.
 
3241
    """
 
3242
    matched = []
 
3243
    did_not_match = []
 
3244
    for test in iter_suite_tests(suite):
 
3245
        if condition(test):
 
3246
            matched.append(test)
2067
3247
        else:
2068
 
            second.append(test)
2069
 
    return TestUtil.TestSuite(first + second)
 
3248
            did_not_match.append(test)
 
3249
    return TestUtil.TestSuite(matched), TestUtil.TestSuite(did_not_match)
 
3250
 
 
3251
 
 
3252
def split_suite_by_re(suite, pattern):
 
3253
    """Split a test suite into two by a regular expression.
 
3254
 
 
3255
    :param suite: The suite to split.
 
3256
    :param pattern: A regular expression string. Test ids that match this
 
3257
        pattern will be in the first test suite returned, and the others in the
 
3258
        second test suite returned.
 
3259
    :return: A tuple of two test suites, where the first contains tests from
 
3260
        suite matching pattern, and the second contains the remainder from
 
3261
        suite. The order within each output suite is the same as it was in
 
3262
        suite.
 
3263
    """
 
3264
    return split_suite_by_condition(suite, condition_id_re(pattern))
2070
3265
 
2071
3266
 
2072
3267
def run_suite(suite, name='test', verbose=False, pattern=".*",
2073
 
              stop_on_failure=False, keep_output=False,
 
3268
              stop_on_failure=False,
2074
3269
              transport=None, lsprof_timed=None, bench_history=None,
2075
3270
              matching_tests_first=None,
2076
 
              numbered_dirs=None):
2077
 
    use_numbered_dirs = bool(numbered_dirs)
 
3271
              list_only=False,
 
3272
              random_seed=None,
 
3273
              exclude_pattern=None,
 
3274
              strict=False,
 
3275
              runner_class=None,
 
3276
              suite_decorators=None,
 
3277
              stream=None,
 
3278
              result_decorators=None,
 
3279
              ):
 
3280
    """Run a test suite for bzr selftest.
2078
3281
 
 
3282
    :param runner_class: The class of runner to use. Must support the
 
3283
        constructor arguments passed by run_suite which are more than standard
 
3284
        python uses.
 
3285
    :return: A boolean indicating success.
 
3286
    """
2079
3287
    TestCase._gather_lsprof_in_benchmarks = lsprof_timed
2080
 
    if numbered_dirs is not None:
2081
 
        TestCaseInTempDir.use_numbered_dirs = use_numbered_dirs
2082
3288
    if verbose:
2083
3289
        verbosity = 2
2084
3290
    else:
2085
3291
        verbosity = 1
2086
 
    runner = TextTestRunner(stream=sys.stdout,
 
3292
    if runner_class is None:
 
3293
        runner_class = TextTestRunner
 
3294
    if stream is None:
 
3295
        stream = sys.stdout
 
3296
    runner = runner_class(stream=stream,
2087
3297
                            descriptions=0,
2088
3298
                            verbosity=verbosity,
2089
 
                            keep_output=keep_output,
2090
3299
                            bench_history=bench_history,
2091
 
                            use_numbered_dirs=use_numbered_dirs,
 
3300
                            strict=strict,
 
3301
                            result_decorators=result_decorators,
2092
3302
                            )
2093
3303
    runner.stop_on_failure=stop_on_failure
2094
 
    if pattern != '.*':
2095
 
        if matching_tests_first:
2096
 
            suite = sort_suite_by_re(suite, pattern)
2097
 
        else:
2098
 
            suite = filter_suite_by_re(suite, pattern)
 
3304
    if isinstance(suite, unittest.TestSuite):
 
3305
        # Empty out _tests list of passed suite and populate new TestSuite
 
3306
        suite._tests[:], suite = [], TestSuite(suite)
 
3307
    # built in decorator factories:
 
3308
    decorators = [
 
3309
        random_order(random_seed, runner),
 
3310
        exclude_tests(exclude_pattern),
 
3311
        ]
 
3312
    if matching_tests_first:
 
3313
        decorators.append(tests_first(pattern))
 
3314
    else:
 
3315
        decorators.append(filter_tests(pattern))
 
3316
    if suite_decorators:
 
3317
        decorators.extend(suite_decorators)
 
3318
    # tell the result object how many tests will be running: (except if
 
3319
    # --parallel=fork is being used. Robert said he will provide a better
 
3320
    # progress design later -- vila 20090817)
 
3321
    if fork_decorator not in decorators:
 
3322
        decorators.append(CountingDecorator)
 
3323
    for decorator in decorators:
 
3324
        suite = decorator(suite)
 
3325
    if list_only:
 
3326
        # Done after test suite decoration to allow randomisation etc
 
3327
        # to take effect, though that is of marginal benefit.
 
3328
        if verbosity >= 2:
 
3329
            stream.write("Listing tests only ...\n")
 
3330
        for t in iter_suite_tests(suite):
 
3331
            stream.write("%s\n" % (t.id()))
 
3332
        return True
2099
3333
    result = runner.run(suite)
2100
 
    return result.wasSuccessful()
 
3334
    if strict:
 
3335
        return result.wasStrictlySuccessful()
 
3336
    else:
 
3337
        return result.wasSuccessful()
 
3338
 
 
3339
 
 
3340
# A registry where get() returns a suite decorator.
 
3341
parallel_registry = registry.Registry()
 
3342
 
 
3343
 
 
3344
def fork_decorator(suite):
 
3345
    if getattr(os, "fork", None) is None:
 
3346
        raise errors.BzrCommandError("platform does not support fork,"
 
3347
            " try --parallel=subprocess instead.")
 
3348
    concurrency = osutils.local_concurrency()
 
3349
    if concurrency == 1:
 
3350
        return suite
 
3351
    from testtools import ConcurrentTestSuite
 
3352
    return ConcurrentTestSuite(suite, fork_for_tests)
 
3353
parallel_registry.register('fork', fork_decorator)
 
3354
 
 
3355
 
 
3356
def subprocess_decorator(suite):
 
3357
    concurrency = osutils.local_concurrency()
 
3358
    if concurrency == 1:
 
3359
        return suite
 
3360
    from testtools import ConcurrentTestSuite
 
3361
    return ConcurrentTestSuite(suite, reinvoke_for_tests)
 
3362
parallel_registry.register('subprocess', subprocess_decorator)
 
3363
 
 
3364
 
 
3365
def exclude_tests(exclude_pattern):
 
3366
    """Return a test suite decorator that excludes tests."""
 
3367
    if exclude_pattern is None:
 
3368
        return identity_decorator
 
3369
    def decorator(suite):
 
3370
        return ExcludeDecorator(suite, exclude_pattern)
 
3371
    return decorator
 
3372
 
 
3373
 
 
3374
def filter_tests(pattern):
 
3375
    if pattern == '.*':
 
3376
        return identity_decorator
 
3377
    def decorator(suite):
 
3378
        return FilterTestsDecorator(suite, pattern)
 
3379
    return decorator
 
3380
 
 
3381
 
 
3382
def random_order(random_seed, runner):
 
3383
    """Return a test suite decorator factory for randomising tests order.
 
3384
    
 
3385
    :param random_seed: now, a string which casts to a long, or a long.
 
3386
    :param runner: A test runner with a stream attribute to report on.
 
3387
    """
 
3388
    if random_seed is None:
 
3389
        return identity_decorator
 
3390
    def decorator(suite):
 
3391
        return RandomDecorator(suite, random_seed, runner.stream)
 
3392
    return decorator
 
3393
 
 
3394
 
 
3395
def tests_first(pattern):
 
3396
    if pattern == '.*':
 
3397
        return identity_decorator
 
3398
    def decorator(suite):
 
3399
        return TestFirstDecorator(suite, pattern)
 
3400
    return decorator
 
3401
 
 
3402
 
 
3403
def identity_decorator(suite):
 
3404
    """Return suite."""
 
3405
    return suite
 
3406
 
 
3407
 
 
3408
class TestDecorator(TestUtil.TestSuite):
 
3409
    """A decorator for TestCase/TestSuite objects.
 
3410
 
 
3411
    Contains rather than flattening suite passed on construction
 
3412
    """
 
3413
 
 
3414
    def __init__(self, suite=None):
 
3415
        super(TestDecorator, self).__init__()
 
3416
        if suite is not None:
 
3417
            self.addTest(suite)
 
3418
 
 
3419
    # Don't need subclass run method with suite emptying
 
3420
    run = unittest.TestSuite.run
 
3421
 
 
3422
 
 
3423
class CountingDecorator(TestDecorator):
 
3424
    """A decorator which calls result.progress(self.countTestCases)."""
 
3425
 
 
3426
    def run(self, result):
 
3427
        progress_method = getattr(result, 'progress', None)
 
3428
        if callable(progress_method):
 
3429
            progress_method(self.countTestCases(), SUBUNIT_SEEK_SET)
 
3430
        return super(CountingDecorator, self).run(result)
 
3431
 
 
3432
 
 
3433
class ExcludeDecorator(TestDecorator):
 
3434
    """A decorator which excludes test matching an exclude pattern."""
 
3435
 
 
3436
    def __init__(self, suite, exclude_pattern):
 
3437
        super(ExcludeDecorator, self).__init__(
 
3438
            exclude_tests_by_re(suite, exclude_pattern))
 
3439
 
 
3440
 
 
3441
class FilterTestsDecorator(TestDecorator):
 
3442
    """A decorator which filters tests to those matching a pattern."""
 
3443
 
 
3444
    def __init__(self, suite, pattern):
 
3445
        super(FilterTestsDecorator, self).__init__(
 
3446
            filter_suite_by_re(suite, pattern))
 
3447
 
 
3448
 
 
3449
class RandomDecorator(TestDecorator):
 
3450
    """A decorator which randomises the order of its tests."""
 
3451
 
 
3452
    def __init__(self, suite, random_seed, stream):
 
3453
        random_seed = self.actual_seed(random_seed)
 
3454
        stream.write("Randomizing test order using seed %s\n\n" %
 
3455
            (random_seed,))
 
3456
        # Initialise the random number generator.
 
3457
        random.seed(random_seed)
 
3458
        super(RandomDecorator, self).__init__(randomize_suite(suite))
 
3459
 
 
3460
    @staticmethod
 
3461
    def actual_seed(seed):
 
3462
        if seed == "now":
 
3463
            # We convert the seed to a long to make it reuseable across
 
3464
            # invocations (because the user can reenter it).
 
3465
            return long(time.time())
 
3466
        else:
 
3467
            # Convert the seed to a long if we can
 
3468
            try:
 
3469
                return long(seed)
 
3470
            except (TypeError, ValueError):
 
3471
                pass
 
3472
        return seed
 
3473
 
 
3474
 
 
3475
class TestFirstDecorator(TestDecorator):
 
3476
    """A decorator which moves named tests to the front."""
 
3477
 
 
3478
    def __init__(self, suite, pattern):
 
3479
        super(TestFirstDecorator, self).__init__()
 
3480
        self.addTests(split_suite_by_re(suite, pattern))
 
3481
 
 
3482
 
 
3483
def partition_tests(suite, count):
 
3484
    """Partition suite into count lists of tests."""
 
3485
    # This just assigns tests in a round-robin fashion.  On one hand this
 
3486
    # splits up blocks of related tests that might run faster if they shared
 
3487
    # resources, but on the other it avoids assigning blocks of slow tests to
 
3488
    # just one partition.  So the slowest partition shouldn't be much slower
 
3489
    # than the fastest.
 
3490
    partitions = [list() for i in range(count)]
 
3491
    tests = iter_suite_tests(suite)
 
3492
    for partition, test in itertools.izip(itertools.cycle(partitions), tests):
 
3493
        partition.append(test)
 
3494
    return partitions
 
3495
 
 
3496
 
 
3497
def workaround_zealous_crypto_random():
 
3498
    """Crypto.Random want to help us being secure, but we don't care here.
 
3499
 
 
3500
    This workaround some test failure related to the sftp server. Once paramiko
 
3501
    stop using the controversial API in Crypto.Random, we may get rid of it.
 
3502
    """
 
3503
    try:
 
3504
        from Crypto.Random import atfork
 
3505
        atfork()
 
3506
    except ImportError:
 
3507
        pass
 
3508
 
 
3509
 
 
3510
def fork_for_tests(suite):
 
3511
    """Take suite and start up one runner per CPU by forking()
 
3512
 
 
3513
    :return: An iterable of TestCase-like objects which can each have
 
3514
        run(result) called on them to feed tests to result.
 
3515
    """
 
3516
    concurrency = osutils.local_concurrency()
 
3517
    result = []
 
3518
    from subunit import ProtocolTestCase
 
3519
    from subunit.test_results import AutoTimingTestResultDecorator
 
3520
    class TestInOtherProcess(ProtocolTestCase):
 
3521
        # Should be in subunit, I think. RBC.
 
3522
        def __init__(self, stream, pid):
 
3523
            ProtocolTestCase.__init__(self, stream)
 
3524
            self.pid = pid
 
3525
 
 
3526
        def run(self, result):
 
3527
            try:
 
3528
                ProtocolTestCase.run(self, result)
 
3529
            finally:
 
3530
                pid, status = os.waitpid(self.pid, 0)
 
3531
            # GZ 2011-10-18: If status is nonzero, should report to the result
 
3532
            #                that something went wrong.
 
3533
 
 
3534
    test_blocks = partition_tests(suite, concurrency)
 
3535
    # Clear the tests from the original suite so it doesn't keep them alive
 
3536
    suite._tests[:] = []
 
3537
    for process_tests in test_blocks:
 
3538
        process_suite = TestUtil.TestSuite(process_tests)
 
3539
        # Also clear each split list so new suite has only reference
 
3540
        process_tests[:] = []
 
3541
        c2pread, c2pwrite = os.pipe()
 
3542
        pid = os.fork()
 
3543
        if pid == 0:
 
3544
            try:
 
3545
                stream = os.fdopen(c2pwrite, 'wb', 1)
 
3546
                workaround_zealous_crypto_random()
 
3547
                os.close(c2pread)
 
3548
                # Leave stderr and stdout open so we can see test noise
 
3549
                # Close stdin so that the child goes away if it decides to
 
3550
                # read from stdin (otherwise its a roulette to see what
 
3551
                # child actually gets keystrokes for pdb etc).
 
3552
                sys.stdin.close()
 
3553
                subunit_result = AutoTimingTestResultDecorator(
 
3554
                    SubUnitBzrProtocolClient(stream))
 
3555
                process_suite.run(subunit_result)
 
3556
            except:
 
3557
                # Try and report traceback on stream, but exit with error even
 
3558
                # if stream couldn't be created or something else goes wrong.
 
3559
                # The traceback is formatted to a string and written in one go
 
3560
                # to avoid interleaving lines from multiple failing children.
 
3561
                try:
 
3562
                    stream.write(traceback.format_exc())
 
3563
                finally:
 
3564
                    os._exit(1)
 
3565
            os._exit(0)
 
3566
        else:
 
3567
            os.close(c2pwrite)
 
3568
            stream = os.fdopen(c2pread, 'rb', 1)
 
3569
            test = TestInOtherProcess(stream, pid)
 
3570
            result.append(test)
 
3571
    return result
 
3572
 
 
3573
 
 
3574
def reinvoke_for_tests(suite):
 
3575
    """Take suite and start up one runner per CPU using subprocess().
 
3576
 
 
3577
    :return: An iterable of TestCase-like objects which can each have
 
3578
        run(result) called on them to feed tests to result.
 
3579
    """
 
3580
    concurrency = osutils.local_concurrency()
 
3581
    result = []
 
3582
    from subunit import ProtocolTestCase
 
3583
    class TestInSubprocess(ProtocolTestCase):
 
3584
        def __init__(self, process, name):
 
3585
            ProtocolTestCase.__init__(self, process.stdout)
 
3586
            self.process = process
 
3587
            self.process.stdin.close()
 
3588
            self.name = name
 
3589
 
 
3590
        def run(self, result):
 
3591
            try:
 
3592
                ProtocolTestCase.run(self, result)
 
3593
            finally:
 
3594
                self.process.wait()
 
3595
                os.unlink(self.name)
 
3596
            # print "pid %d finished" % finished_process
 
3597
    test_blocks = partition_tests(suite, concurrency)
 
3598
    for process_tests in test_blocks:
 
3599
        # ugly; currently reimplement rather than reuses TestCase methods.
 
3600
        bzr_path = os.path.dirname(os.path.dirname(bzrlib.__file__))+'/bzr'
 
3601
        if not os.path.isfile(bzr_path):
 
3602
            # We are probably installed. Assume sys.argv is the right file
 
3603
            bzr_path = sys.argv[0]
 
3604
        bzr_path = [bzr_path]
 
3605
        if sys.platform == "win32":
 
3606
            # if we're on windows, we can't execute the bzr script directly
 
3607
            bzr_path = [sys.executable] + bzr_path
 
3608
        fd, test_list_file_name = tempfile.mkstemp()
 
3609
        test_list_file = os.fdopen(fd, 'wb', 1)
 
3610
        for test in process_tests:
 
3611
            test_list_file.write(test.id() + '\n')
 
3612
        test_list_file.close()
 
3613
        try:
 
3614
            argv = bzr_path + ['selftest', '--load-list', test_list_file_name,
 
3615
                '--subunit']
 
3616
            if '--no-plugins' in sys.argv:
 
3617
                argv.append('--no-plugins')
 
3618
            # stderr=subprocess.STDOUT would be ideal, but until we prevent
 
3619
            # noise on stderr it can interrupt the subunit protocol.
 
3620
            process = subprocess.Popen(argv, stdin=subprocess.PIPE,
 
3621
                                      stdout=subprocess.PIPE,
 
3622
                                      stderr=subprocess.PIPE,
 
3623
                                      bufsize=1)
 
3624
            test = TestInSubprocess(process, test_list_file_name)
 
3625
            result.append(test)
 
3626
        except:
 
3627
            os.unlink(test_list_file_name)
 
3628
            raise
 
3629
    return result
 
3630
 
 
3631
 
 
3632
class ProfileResult(testtools.ExtendedToOriginalDecorator):
 
3633
    """Generate profiling data for all activity between start and success.
 
3634
    
 
3635
    The profile data is appended to the test's _benchcalls attribute and can
 
3636
    be accessed by the forwarded-to TestResult.
 
3637
 
 
3638
    While it might be cleaner do accumulate this in stopTest, addSuccess is
 
3639
    where our existing output support for lsprof is, and this class aims to
 
3640
    fit in with that: while it could be moved it's not necessary to accomplish
 
3641
    test profiling, nor would it be dramatically cleaner.
 
3642
    """
 
3643
 
 
3644
    def startTest(self, test):
 
3645
        self.profiler = bzrlib.lsprof.BzrProfiler()
 
3646
        # Prevent deadlocks in tests that use lsprof: those tests will
 
3647
        # unavoidably fail.
 
3648
        bzrlib.lsprof.BzrProfiler.profiler_block = 0
 
3649
        self.profiler.start()
 
3650
        testtools.ExtendedToOriginalDecorator.startTest(self, test)
 
3651
 
 
3652
    def addSuccess(self, test):
 
3653
        stats = self.profiler.stop()
 
3654
        try:
 
3655
            calls = test._benchcalls
 
3656
        except AttributeError:
 
3657
            test._benchcalls = []
 
3658
            calls = test._benchcalls
 
3659
        calls.append(((test.id(), "", ""), stats))
 
3660
        testtools.ExtendedToOriginalDecorator.addSuccess(self, test)
 
3661
 
 
3662
    def stopTest(self, test):
 
3663
        testtools.ExtendedToOriginalDecorator.stopTest(self, test)
 
3664
        self.profiler = None
 
3665
 
 
3666
 
 
3667
# Controlled by "bzr selftest -E=..." option
 
3668
# Currently supported:
 
3669
#   -Eallow_debug           Will no longer clear debug.debug_flags() so it
 
3670
#                           preserves any flags supplied at the command line.
 
3671
#   -Edisable_lock_checks   Turns errors in mismatched locks into simple prints
 
3672
#                           rather than failing tests. And no longer raise
 
3673
#                           LockContention when fctnl locks are not being used
 
3674
#                           with proper exclusion rules.
 
3675
#   -Ethreads               Will display thread ident at creation/join time to
 
3676
#                           help track thread leaks
 
3677
#   -Euncollected_cases     Display the identity of any test cases that weren't
 
3678
#                           deallocated after being completed.
 
3679
#   -Econfig_stats          Will collect statistics using addDetail
 
3680
selftest_debug_flags = set()
2101
3681
 
2102
3682
 
2103
3683
def selftest(verbose=False, pattern=".*", stop_on_failure=True,
2104
 
             keep_output=False,
2105
3684
             transport=None,
2106
3685
             test_suite_factory=None,
2107
3686
             lsprof_timed=None,
2108
3687
             bench_history=None,
2109
3688
             matching_tests_first=None,
2110
 
             numbered_dirs=None):
 
3689
             list_only=False,
 
3690
             random_seed=None,
 
3691
             exclude_pattern=None,
 
3692
             strict=False,
 
3693
             load_list=None,
 
3694
             debug_flags=None,
 
3695
             starting_with=None,
 
3696
             runner_class=None,
 
3697
             suite_decorators=None,
 
3698
             stream=None,
 
3699
             lsprof_tests=False,
 
3700
             ):
2111
3701
    """Run the whole test suite under the enhanced runner"""
2112
3702
    # XXX: Very ugly way to do this...
2113
3703
    # Disable warning about old formats because we don't want it to disturb
2120
3710
        transport = default_transport
2121
3711
    old_transport = default_transport
2122
3712
    default_transport = transport
 
3713
    global selftest_debug_flags
 
3714
    old_debug_flags = selftest_debug_flags
 
3715
    if debug_flags is not None:
 
3716
        selftest_debug_flags = set(debug_flags)
2123
3717
    try:
 
3718
        if load_list is None:
 
3719
            keep_only = None
 
3720
        else:
 
3721
            keep_only = load_test_id_list(load_list)
 
3722
        if starting_with:
 
3723
            starting_with = [test_prefix_alias_registry.resolve_alias(start)
 
3724
                             for start in starting_with]
2124
3725
        if test_suite_factory is None:
2125
 
            suite = test_suite()
 
3726
            # Reduce loading time by loading modules based on the starting_with
 
3727
            # patterns.
 
3728
            suite = test_suite(keep_only, starting_with)
2126
3729
        else:
2127
3730
            suite = test_suite_factory()
 
3731
        if starting_with:
 
3732
            # But always filter as requested.
 
3733
            suite = filter_suite_by_id_startswith(suite, starting_with)
 
3734
        result_decorators = []
 
3735
        if lsprof_tests:
 
3736
            result_decorators.append(ProfileResult)
2128
3737
        return run_suite(suite, 'testbzr', verbose=verbose, pattern=pattern,
2129
 
                     stop_on_failure=stop_on_failure, keep_output=keep_output,
 
3738
                     stop_on_failure=stop_on_failure,
2130
3739
                     transport=transport,
2131
3740
                     lsprof_timed=lsprof_timed,
2132
3741
                     bench_history=bench_history,
2133
3742
                     matching_tests_first=matching_tests_first,
2134
 
                     numbered_dirs=numbered_dirs)
 
3743
                     list_only=list_only,
 
3744
                     random_seed=random_seed,
 
3745
                     exclude_pattern=exclude_pattern,
 
3746
                     strict=strict,
 
3747
                     runner_class=runner_class,
 
3748
                     suite_decorators=suite_decorators,
 
3749
                     stream=stream,
 
3750
                     result_decorators=result_decorators,
 
3751
                     )
2135
3752
    finally:
2136
3753
        default_transport = old_transport
2137
 
 
2138
 
 
2139
 
def test_suite():
 
3754
        selftest_debug_flags = old_debug_flags
 
3755
 
 
3756
 
 
3757
def load_test_id_list(file_name):
 
3758
    """Load a test id list from a text file.
 
3759
 
 
3760
    The format is one test id by line.  No special care is taken to impose
 
3761
    strict rules, these test ids are used to filter the test suite so a test id
 
3762
    that do not match an existing test will do no harm. This allows user to add
 
3763
    comments, leave blank lines, etc.
 
3764
    """
 
3765
    test_list = []
 
3766
    try:
 
3767
        ftest = open(file_name, 'rt')
 
3768
    except IOError, e:
 
3769
        if e.errno != errno.ENOENT:
 
3770
            raise
 
3771
        else:
 
3772
            raise errors.NoSuchFile(file_name)
 
3773
 
 
3774
    for test_name in ftest.readlines():
 
3775
        test_list.append(test_name.strip())
 
3776
    ftest.close()
 
3777
    return test_list
 
3778
 
 
3779
 
 
3780
def suite_matches_id_list(test_suite, id_list):
 
3781
    """Warns about tests not appearing or appearing more than once.
 
3782
 
 
3783
    :param test_suite: A TestSuite object.
 
3784
    :param test_id_list: The list of test ids that should be found in
 
3785
         test_suite.
 
3786
 
 
3787
    :return: (absents, duplicates) absents is a list containing the test found
 
3788
        in id_list but not in test_suite, duplicates is a list containing the
 
3789
        test found multiple times in test_suite.
 
3790
 
 
3791
    When using a prefined test id list, it may occurs that some tests do not
 
3792
    exist anymore or that some tests use the same id. This function warns the
 
3793
    tester about potential problems in his workflow (test lists are volatile)
 
3794
    or in the test suite itself (using the same id for several tests does not
 
3795
    help to localize defects).
 
3796
    """
 
3797
    # Build a dict counting id occurrences
 
3798
    tests = dict()
 
3799
    for test in iter_suite_tests(test_suite):
 
3800
        id = test.id()
 
3801
        tests[id] = tests.get(id, 0) + 1
 
3802
 
 
3803
    not_found = []
 
3804
    duplicates = []
 
3805
    for id in id_list:
 
3806
        occurs = tests.get(id, 0)
 
3807
        if not occurs:
 
3808
            not_found.append(id)
 
3809
        elif occurs > 1:
 
3810
            duplicates.append(id)
 
3811
 
 
3812
    return not_found, duplicates
 
3813
 
 
3814
 
 
3815
class TestIdList(object):
 
3816
    """Test id list to filter a test suite.
 
3817
 
 
3818
    Relying on the assumption that test ids are built as:
 
3819
    <module>[.<class>.<method>][(<param>+)], <module> being in python dotted
 
3820
    notation, this class offers methods to :
 
3821
    - avoid building a test suite for modules not refered to in the test list,
 
3822
    - keep only the tests listed from the module test suite.
 
3823
    """
 
3824
 
 
3825
    def __init__(self, test_id_list):
 
3826
        # When a test suite needs to be filtered against us we compare test ids
 
3827
        # for equality, so a simple dict offers a quick and simple solution.
 
3828
        self.tests = dict().fromkeys(test_id_list, True)
 
3829
 
 
3830
        # While unittest.TestCase have ids like:
 
3831
        # <module>.<class>.<method>[(<param+)],
 
3832
        # doctest.DocTestCase can have ids like:
 
3833
        # <module>
 
3834
        # <module>.<class>
 
3835
        # <module>.<function>
 
3836
        # <module>.<class>.<method>
 
3837
 
 
3838
        # Since we can't predict a test class from its name only, we settle on
 
3839
        # a simple constraint: a test id always begins with its module name.
 
3840
 
 
3841
        modules = {}
 
3842
        for test_id in test_id_list:
 
3843
            parts = test_id.split('.')
 
3844
            mod_name = parts.pop(0)
 
3845
            modules[mod_name] = True
 
3846
            for part in parts:
 
3847
                mod_name += '.' + part
 
3848
                modules[mod_name] = True
 
3849
        self.modules = modules
 
3850
 
 
3851
    def refers_to(self, module_name):
 
3852
        """Is there tests for the module or one of its sub modules."""
 
3853
        return self.modules.has_key(module_name)
 
3854
 
 
3855
    def includes(self, test_id):
 
3856
        return self.tests.has_key(test_id)
 
3857
 
 
3858
 
 
3859
class TestPrefixAliasRegistry(registry.Registry):
 
3860
    """A registry for test prefix aliases.
 
3861
 
 
3862
    This helps implement shorcuts for the --starting-with selftest
 
3863
    option. Overriding existing prefixes is not allowed but not fatal (a
 
3864
    warning will be emitted).
 
3865
    """
 
3866
 
 
3867
    def register(self, key, obj, help=None, info=None,
 
3868
                 override_existing=False):
 
3869
        """See Registry.register.
 
3870
 
 
3871
        Trying to override an existing alias causes a warning to be emitted,
 
3872
        not a fatal execption.
 
3873
        """
 
3874
        try:
 
3875
            super(TestPrefixAliasRegistry, self).register(
 
3876
                key, obj, help=help, info=info, override_existing=False)
 
3877
        except KeyError:
 
3878
            actual = self.get(key)
 
3879
            trace.note(
 
3880
                'Test prefix alias %s is already used for %s, ignoring %s'
 
3881
                % (key, actual, obj))
 
3882
 
 
3883
    def resolve_alias(self, id_start):
 
3884
        """Replace the alias by the prefix in the given string.
 
3885
 
 
3886
        Using an unknown prefix is an error to help catching typos.
 
3887
        """
 
3888
        parts = id_start.split('.')
 
3889
        try:
 
3890
            parts[0] = self.get(parts[0])
 
3891
        except KeyError:
 
3892
            raise errors.BzrCommandError(
 
3893
                '%s is not a known test prefix alias' % parts[0])
 
3894
        return '.'.join(parts)
 
3895
 
 
3896
 
 
3897
test_prefix_alias_registry = TestPrefixAliasRegistry()
 
3898
"""Registry of test prefix aliases."""
 
3899
 
 
3900
 
 
3901
# This alias allows to detect typos ('bzrlin.') by making all valid test ids
 
3902
# appear prefixed ('bzrlib.' is "replaced" by 'bzrlib.').
 
3903
test_prefix_alias_registry.register('bzrlib', 'bzrlib')
 
3904
 
 
3905
# Obvious highest levels prefixes, feel free to add your own via a plugin
 
3906
test_prefix_alias_registry.register('bd', 'bzrlib.doc')
 
3907
test_prefix_alias_registry.register('bu', 'bzrlib.utils')
 
3908
test_prefix_alias_registry.register('bt', 'bzrlib.tests')
 
3909
test_prefix_alias_registry.register('bb', 'bzrlib.tests.blackbox')
 
3910
test_prefix_alias_registry.register('bp', 'bzrlib.plugins')
 
3911
 
 
3912
 
 
3913
def _test_suite_testmod_names():
 
3914
    """Return the standard list of test module names to test."""
 
3915
    return [
 
3916
        'bzrlib.doc',
 
3917
        'bzrlib.tests.blackbox',
 
3918
        'bzrlib.tests.commands',
 
3919
        'bzrlib.tests.per_branch',
 
3920
        'bzrlib.tests.per_bzrdir',
 
3921
        'bzrlib.tests.per_controldir',
 
3922
        'bzrlib.tests.per_controldir_colo',
 
3923
        'bzrlib.tests.per_foreign_vcs',
 
3924
        'bzrlib.tests.per_interrepository',
 
3925
        'bzrlib.tests.per_intertree',
 
3926
        'bzrlib.tests.per_inventory',
 
3927
        'bzrlib.tests.per_interbranch',
 
3928
        'bzrlib.tests.per_lock',
 
3929
        'bzrlib.tests.per_merger',
 
3930
        'bzrlib.tests.per_transport',
 
3931
        'bzrlib.tests.per_tree',
 
3932
        'bzrlib.tests.per_pack_repository',
 
3933
        'bzrlib.tests.per_repository',
 
3934
        'bzrlib.tests.per_repository_chk',
 
3935
        'bzrlib.tests.per_repository_reference',
 
3936
        'bzrlib.tests.per_repository_vf',
 
3937
        'bzrlib.tests.per_uifactory',
 
3938
        'bzrlib.tests.per_versionedfile',
 
3939
        'bzrlib.tests.per_workingtree',
 
3940
        'bzrlib.tests.test__annotator',
 
3941
        'bzrlib.tests.test__bencode',
 
3942
        'bzrlib.tests.test__btree_serializer',
 
3943
        'bzrlib.tests.test__chk_map',
 
3944
        'bzrlib.tests.test__dirstate_helpers',
 
3945
        'bzrlib.tests.test__groupcompress',
 
3946
        'bzrlib.tests.test__known_graph',
 
3947
        'bzrlib.tests.test__rio',
 
3948
        'bzrlib.tests.test__simple_set',
 
3949
        'bzrlib.tests.test__static_tuple',
 
3950
        'bzrlib.tests.test__walkdirs_win32',
 
3951
        'bzrlib.tests.test_ancestry',
 
3952
        'bzrlib.tests.test_annotate',
 
3953
        'bzrlib.tests.test_api',
 
3954
        'bzrlib.tests.test_atomicfile',
 
3955
        'bzrlib.tests.test_bad_files',
 
3956
        'bzrlib.tests.test_bisect_multi',
 
3957
        'bzrlib.tests.test_branch',
 
3958
        'bzrlib.tests.test_branchbuilder',
 
3959
        'bzrlib.tests.test_btree_index',
 
3960
        'bzrlib.tests.test_bugtracker',
 
3961
        'bzrlib.tests.test_bundle',
 
3962
        'bzrlib.tests.test_bzrdir',
 
3963
        'bzrlib.tests.test__chunks_to_lines',
 
3964
        'bzrlib.tests.test_cache_utf8',
 
3965
        'bzrlib.tests.test_chk_map',
 
3966
        'bzrlib.tests.test_chk_serializer',
 
3967
        'bzrlib.tests.test_chunk_writer',
 
3968
        'bzrlib.tests.test_clean_tree',
 
3969
        'bzrlib.tests.test_cleanup',
 
3970
        'bzrlib.tests.test_cmdline',
 
3971
        'bzrlib.tests.test_commands',
 
3972
        'bzrlib.tests.test_commit',
 
3973
        'bzrlib.tests.test_commit_merge',
 
3974
        'bzrlib.tests.test_config',
 
3975
        'bzrlib.tests.test_conflicts',
 
3976
        'bzrlib.tests.test_controldir',
 
3977
        'bzrlib.tests.test_counted_lock',
 
3978
        'bzrlib.tests.test_crash',
 
3979
        'bzrlib.tests.test_decorators',
 
3980
        'bzrlib.tests.test_delta',
 
3981
        'bzrlib.tests.test_debug',
 
3982
        'bzrlib.tests.test_diff',
 
3983
        'bzrlib.tests.test_directory_service',
 
3984
        'bzrlib.tests.test_dirstate',
 
3985
        'bzrlib.tests.test_email_message',
 
3986
        'bzrlib.tests.test_eol_filters',
 
3987
        'bzrlib.tests.test_errors',
 
3988
        'bzrlib.tests.test_estimate_compressed_size',
 
3989
        'bzrlib.tests.test_export',
 
3990
        'bzrlib.tests.test_export_pot',
 
3991
        'bzrlib.tests.test_extract',
 
3992
        'bzrlib.tests.test_features',
 
3993
        'bzrlib.tests.test_fetch',
 
3994
        'bzrlib.tests.test_fixtures',
 
3995
        'bzrlib.tests.test_fifo_cache',
 
3996
        'bzrlib.tests.test_filters',
 
3997
        'bzrlib.tests.test_filter_tree',
 
3998
        'bzrlib.tests.test_ftp_transport',
 
3999
        'bzrlib.tests.test_foreign',
 
4000
        'bzrlib.tests.test_generate_docs',
 
4001
        'bzrlib.tests.test_generate_ids',
 
4002
        'bzrlib.tests.test_globbing',
 
4003
        'bzrlib.tests.test_gpg',
 
4004
        'bzrlib.tests.test_graph',
 
4005
        'bzrlib.tests.test_groupcompress',
 
4006
        'bzrlib.tests.test_hashcache',
 
4007
        'bzrlib.tests.test_help',
 
4008
        'bzrlib.tests.test_hooks',
 
4009
        'bzrlib.tests.test_http',
 
4010
        'bzrlib.tests.test_http_response',
 
4011
        'bzrlib.tests.test_https_ca_bundle',
 
4012
        'bzrlib.tests.test_https_urllib',
 
4013
        'bzrlib.tests.test_i18n',
 
4014
        'bzrlib.tests.test_identitymap',
 
4015
        'bzrlib.tests.test_ignores',
 
4016
        'bzrlib.tests.test_index',
 
4017
        'bzrlib.tests.test_import_tariff',
 
4018
        'bzrlib.tests.test_info',
 
4019
        'bzrlib.tests.test_inv',
 
4020
        'bzrlib.tests.test_inventory_delta',
 
4021
        'bzrlib.tests.test_knit',
 
4022
        'bzrlib.tests.test_lazy_import',
 
4023
        'bzrlib.tests.test_lazy_regex',
 
4024
        'bzrlib.tests.test_library_state',
 
4025
        'bzrlib.tests.test_lock',
 
4026
        'bzrlib.tests.test_lockable_files',
 
4027
        'bzrlib.tests.test_lockdir',
 
4028
        'bzrlib.tests.test_log',
 
4029
        'bzrlib.tests.test_lru_cache',
 
4030
        'bzrlib.tests.test_lsprof',
 
4031
        'bzrlib.tests.test_mail_client',
 
4032
        'bzrlib.tests.test_matchers',
 
4033
        'bzrlib.tests.test_memorytree',
 
4034
        'bzrlib.tests.test_merge',
 
4035
        'bzrlib.tests.test_merge3',
 
4036
        'bzrlib.tests.test_merge_core',
 
4037
        'bzrlib.tests.test_merge_directive',
 
4038
        'bzrlib.tests.test_mergetools',
 
4039
        'bzrlib.tests.test_missing',
 
4040
        'bzrlib.tests.test_msgeditor',
 
4041
        'bzrlib.tests.test_multiparent',
 
4042
        'bzrlib.tests.test_mutabletree',
 
4043
        'bzrlib.tests.test_nonascii',
 
4044
        'bzrlib.tests.test_options',
 
4045
        'bzrlib.tests.test_osutils',
 
4046
        'bzrlib.tests.test_osutils_encodings',
 
4047
        'bzrlib.tests.test_pack',
 
4048
        'bzrlib.tests.test_patch',
 
4049
        'bzrlib.tests.test_patches',
 
4050
        'bzrlib.tests.test_permissions',
 
4051
        'bzrlib.tests.test_plugins',
 
4052
        'bzrlib.tests.test_progress',
 
4053
        'bzrlib.tests.test_pyutils',
 
4054
        'bzrlib.tests.test_read_bundle',
 
4055
        'bzrlib.tests.test_reconcile',
 
4056
        'bzrlib.tests.test_reconfigure',
 
4057
        'bzrlib.tests.test_registry',
 
4058
        'bzrlib.tests.test_remote',
 
4059
        'bzrlib.tests.test_rename_map',
 
4060
        'bzrlib.tests.test_repository',
 
4061
        'bzrlib.tests.test_revert',
 
4062
        'bzrlib.tests.test_revision',
 
4063
        'bzrlib.tests.test_revisionspec',
 
4064
        'bzrlib.tests.test_revisiontree',
 
4065
        'bzrlib.tests.test_rio',
 
4066
        'bzrlib.tests.test_rules',
 
4067
        'bzrlib.tests.test_url_policy_open',
 
4068
        'bzrlib.tests.test_sampler',
 
4069
        'bzrlib.tests.test_scenarios',
 
4070
        'bzrlib.tests.test_script',
 
4071
        'bzrlib.tests.test_selftest',
 
4072
        'bzrlib.tests.test_serializer',
 
4073
        'bzrlib.tests.test_setup',
 
4074
        'bzrlib.tests.test_sftp_transport',
 
4075
        'bzrlib.tests.test_shelf',
 
4076
        'bzrlib.tests.test_shelf_ui',
 
4077
        'bzrlib.tests.test_smart',
 
4078
        'bzrlib.tests.test_smart_add',
 
4079
        'bzrlib.tests.test_smart_request',
 
4080
        'bzrlib.tests.test_smart_signals',
 
4081
        'bzrlib.tests.test_smart_transport',
 
4082
        'bzrlib.tests.test_smtp_connection',
 
4083
        'bzrlib.tests.test_source',
 
4084
        'bzrlib.tests.test_ssh_transport',
 
4085
        'bzrlib.tests.test_status',
 
4086
        'bzrlib.tests.test_store',
 
4087
        'bzrlib.tests.test_strace',
 
4088
        'bzrlib.tests.test_subsume',
 
4089
        'bzrlib.tests.test_switch',
 
4090
        'bzrlib.tests.test_symbol_versioning',
 
4091
        'bzrlib.tests.test_tag',
 
4092
        'bzrlib.tests.test_test_server',
 
4093
        'bzrlib.tests.test_testament',
 
4094
        'bzrlib.tests.test_textfile',
 
4095
        'bzrlib.tests.test_textmerge',
 
4096
        'bzrlib.tests.test_cethread',
 
4097
        'bzrlib.tests.test_timestamp',
 
4098
        'bzrlib.tests.test_trace',
 
4099
        'bzrlib.tests.test_transactions',
 
4100
        'bzrlib.tests.test_transform',
 
4101
        'bzrlib.tests.test_transport',
 
4102
        'bzrlib.tests.test_transport_log',
 
4103
        'bzrlib.tests.test_tree',
 
4104
        'bzrlib.tests.test_treebuilder',
 
4105
        'bzrlib.tests.test_treeshape',
 
4106
        'bzrlib.tests.test_tsort',
 
4107
        'bzrlib.tests.test_tuned_gzip',
 
4108
        'bzrlib.tests.test_ui',
 
4109
        'bzrlib.tests.test_uncommit',
 
4110
        'bzrlib.tests.test_upgrade',
 
4111
        'bzrlib.tests.test_upgrade_stacked',
 
4112
        'bzrlib.tests.test_urlutils',
 
4113
        'bzrlib.tests.test_utextwrap',
 
4114
        'bzrlib.tests.test_version',
 
4115
        'bzrlib.tests.test_version_info',
 
4116
        'bzrlib.tests.test_versionedfile',
 
4117
        'bzrlib.tests.test_vf_search',
 
4118
        'bzrlib.tests.test_weave',
 
4119
        'bzrlib.tests.test_whitebox',
 
4120
        'bzrlib.tests.test_win32utils',
 
4121
        'bzrlib.tests.test_workingtree',
 
4122
        'bzrlib.tests.test_workingtree_4',
 
4123
        'bzrlib.tests.test_wsgi',
 
4124
        'bzrlib.tests.test_xml',
 
4125
        ]
 
4126
 
 
4127
 
 
4128
def _test_suite_modules_to_doctest():
 
4129
    """Return the list of modules to doctest."""
 
4130
    if __doc__ is None:
 
4131
        # GZ 2009-03-31: No docstrings with -OO so there's nothing to doctest
 
4132
        return []
 
4133
    return [
 
4134
        'bzrlib',
 
4135
        'bzrlib.branchbuilder',
 
4136
        'bzrlib.decorators',
 
4137
        'bzrlib.inventory',
 
4138
        'bzrlib.iterablefile',
 
4139
        'bzrlib.lockdir',
 
4140
        'bzrlib.merge3',
 
4141
        'bzrlib.option',
 
4142
        'bzrlib.pyutils',
 
4143
        'bzrlib.symbol_versioning',
 
4144
        'bzrlib.tests',
 
4145
        'bzrlib.tests.fixtures',
 
4146
        'bzrlib.timestamp',
 
4147
        'bzrlib.transport.http',
 
4148
        'bzrlib.version_info_formats.format_custom',
 
4149
        ]
 
4150
 
 
4151
 
 
4152
def test_suite(keep_only=None, starting_with=None):
2140
4153
    """Build and return TestSuite for the whole of bzrlib.
2141
 
    
 
4154
 
 
4155
    :param keep_only: A list of test ids limiting the suite returned.
 
4156
 
 
4157
    :param starting_with: An id limiting the suite returned to the tests
 
4158
         starting with it.
 
4159
 
2142
4160
    This function can be replaced if you need to change the default test
2143
4161
    suite on a global basis, but it is not encouraged.
2144
4162
    """
2145
 
    testmod_names = [
2146
 
                   'bzrlib.tests.test_ancestry',
2147
 
                   'bzrlib.tests.test_annotate',
2148
 
                   'bzrlib.tests.test_api',
2149
 
                   'bzrlib.tests.test_atomicfile',
2150
 
                   'bzrlib.tests.test_bad_files',
2151
 
                   'bzrlib.tests.test_branch',
2152
 
                   'bzrlib.tests.test_bundle',
2153
 
                   'bzrlib.tests.test_bzrdir',
2154
 
                   'bzrlib.tests.test_cache_utf8',
2155
 
                   'bzrlib.tests.test_commands',
2156
 
                   'bzrlib.tests.test_commit',
2157
 
                   'bzrlib.tests.test_commit_merge',
2158
 
                   'bzrlib.tests.test_config',
2159
 
                   'bzrlib.tests.test_conflicts',
2160
 
                   'bzrlib.tests.test_decorators',
2161
 
                   'bzrlib.tests.test_delta',
2162
 
                   'bzrlib.tests.test_diff',
2163
 
                   'bzrlib.tests.test_dirstate',
2164
 
                   'bzrlib.tests.test_doc_generate',
2165
 
                   'bzrlib.tests.test_errors',
2166
 
                   'bzrlib.tests.test_escaped_store',
2167
 
                   'bzrlib.tests.test_extract',
2168
 
                   'bzrlib.tests.test_fetch',
2169
 
                   'bzrlib.tests.test_ftp_transport',
2170
 
                   'bzrlib.tests.test_generate_docs',
2171
 
                   'bzrlib.tests.test_generate_ids',
2172
 
                   'bzrlib.tests.test_globbing',
2173
 
                   'bzrlib.tests.test_gpg',
2174
 
                   'bzrlib.tests.test_graph',
2175
 
                   'bzrlib.tests.test_hashcache',
2176
 
                   'bzrlib.tests.test_http',
2177
 
                   'bzrlib.tests.test_http_response',
2178
 
                   'bzrlib.tests.test_https_ca_bundle',
2179
 
                   'bzrlib.tests.test_identitymap',
2180
 
                   'bzrlib.tests.test_ignores',
2181
 
                   'bzrlib.tests.test_inv',
2182
 
                   'bzrlib.tests.test_knit',
2183
 
                   'bzrlib.tests.test_lazy_import',
2184
 
                   'bzrlib.tests.test_lazy_regex',
2185
 
                   'bzrlib.tests.test_lockdir',
2186
 
                   'bzrlib.tests.test_lockable_files',
2187
 
                   'bzrlib.tests.test_log',
2188
 
                   'bzrlib.tests.test_memorytree',
2189
 
                   'bzrlib.tests.test_merge',
2190
 
                   'bzrlib.tests.test_merge3',
2191
 
                   'bzrlib.tests.test_merge_core',
2192
 
                   'bzrlib.tests.test_merge_directive',
2193
 
                   'bzrlib.tests.test_missing',
2194
 
                   'bzrlib.tests.test_msgeditor',
2195
 
                   'bzrlib.tests.test_nonascii',
2196
 
                   'bzrlib.tests.test_options',
2197
 
                   'bzrlib.tests.test_osutils',
2198
 
                   'bzrlib.tests.test_osutils_encodings',
2199
 
                   'bzrlib.tests.test_patch',
2200
 
                   'bzrlib.tests.test_patches',
2201
 
                   'bzrlib.tests.test_permissions',
2202
 
                   'bzrlib.tests.test_plugins',
2203
 
                   'bzrlib.tests.test_progress',
2204
 
                   'bzrlib.tests.test_reconcile',
2205
 
                   'bzrlib.tests.test_registry',
2206
 
                   'bzrlib.tests.test_repository',
2207
 
                   'bzrlib.tests.test_revert',
2208
 
                   'bzrlib.tests.test_revision',
2209
 
                   'bzrlib.tests.test_revisionnamespaces',
2210
 
                   'bzrlib.tests.test_revisiontree',
2211
 
                   'bzrlib.tests.test_rio',
2212
 
                   'bzrlib.tests.test_sampler',
2213
 
                   'bzrlib.tests.test_selftest',
2214
 
                   'bzrlib.tests.test_setup',
2215
 
                   'bzrlib.tests.test_sftp_transport',
2216
 
                   'bzrlib.tests.test_smart_add',
2217
 
                   'bzrlib.tests.test_smart_transport',
2218
 
                   'bzrlib.tests.test_source',
2219
 
                   'bzrlib.tests.test_ssh_transport',
2220
 
                   'bzrlib.tests.test_status',
2221
 
                   'bzrlib.tests.test_store',
2222
 
                   'bzrlib.tests.test_strace',
2223
 
                   'bzrlib.tests.test_subsume',
2224
 
                   'bzrlib.tests.test_symbol_versioning',
2225
 
                   'bzrlib.tests.test_tag',
2226
 
                   'bzrlib.tests.test_testament',
2227
 
                   'bzrlib.tests.test_textfile',
2228
 
                   'bzrlib.tests.test_textmerge',
2229
 
                   'bzrlib.tests.test_timestamp',
2230
 
                   'bzrlib.tests.test_trace',
2231
 
                   'bzrlib.tests.test_transactions',
2232
 
                   'bzrlib.tests.test_transform',
2233
 
                   'bzrlib.tests.test_transport',
2234
 
                   'bzrlib.tests.test_tree',
2235
 
                   'bzrlib.tests.test_treebuilder',
2236
 
                   'bzrlib.tests.test_tsort',
2237
 
                   'bzrlib.tests.test_tuned_gzip',
2238
 
                   'bzrlib.tests.test_ui',
2239
 
                   'bzrlib.tests.test_upgrade',
2240
 
                   'bzrlib.tests.test_urlutils',
2241
 
                   'bzrlib.tests.test_versionedfile',
2242
 
                   'bzrlib.tests.test_version',
2243
 
                   'bzrlib.tests.test_version_info',
2244
 
                   'bzrlib.tests.test_weave',
2245
 
                   'bzrlib.tests.test_whitebox',
2246
 
                   'bzrlib.tests.test_workingtree',
2247
 
                   'bzrlib.tests.test_workingtree_4',
2248
 
                   'bzrlib.tests.test_wsgi',
2249
 
                   'bzrlib.tests.test_xml',
2250
 
                   ]
2251
 
    test_transport_implementations = [
2252
 
        'bzrlib.tests.test_transport_implementations',
2253
 
        'bzrlib.tests.test_read_bundle',
2254
 
        ]
2255
 
    suite = TestUtil.TestSuite()
 
4163
 
2256
4164
    loader = TestUtil.TestLoader()
2257
 
    suite.addTest(loader.loadTestsFromModuleNames(testmod_names))
2258
 
    from bzrlib.transport import TransportTestProviderAdapter
2259
 
    adapter = TransportTestProviderAdapter()
2260
 
    adapt_modules(test_transport_implementations, adapter, loader, suite)
2261
 
    for package in packages_to_test():
2262
 
        suite.addTest(package.test_suite())
2263
 
    for m in MODULES_TO_TEST:
2264
 
        suite.addTest(loader.loadTestsFromModule(m))
2265
 
    for m in MODULES_TO_DOCTEST:
 
4165
 
 
4166
    if keep_only is not None:
 
4167
        id_filter = TestIdList(keep_only)
 
4168
    if starting_with:
 
4169
        # We take precedence over keep_only because *at loading time* using
 
4170
        # both options means we will load less tests for the same final result.
 
4171
        def interesting_module(name):
 
4172
            for start in starting_with:
 
4173
                if (
 
4174
                    # Either the module name starts with the specified string
 
4175
                    name.startswith(start)
 
4176
                    # or it may contain tests starting with the specified string
 
4177
                    or start.startswith(name)
 
4178
                    ):
 
4179
                    return True
 
4180
            return False
 
4181
        loader = TestUtil.FilteredByModuleTestLoader(interesting_module)
 
4182
 
 
4183
    elif keep_only is not None:
 
4184
        loader = TestUtil.FilteredByModuleTestLoader(id_filter.refers_to)
 
4185
        def interesting_module(name):
 
4186
            return id_filter.refers_to(name)
 
4187
 
 
4188
    else:
 
4189
        loader = TestUtil.TestLoader()
 
4190
        def interesting_module(name):
 
4191
            # No filtering, all modules are interesting
 
4192
            return True
 
4193
 
 
4194
    suite = loader.suiteClass()
 
4195
 
 
4196
    # modules building their suite with loadTestsFromModuleNames
 
4197
    suite.addTest(loader.loadTestsFromModuleNames(_test_suite_testmod_names()))
 
4198
 
 
4199
    for mod in _test_suite_modules_to_doctest():
 
4200
        if not interesting_module(mod):
 
4201
            # No tests to keep here, move along
 
4202
            continue
2266
4203
        try:
2267
 
            suite.addTest(doctest.DocTestSuite(m))
 
4204
            # note that this really does mean "report only" -- doctest
 
4205
            # still runs the rest of the examples
 
4206
            doc_suite = IsolatedDocTestSuite(
 
4207
                mod, optionflags=doctest.REPORT_ONLY_FIRST_FAILURE)
2268
4208
        except ValueError, e:
2269
 
            print '**failed to get doctest for: %s\n%s' %(m,e)
 
4209
            print '**failed to get doctest for: %s\n%s' % (mod, e)
2270
4210
            raise
2271
 
    for name, plugin in bzrlib.plugin.all_plugins().items():
2272
 
        if getattr(plugin, 'test_suite', None) is not None:
2273
 
            default_encoding = sys.getdefaultencoding()
2274
 
            try:
2275
 
                plugin_suite = plugin.test_suite()
2276
 
            except ImportError, e:
2277
 
                bzrlib.trace.warning(
2278
 
                    'Unable to test plugin "%s": %s', name, e)
2279
 
            else:
2280
 
                suite.addTest(plugin_suite)
2281
 
            if default_encoding != sys.getdefaultencoding():
2282
 
                bzrlib.trace.warning(
2283
 
                    'Plugin "%s" tried to reset default encoding to: %s', name,
2284
 
                    sys.getdefaultencoding())
2285
 
                reload(sys)
2286
 
                sys.setdefaultencoding(default_encoding)
 
4211
        if len(doc_suite._tests) == 0:
 
4212
            raise errors.BzrError("no doctests found in %s" % (mod,))
 
4213
        suite.addTest(doc_suite)
 
4214
 
 
4215
    default_encoding = sys.getdefaultencoding()
 
4216
    for name, plugin in _mod_plugin.plugins().items():
 
4217
        if not interesting_module(plugin.module.__name__):
 
4218
            continue
 
4219
        plugin_suite = plugin.test_suite()
 
4220
        # We used to catch ImportError here and turn it into just a warning,
 
4221
        # but really if you don't have --no-plugins this should be a failure.
 
4222
        # mbp 20080213 - see http://bugs.launchpad.net/bugs/189771
 
4223
        if plugin_suite is None:
 
4224
            plugin_suite = plugin.load_plugin_tests(loader)
 
4225
        if plugin_suite is not None:
 
4226
            suite.addTest(plugin_suite)
 
4227
        if default_encoding != sys.getdefaultencoding():
 
4228
            trace.warning(
 
4229
                'Plugin "%s" tried to reset default encoding to: %s', name,
 
4230
                sys.getdefaultencoding())
 
4231
            reload(sys)
 
4232
            sys.setdefaultencoding(default_encoding)
 
4233
 
 
4234
    if keep_only is not None:
 
4235
        # Now that the referred modules have loaded their tests, keep only the
 
4236
        # requested ones.
 
4237
        suite = filter_suite_by_id_list(suite, id_filter)
 
4238
        # Do some sanity checks on the id_list filtering
 
4239
        not_found, duplicates = suite_matches_id_list(suite, keep_only)
 
4240
        if starting_with:
 
4241
            # The tester has used both keep_only and starting_with, so he is
 
4242
            # already aware that some tests are excluded from the list, there
 
4243
            # is no need to tell him which.
 
4244
            pass
 
4245
        else:
 
4246
            # Some tests mentioned in the list are not in the test suite. The
 
4247
            # list may be out of date, report to the tester.
 
4248
            for id in not_found:
 
4249
                trace.warning('"%s" not found in the test suite', id)
 
4250
        for id in duplicates:
 
4251
            trace.warning('"%s" is used as an id by several tests', id)
 
4252
 
2287
4253
    return suite
2288
4254
 
2289
4255
 
2290
 
def adapt_modules(mods_list, adapter, loader, suite):
2291
 
    """Adapt the modules in mods_list using adapter and add to suite."""
2292
 
    for test in iter_suite_tests(loader.loadTestsFromModuleNames(mods_list)):
2293
 
        suite.addTests(adapter.adapt(test))
2294
 
 
2295
 
 
2296
 
def _rmtree_temp_dir(dirname):
 
4256
def multiply_scenarios(*scenarios):
 
4257
    """Multiply two or more iterables of scenarios.
 
4258
 
 
4259
    It is safe to pass scenario generators or iterators.
 
4260
 
 
4261
    :returns: A list of compound scenarios: the cross-product of all 
 
4262
        scenarios, with the names concatenated and the parameters
 
4263
        merged together.
 
4264
    """
 
4265
    return reduce(_multiply_two_scenarios, map(list, scenarios))
 
4266
 
 
4267
 
 
4268
def _multiply_two_scenarios(scenarios_left, scenarios_right):
 
4269
    """Multiply two sets of scenarios.
 
4270
 
 
4271
    :returns: the cartesian product of the two sets of scenarios, that is
 
4272
        a scenario for every possible combination of a left scenario and a
 
4273
        right scenario.
 
4274
    """
 
4275
    return [
 
4276
        ('%s,%s' % (left_name, right_name),
 
4277
         dict(left_dict.items() + right_dict.items()))
 
4278
        for left_name, left_dict in scenarios_left
 
4279
        for right_name, right_dict in scenarios_right]
 
4280
 
 
4281
 
 
4282
def multiply_tests(tests, scenarios, result):
 
4283
    """Multiply tests_list by scenarios into result.
 
4284
 
 
4285
    This is the core workhorse for test parameterisation.
 
4286
 
 
4287
    Typically the load_tests() method for a per-implementation test suite will
 
4288
    call multiply_tests and return the result.
 
4289
 
 
4290
    :param tests: The tests to parameterise.
 
4291
    :param scenarios: The scenarios to apply: pairs of (scenario_name,
 
4292
        scenario_param_dict).
 
4293
    :param result: A TestSuite to add created tests to.
 
4294
 
 
4295
    This returns the passed in result TestSuite with the cross product of all
 
4296
    the tests repeated once for each scenario.  Each test is adapted by adding
 
4297
    the scenario name at the end of its id(), and updating the test object's
 
4298
    __dict__ with the scenario_param_dict.
 
4299
 
 
4300
    >>> import bzrlib.tests.test_sampler
 
4301
    >>> r = multiply_tests(
 
4302
    ...     bzrlib.tests.test_sampler.DemoTest('test_nothing'),
 
4303
    ...     [('one', dict(param=1)),
 
4304
    ...      ('two', dict(param=2))],
 
4305
    ...     TestUtil.TestSuite())
 
4306
    >>> tests = list(iter_suite_tests(r))
 
4307
    >>> len(tests)
 
4308
    2
 
4309
    >>> tests[0].id()
 
4310
    'bzrlib.tests.test_sampler.DemoTest.test_nothing(one)'
 
4311
    >>> tests[0].param
 
4312
    1
 
4313
    >>> tests[1].param
 
4314
    2
 
4315
    """
 
4316
    for test in iter_suite_tests(tests):
 
4317
        apply_scenarios(test, scenarios, result)
 
4318
    return result
 
4319
 
 
4320
 
 
4321
def apply_scenarios(test, scenarios, result):
 
4322
    """Apply the scenarios in scenarios to test and add to result.
 
4323
 
 
4324
    :param test: The test to apply scenarios to.
 
4325
    :param scenarios: An iterable of scenarios to apply to test.
 
4326
    :return: result
 
4327
    :seealso: apply_scenario
 
4328
    """
 
4329
    for scenario in scenarios:
 
4330
        result.addTest(apply_scenario(test, scenario))
 
4331
    return result
 
4332
 
 
4333
 
 
4334
def apply_scenario(test, scenario):
 
4335
    """Copy test and apply scenario to it.
 
4336
 
 
4337
    :param test: A test to adapt.
 
4338
    :param scenario: A tuple describing the scenarion.
 
4339
        The first element of the tuple is the new test id.
 
4340
        The second element is a dict containing attributes to set on the
 
4341
        test.
 
4342
    :return: The adapted test.
 
4343
    """
 
4344
    new_id = "%s(%s)" % (test.id(), scenario[0])
 
4345
    new_test = clone_test(test, new_id)
 
4346
    for name, value in scenario[1].items():
 
4347
        setattr(new_test, name, value)
 
4348
    return new_test
 
4349
 
 
4350
 
 
4351
def clone_test(test, new_id):
 
4352
    """Clone a test giving it a new id.
 
4353
 
 
4354
    :param test: The test to clone.
 
4355
    :param new_id: The id to assign to it.
 
4356
    :return: The new test.
 
4357
    """
 
4358
    new_test = copy.copy(test)
 
4359
    new_test.id = lambda: new_id
 
4360
    # XXX: Workaround <https://bugs.launchpad.net/testtools/+bug/637725>, which
 
4361
    # causes cloned tests to share the 'details' dict.  This makes it hard to
 
4362
    # read the test output for parameterized tests, because tracebacks will be
 
4363
    # associated with irrelevant tests.
 
4364
    try:
 
4365
        details = new_test._TestCase__details
 
4366
    except AttributeError:
 
4367
        # must be a different version of testtools than expected.  Do nothing.
 
4368
        pass
 
4369
    else:
 
4370
        # Reset the '__details' dict.
 
4371
        new_test._TestCase__details = {}
 
4372
    return new_test
 
4373
 
 
4374
 
 
4375
def permute_tests_for_extension(standard_tests, loader, py_module_name,
 
4376
                                ext_module_name):
 
4377
    """Helper for permutating tests against an extension module.
 
4378
 
 
4379
    This is meant to be used inside a modules 'load_tests()' function. It will
 
4380
    create 2 scenarios, and cause all tests in the 'standard_tests' to be run
 
4381
    against both implementations. Setting 'test.module' to the appropriate
 
4382
    module. See bzrlib.tests.test__chk_map.load_tests as an example.
 
4383
 
 
4384
    :param standard_tests: A test suite to permute
 
4385
    :param loader: A TestLoader
 
4386
    :param py_module_name: The python path to a python module that can always
 
4387
        be loaded, and will be considered the 'python' implementation. (eg
 
4388
        'bzrlib._chk_map_py')
 
4389
    :param ext_module_name: The python path to an extension module. If the
 
4390
        module cannot be loaded, a single test will be added, which notes that
 
4391
        the module is not available. If it can be loaded, all standard_tests
 
4392
        will be run against that module.
 
4393
    :return: (suite, feature) suite is a test-suite that has all the permuted
 
4394
        tests. feature is the Feature object that can be used to determine if
 
4395
        the module is available.
 
4396
    """
 
4397
 
 
4398
    from bzrlib.tests.features import ModuleAvailableFeature
 
4399
    py_module = pyutils.get_named_object(py_module_name)
 
4400
    scenarios = [
 
4401
        ('python', {'module': py_module}),
 
4402
    ]
 
4403
    suite = loader.suiteClass()
 
4404
    feature = ModuleAvailableFeature(ext_module_name)
 
4405
    if feature.available():
 
4406
        scenarios.append(('C', {'module': feature.module}))
 
4407
    else:
 
4408
        # the compiled module isn't available, so we add a failing test
 
4409
        class FailWithoutFeature(TestCase):
 
4410
            def test_fail(self):
 
4411
                self.requireFeature(feature)
 
4412
        suite.addTest(loader.loadTestsFromTestCase(FailWithoutFeature))
 
4413
    result = multiply_tests(standard_tests, scenarios, suite)
 
4414
    return result, feature
 
4415
 
 
4416
 
 
4417
def _rmtree_temp_dir(dirname, test_id=None):
 
4418
    # If LANG=C we probably have created some bogus paths
 
4419
    # which rmtree(unicode) will fail to delete
 
4420
    # so make sure we are using rmtree(str) to delete everything
 
4421
    # except on win32, where rmtree(str) will fail
 
4422
    # since it doesn't have the property of byte-stream paths
 
4423
    # (they are either ascii or mbcs)
 
4424
    if sys.platform == 'win32':
 
4425
        # make sure we are using the unicode win32 api
 
4426
        dirname = unicode(dirname)
 
4427
    else:
 
4428
        dirname = dirname.encode(sys.getfilesystemencoding())
2297
4429
    try:
2298
4430
        osutils.rmtree(dirname)
2299
4431
    except OSError, e:
2300
 
        if sys.platform == 'win32' and e.errno == errno.EACCES:
2301
 
            print >>sys.stderr, ('Permission denied: '
2302
 
                                 'unable to remove testing dir '
2303
 
                                 '%s' % os.path.basename(dirname))
 
4432
        # We don't want to fail here because some useful display will be lost
 
4433
        # otherwise. Polluting the tmp dir is bad, but not giving all the
 
4434
        # possible info to the test runner is even worse.
 
4435
        if test_id != None:
 
4436
            ui.ui_factory.clear_term()
 
4437
            sys.stderr.write('\nWhile running: %s\n' % (test_id,))
 
4438
        # Ugly, but the last thing we want here is fail, so bear with it.
 
4439
        printable_e = str(e).decode(osutils.get_user_encoding(), 'replace'
 
4440
                                    ).encode('ascii', 'replace')
 
4441
        sys.stderr.write('Unable to remove testing dir %s\n%s'
 
4442
                         % (os.path.basename(dirname), printable_e))
 
4443
 
 
4444
 
 
4445
def probe_unicode_in_user_encoding():
 
4446
    """Try to encode several unicode strings to use in unicode-aware tests.
 
4447
    Return first successfull match.
 
4448
 
 
4449
    :return:  (unicode value, encoded plain string value) or (None, None)
 
4450
    """
 
4451
    possible_vals = [u'm\xb5', u'\xe1', u'\u0410']
 
4452
    for uni_val in possible_vals:
 
4453
        try:
 
4454
            str_val = uni_val.encode(osutils.get_user_encoding())
 
4455
        except UnicodeEncodeError:
 
4456
            # Try a different character
 
4457
            pass
2304
4458
        else:
2305
 
            raise
2306
 
 
2307
 
 
2308
 
def clean_selftest_output(root=None, quiet=False):
2309
 
    """Remove all selftest output directories from root directory.
2310
 
 
2311
 
    :param  root:   root directory for clean
2312
 
                    (if ommitted or None then clean current directory).
2313
 
    :param  quiet:  suppress report about deleting directories
 
4459
            return uni_val, str_val
 
4460
    return None, None
 
4461
 
 
4462
 
 
4463
def probe_bad_non_ascii(encoding):
 
4464
    """Try to find [bad] character with code [128..255]
 
4465
    that cannot be decoded to unicode in some encoding.
 
4466
    Return None if all non-ascii characters is valid
 
4467
    for given encoding.
2314
4468
    """
2315
 
    import re
2316
 
    import shutil
2317
 
 
2318
 
    re_dir = re.compile(r'''test\d\d\d\d\.tmp''')
2319
 
    if root is None:
2320
 
        root = u'.'
2321
 
    for i in os.listdir(root):
2322
 
        if os.path.isdir(i) and re_dir.match(i):
2323
 
            if not quiet:
2324
 
                print 'delete directory:', i
2325
 
            _rmtree_temp_dir(i)
2326
 
 
2327
 
 
2328
 
class Feature(object):
2329
 
    """An operating system Feature."""
2330
 
 
2331
 
    def __init__(self):
2332
 
        self._available = None
2333
 
 
2334
 
    def available(self):
2335
 
        """Is the feature available?
2336
 
 
2337
 
        :return: True if the feature is available.
2338
 
        """
2339
 
        if self._available is None:
2340
 
            self._available = self._probe()
2341
 
        return self._available
2342
 
 
2343
 
    def _probe(self):
2344
 
        """Implement this method in concrete features.
2345
 
 
2346
 
        :return: True if the feature is available.
2347
 
        """
2348
 
        raise NotImplementedError
2349
 
 
2350
 
    def __str__(self):
2351
 
        if getattr(self, 'feature_name', None):
2352
 
            return self.feature_name()
2353
 
        return self.__class__.__name__
 
4469
    for i in xrange(128, 256):
 
4470
        char = chr(i)
 
4471
        try:
 
4472
            char.decode(encoding)
 
4473
        except UnicodeDecodeError:
 
4474
            return char
 
4475
    return None
 
4476
 
 
4477
 
 
4478
# Only define SubUnitBzrRunner if subunit is available.
 
4479
try:
 
4480
    from subunit import TestProtocolClient
 
4481
    from subunit.test_results import AutoTimingTestResultDecorator
 
4482
    class SubUnitBzrProtocolClient(TestProtocolClient):
 
4483
 
 
4484
        def stopTest(self, test):
 
4485
            super(SubUnitBzrProtocolClient, self).stopTest(test)
 
4486
            _clear__type_equality_funcs(test)
 
4487
 
 
4488
        def addSuccess(self, test, details=None):
 
4489
            # The subunit client always includes the details in the subunit
 
4490
            # stream, but we don't want to include it in ours.
 
4491
            if details is not None and 'log' in details:
 
4492
                del details['log']
 
4493
            return super(SubUnitBzrProtocolClient, self).addSuccess(
 
4494
                test, details)
 
4495
 
 
4496
    class SubUnitBzrRunner(TextTestRunner):
 
4497
        def run(self, test):
 
4498
            result = AutoTimingTestResultDecorator(
 
4499
                SubUnitBzrProtocolClient(self.stream))
 
4500
            test.run(result)
 
4501
            return result
 
4502
except ImportError:
 
4503
    pass
 
4504
 
 
4505
 
 
4506
# API compatibility for old plugins; see bug 892622.
 
4507
for name in [
 
4508
    'Feature',
 
4509
    'HTTPServerFeature', 
 
4510
    'ModuleAvailableFeature',
 
4511
    'HTTPSServerFeature', 'SymlinkFeature', 'HardlinkFeature',
 
4512
    'OsFifoFeature', 'UnicodeFilenameFeature',
 
4513
    'ByteStringNamedFilesystem', 'UTF8Filesystem',
 
4514
    'BreakinFeature', 'CaseInsCasePresFilenameFeature',
 
4515
    'CaseInsensitiveFilesystemFeature', 'case_sensitive_filesystem_feature',
 
4516
    'posix_permissions_feature',
 
4517
    ]:
 
4518
    globals()[name] = _CompatabilityThunkFeature(
 
4519
        symbol_versioning.deprecated_in((2, 5, 0)),
 
4520
        'bzrlib.tests', name,
 
4521
        name, 'bzrlib.tests.features')
 
4522
 
 
4523
 
 
4524
for (old_name, new_name) in [
 
4525
    ('UnicodeFilename', 'UnicodeFilenameFeature'),
 
4526
    ]:
 
4527
    globals()[name] = _CompatabilityThunkFeature(
 
4528
        symbol_versioning.deprecated_in((2, 5, 0)),
 
4529
        'bzrlib.tests', old_name,
 
4530
        new_name, 'bzrlib.tests.features')