~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/__init__.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2010-01-25 10:54:10 UTC
  • mfrom: (4981.2.4 jam-integration)
  • Revision ID: pqm@pqm.ubuntu.com-20100125105410-8l7842imp6z7jcs4
(jam) Update to win32_setup

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2011 Canonical Ltd
 
1
# Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
 
"""Testing framework extensions"""
 
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)
18
23
 
19
24
# NOTE: Some classes in here use camelCaseNaming() rather than
20
25
# underscore_naming().  That's for consistency with unittest; it's not the
23
28
 
24
29
import atexit
25
30
import codecs
26
 
import copy
 
31
from copy import copy
27
32
from cStringIO import StringIO
28
33
import difflib
29
34
import doctest
30
35
import errno
31
 
import itertools
32
36
import logging
 
37
import math
33
38
import os
34
 
import platform
35
 
import pprint
 
39
from pprint import pformat
36
40
import random
37
41
import re
38
42
import shlex
39
43
import stat
40
 
import subprocess
 
44
from subprocess import Popen, PIPE, STDOUT
41
45
import sys
42
46
import tempfile
43
47
import threading
49
53
import testtools
50
54
# nb: check this before importing anything else from within it
51
55
_testtools_version = getattr(testtools, '__version__', ())
52
 
if _testtools_version < (0, 9, 5):
53
 
    raise ImportError("need at least testtools 0.9.5: %s is %r"
 
56
if _testtools_version < (0, 9, 2):
 
57
    raise ImportError("need at least testtools 0.9.2: %s is %r"
54
58
        % (testtools.__file__, _testtools_version))
55
59
from testtools import content
56
60
 
57
 
import bzrlib
58
61
from bzrlib import (
59
62
    branchbuilder,
60
63
    bzrdir,
61
64
    chk_map,
62
 
    commands as _mod_commands,
63
65
    config,
64
66
    debug,
65
67
    errors,
66
68
    hooks,
67
69
    lock as _mod_lock,
68
 
    lockdir,
69
70
    memorytree,
70
71
    osutils,
71
 
    plugin as _mod_plugin,
72
 
    pyutils,
 
72
    progress,
73
73
    ui,
74
74
    urlutils,
75
75
    registry,
76
 
    symbol_versioning,
77
 
    trace,
78
 
    transport as _mod_transport,
79
76
    workingtree,
80
77
    )
 
78
import bzrlib.branch
 
79
import bzrlib.commands
 
80
import bzrlib.timestamp
 
81
import bzrlib.export
 
82
import bzrlib.inventory
 
83
import bzrlib.iterablefile
 
84
import bzrlib.lockdir
81
85
try:
82
86
    import bzrlib.lsprof
83
87
except ImportError:
84
88
    # lsprof not available
85
89
    pass
86
 
from bzrlib.smart import client, request
87
 
from bzrlib.transport import (
88
 
    memory,
89
 
    pathfilter,
90
 
    )
 
90
from bzrlib.merge import merge_inner
 
91
import bzrlib.merge3
 
92
import bzrlib.plugin
 
93
from bzrlib.smart import client, request, server
 
94
import bzrlib.store
 
95
from bzrlib import symbol_versioning
91
96
from bzrlib.symbol_versioning import (
 
97
    DEPRECATED_PARAMETER,
92
98
    deprecated_function,
93
99
    deprecated_in,
94
 
    )
95
 
from bzrlib.tests import (
96
 
    test_server,
97
 
    TestUtil,
98
 
    treeshape,
99
 
    )
 
100
    deprecated_method,
 
101
    deprecated_passed,
 
102
    )
 
103
import bzrlib.trace
 
104
from bzrlib.transport import get_transport, pathfilter
 
105
import bzrlib.transport
 
106
from bzrlib.transport.local import LocalURLServer
 
107
from bzrlib.transport.memory import MemoryServer
 
108
from bzrlib.transport.readonly import ReadonlyServer
 
109
from bzrlib.trace import mutter, note
 
110
from bzrlib.tests import TestUtil
 
111
from bzrlib.tests.http_server import HttpServer
 
112
from bzrlib.tests.TestUtil import (
 
113
                          TestSuite,
 
114
                          TestLoader,
 
115
                          )
 
116
from bzrlib.tests.treeshape import build_tree_contents
100
117
from bzrlib.ui import NullProgressView
101
118
from bzrlib.ui.text import TextUIFactory
 
119
import bzrlib.version_info_formats.format_custom
 
120
from bzrlib.workingtree import WorkingTree, WorkingTreeFormat2
102
121
 
103
122
# Mark this python module as being part of the implementation
104
123
# of unittest: this gives us better tracebacks where the last
105
124
# shown frame is the test code, not our assertXYZ.
106
125
__unittest = 1
107
126
 
108
 
default_transport = test_server.LocalURLServer
109
 
 
110
 
 
111
 
_unitialized_attr = object()
112
 
"""A sentinel needed to act as a default value in a method signature."""
113
 
 
 
127
default_transport = LocalURLServer
114
128
 
115
129
# Subunit result codes, defined here to prevent a hard dependency on subunit.
116
130
SUBUNIT_SEEK_SET = 0
117
131
SUBUNIT_SEEK_CUR = 1
118
132
 
119
 
# These are intentionally brought into this namespace. That way plugins, etc
120
 
# can just "from bzrlib.tests import TestCase, TestLoader, etc"
121
 
TestSuite = TestUtil.TestSuite
122
 
TestLoader = TestUtil.TestLoader
123
 
 
124
 
# Tests should run in a clean and clearly defined environment. The goal is to
125
 
# keep them isolated from the running environment as mush as possible. The test
126
 
# framework ensures the variables defined below are set (or deleted if the
127
 
# value is None) before a test is run and reset to their original value after
128
 
# the test is run. Generally if some code depends on an environment variable,
129
 
# the tests should start without this variable in the environment. There are a
130
 
# few exceptions but you shouldn't violate this rule lightly.
131
 
isolated_environ = {
132
 
    'BZR_HOME': None,
133
 
    'HOME': None,
134
 
    # bzr now uses the Win32 API and doesn't rely on APPDATA, but the
135
 
    # tests do check our impls match APPDATA
136
 
    'BZR_EDITOR': None, # test_msgeditor manipulates this variable
137
 
    'VISUAL': None,
138
 
    'EDITOR': None,
139
 
    'BZR_EMAIL': None,
140
 
    'BZREMAIL': None, # may still be present in the environment
141
 
    'EMAIL': 'jrandom@example.com', # set EMAIL as bzr does not guess
142
 
    'BZR_PROGRESS_BAR': None,
143
 
    # This should trap leaks to ~/.bzr.log. This occurs when tests use TestCase
144
 
    # as a base class instead of TestCaseInTempDir. Tests inheriting from
145
 
    # TestCase should not use disk resources, BZR_LOG is one.
146
 
    'BZR_LOG': '/you-should-use-TestCaseInTempDir-if-you-need-a-log-file',
147
 
    'BZR_PLUGIN_PATH': None,
148
 
    'BZR_DISABLE_PLUGINS': None,
149
 
    'BZR_PLUGINS_AT': None,
150
 
    'BZR_CONCURRENCY': None,
151
 
    # Make sure that any text ui tests are consistent regardless of
152
 
    # the environment the test case is run in; you may want tests that
153
 
    # test other combinations.  'dumb' is a reasonable guess for tests
154
 
    # going to a pipe or a StringIO.
155
 
    'TERM': 'dumb',
156
 
    'LINES': '25',
157
 
    'COLUMNS': '80',
158
 
    'BZR_COLUMNS': '80',
159
 
    # Disable SSH Agent
160
 
    'SSH_AUTH_SOCK': None,
161
 
    # Proxies
162
 
    'http_proxy': None,
163
 
    'HTTP_PROXY': None,
164
 
    'https_proxy': None,
165
 
    'HTTPS_PROXY': None,
166
 
    'no_proxy': None,
167
 
    'NO_PROXY': None,
168
 
    'all_proxy': None,
169
 
    'ALL_PROXY': None,
170
 
    # Nobody cares about ftp_proxy, FTP_PROXY AFAIK. So far at
171
 
    # least. If you do (care), please update this comment
172
 
    # -- vila 20080401
173
 
    'ftp_proxy': None,
174
 
    'FTP_PROXY': None,
175
 
    'BZR_REMOTE_PATH': None,
176
 
    # Generally speaking, we don't want apport reporting on crashes in
177
 
    # the test envirnoment unless we're specifically testing apport,
178
 
    # so that it doesn't leak into the real system environment.  We
179
 
    # use an env var so it propagates to subprocesses.
180
 
    'APPORT_DISABLE': '1',
181
 
    }
182
 
 
183
 
 
184
 
def override_os_environ(test, env=None):
185
 
    """Modify os.environ keeping a copy.
186
 
    
187
 
    :param test: A test instance
188
 
 
189
 
    :param env: A dict containing variable definitions to be installed
190
 
    """
191
 
    if env is None:
192
 
        env = isolated_environ
193
 
    test._original_os_environ = dict([(var, value)
194
 
                                      for var, value in os.environ.iteritems()])
195
 
    for var, value in env.iteritems():
196
 
        osutils.set_or_unset_env(var, value)
197
 
        if var not in test._original_os_environ:
198
 
            # The var is new, add it with a value of None, so
199
 
            # restore_os_environ will delete it
200
 
            test._original_os_environ[var] = None
201
 
 
202
 
 
203
 
def restore_os_environ(test):
204
 
    """Restore os.environ to its original state.
205
 
 
206
 
    :param test: A test instance previously passed to override_os_environ.
207
 
    """
208
 
    for var, value in test._original_os_environ.iteritems():
209
 
        # Restore the original value (or delete it if the value has been set to
210
 
        # None in override_os_environ).
211
 
        osutils.set_or_unset_env(var, value)
212
 
 
213
 
 
214
 
class ExtendedTestResult(testtools.TextTestResult):
 
133
 
 
134
class ExtendedTestResult(unittest._TextTestResult):
215
135
    """Accepts, reports and accumulates the results of running tests.
216
136
 
217
137
    Compared to the unittest version this class adds support for
238
158
        :param bench_history: Optionally, a writable file object to accumulate
239
159
            benchmark results.
240
160
        """
241
 
        testtools.TextTestResult.__init__(self, stream)
 
161
        unittest._TextTestResult.__init__(self, stream, descriptions, verbosity)
242
162
        if bench_history is not None:
243
163
            from bzrlib.version import _get_bzr_source_tree
244
164
            src_tree = _get_bzr_source_tree()
265
185
        self.count = 0
266
186
        self._overall_start_time = time.time()
267
187
        self._strict = strict
268
 
        self._first_thread_leaker_id = None
269
 
        self._tests_leaking_threads_count = 0
270
 
        self._traceback_from_test = None
271
188
 
272
189
    def stopTestRun(self):
273
190
        run = self.testsRun
274
191
        actionTaken = "Ran"
275
192
        stopTime = time.time()
276
193
        timeTaken = stopTime - self.startTime
277
 
        # GZ 2010-07-19: Seems testtools has no printErrors method, and though
278
 
        #                the parent class method is similar have to duplicate
279
 
        self._show_list('ERROR', self.errors)
280
 
        self._show_list('FAIL', self.failures)
281
 
        self.stream.write(self.sep2)
282
 
        self.stream.write("%s %d test%s in %.3fs\n\n" % (actionTaken,
 
194
        self.printErrors()
 
195
        self.stream.writeln(self.separator2)
 
196
        self.stream.writeln("%s %d test%s in %.3fs" % (actionTaken,
283
197
                            run, run != 1 and "s" or "", timeTaken))
 
198
        self.stream.writeln()
284
199
        if not self.wasSuccessful():
285
200
            self.stream.write("FAILED (")
286
201
            failed, errored = map(len, (self.failures, self.errors))
293
208
                if failed or errored: self.stream.write(", ")
294
209
                self.stream.write("known_failure_count=%d" %
295
210
                    self.known_failure_count)
296
 
            self.stream.write(")\n")
 
211
            self.stream.writeln(")")
297
212
        else:
298
213
            if self.known_failure_count:
299
 
                self.stream.write("OK (known_failures=%d)\n" %
 
214
                self.stream.writeln("OK (known_failures=%d)" %
300
215
                    self.known_failure_count)
301
216
            else:
302
 
                self.stream.write("OK\n")
 
217
                self.stream.writeln("OK")
303
218
        if self.skip_count > 0:
304
219
            skipped = self.skip_count
305
 
            self.stream.write('%d test%s skipped\n' %
 
220
            self.stream.writeln('%d test%s skipped' %
306
221
                                (skipped, skipped != 1 and "s" or ""))
307
222
        if self.unsupported:
308
223
            for feature, count in sorted(self.unsupported.items()):
309
 
                self.stream.write("Missing feature '%s' skipped %d tests.\n" %
 
224
                self.stream.writeln("Missing feature '%s' skipped %d tests." %
310
225
                    (feature, count))
311
226
        if self._strict:
312
227
            ok = self.wasStrictlySuccessful()
313
228
        else:
314
229
            ok = self.wasSuccessful()
315
 
        if self._first_thread_leaker_id:
 
230
        if TestCase._first_thread_leaker_id:
316
231
            self.stream.write(
317
232
                '%s is leaking threads among %d leaking tests.\n' % (
318
 
                self._first_thread_leaker_id,
319
 
                self._tests_leaking_threads_count))
 
233
                TestCase._first_thread_leaker_id,
 
234
                TestCase._leaking_threads_tests))
320
235
            # We don't report the main thread as an active one.
321
236
            self.stream.write(
322
237
                '%d non-main threads were left active in the end.\n'
323
 
                % (len(self._active_threads) - 1))
 
238
                % (TestCase._active_threads - 1))
324
239
 
325
240
    def getDescription(self, test):
326
241
        return test.id()
333
248
 
334
249
    def _elapsedTestTimeString(self):
335
250
        """Return a time string for the overall time the current test has taken."""
336
 
        return self._formatTime(self._delta_to_float(
337
 
            self._now() - self._start_datetime))
 
251
        return self._formatTime(time.time() - self._start_time)
338
252
 
339
253
    def _testTimeString(self, testCase):
340
254
        benchmark_time = self._extractBenchmarkTime(testCase)
351
265
 
352
266
    def _shortened_test_description(self, test):
353
267
        what = test.id()
354
 
        what = re.sub(r'^bzrlib\.tests\.', '', what)
 
268
        what = re.sub(r'^bzrlib\.(tests|benchmarks)\.', '', what)
355
269
        return what
356
270
 
357
 
    # GZ 2010-10-04: Cloned tests may end up harmlessly calling this method
358
 
    #                multiple times in a row, because the handler is added for
359
 
    #                each test but the container list is shared between cases.
360
 
    #                See lp:498869 lp:625574 and lp:637725 for background.
361
 
    def _record_traceback_from_test(self, exc_info):
362
 
        """Store the traceback from passed exc_info tuple till"""
363
 
        self._traceback_from_test = exc_info[2]
364
 
 
365
271
    def startTest(self, test):
366
 
        super(ExtendedTestResult, self).startTest(test)
 
272
        unittest.TestResult.startTest(self, test)
367
273
        if self.count == 0:
368
274
            self.startTests()
369
 
        self.count += 1
370
275
        self.report_test_start(test)
371
276
        test.number = self.count
372
277
        self._recordTestStartTime()
373
 
        # Make testtools cases give us the real traceback on failure
374
 
        addOnException = getattr(test, "addOnException", None)
375
 
        if addOnException is not None:
376
 
            addOnException(self._record_traceback_from_test)
377
 
        # Only check for thread leaks on bzrlib derived test cases
378
 
        if isinstance(test, TestCase):
379
 
            test.addCleanup(self._check_leaked_threads, test)
380
 
 
381
 
    def stopTest(self, test):
382
 
        super(ExtendedTestResult, self).stopTest(test)
383
 
        # Manually break cycles, means touching various private things but hey
384
 
        getDetails = getattr(test, "getDetails", None)
385
 
        if getDetails is not None:
386
 
            getDetails().clear()
387
 
        # Clear _type_equality_funcs to try to stop TestCase instances
388
 
        # from wasting memory. 'clear' is not available in all Python
389
 
        # versions (bug 809048)
390
 
        type_equality_funcs = getattr(test, "_type_equality_funcs", None)
391
 
        if type_equality_funcs is not None:
392
 
            tef_clear = getattr(type_equality_funcs, "clear", None)
393
 
            if tef_clear is None:
394
 
                tef_instance_dict = getattr(type_equality_funcs, "__dict__", None)
395
 
                if tef_instance_dict is not None:
396
 
                    tef_clear = tef_instance_dict.clear
397
 
            if tef_clear is not None:
398
 
                tef_clear()
399
 
        self._traceback_from_test = None
400
278
 
401
279
    def startTests(self):
402
 
        self.report_tests_starting()
403
 
        self._active_threads = threading.enumerate()
404
 
 
405
 
    def _check_leaked_threads(self, test):
406
 
        """See if any threads have leaked since last call
407
 
 
408
 
        A sample of live threads is stored in the _active_threads attribute,
409
 
        when this method runs it compares the current live threads and any not
410
 
        in the previous sample are treated as having leaked.
411
 
        """
412
 
        now_active_threads = set(threading.enumerate())
413
 
        threads_leaked = now_active_threads.difference(self._active_threads)
414
 
        if threads_leaked:
415
 
            self._report_thread_leak(test, threads_leaked, now_active_threads)
416
 
            self._tests_leaking_threads_count += 1
417
 
            if self._first_thread_leaker_id is None:
418
 
                self._first_thread_leaker_id = test.id()
419
 
            self._active_threads = now_active_threads
 
280
        import platform
 
281
        if getattr(sys, 'frozen', None) is None:
 
282
            bzr_path = osutils.realpath(sys.argv[0])
 
283
        else:
 
284
            bzr_path = sys.executable
 
285
        self.stream.write(
 
286
            'bzr selftest: %s\n' % (bzr_path,))
 
287
        self.stream.write(
 
288
            '   %s\n' % (
 
289
                    bzrlib.__path__[0],))
 
290
        self.stream.write(
 
291
            '   bzr-%s python-%s %s\n' % (
 
292
                    bzrlib.version_string,
 
293
                    bzrlib._format_version_tuple(sys.version_info),
 
294
                    platform.platform(aliased=1),
 
295
                    ))
 
296
        self.stream.write('\n')
420
297
 
421
298
    def _recordTestStartTime(self):
422
299
        """Record that a test has started."""
423
 
        self._start_datetime = self._now()
 
300
        self._start_time = time.time()
 
301
 
 
302
    def _cleanupLogFile(self, test):
 
303
        # We can only do this if we have one of our TestCases, not if
 
304
        # we have a doctest.
 
305
        setKeepLogfile = getattr(test, 'setKeepLogfile', None)
 
306
        if setKeepLogfile is not None:
 
307
            setKeepLogfile()
424
308
 
425
309
    def addError(self, test, err):
426
310
        """Tell result that test finished with an error.
428
312
        Called from the TestCase run() method when the test
429
313
        fails with an unexpected error.
430
314
        """
431
 
        self._post_mortem(self._traceback_from_test)
432
 
        super(ExtendedTestResult, self).addError(test, err)
 
315
        self._post_mortem()
 
316
        unittest.TestResult.addError(self, test, err)
433
317
        self.error_count += 1
434
318
        self.report_error(test, err)
435
319
        if self.stop_early:
436
320
            self.stop()
 
321
        self._cleanupLogFile(test)
437
322
 
438
323
    def addFailure(self, test, err):
439
324
        """Tell result that test failed.
441
326
        Called from the TestCase run() method when the test
442
327
        fails because e.g. an assert() method failed.
443
328
        """
444
 
        self._post_mortem(self._traceback_from_test)
445
 
        super(ExtendedTestResult, self).addFailure(test, err)
 
329
        self._post_mortem()
 
330
        unittest.TestResult.addFailure(self, test, err)
446
331
        self.failure_count += 1
447
332
        self.report_failure(test, err)
448
333
        if self.stop_early:
449
334
            self.stop()
 
335
        self._cleanupLogFile(test)
450
336
 
451
337
    def addSuccess(self, test, details=None):
452
338
        """Tell result that test completed successfully.
460
346
                    self._formatTime(benchmark_time),
461
347
                    test.id()))
462
348
        self.report_success(test)
463
 
        super(ExtendedTestResult, self).addSuccess(test)
 
349
        self._cleanupLogFile(test)
 
350
        unittest.TestResult.addSuccess(self, test)
464
351
        test._log_contents = ''
465
352
 
466
353
    def addExpectedFailure(self, test, err):
467
354
        self.known_failure_count += 1
468
355
        self.report_known_failure(test, err)
469
356
 
470
 
    def addUnexpectedSuccess(self, test, details=None):
471
 
        """Tell result the test unexpectedly passed, counting as a failure
472
 
 
473
 
        When the minimum version of testtools required becomes 0.9.8 this
474
 
        can be updated to use the new handling there.
475
 
        """
476
 
        super(ExtendedTestResult, self).addFailure(test, details=details)
477
 
        self.failure_count += 1
478
 
        self.report_unexpected_success(test,
479
 
            "".join(details["reason"].iter_text()))
480
 
        if self.stop_early:
481
 
            self.stop()
482
 
 
483
357
    def addNotSupported(self, test, feature):
484
358
        """The test will not be run because of a missing feature.
485
359
        """
502
376
        self.not_applicable_count += 1
503
377
        self.report_not_applicable(test, reason)
504
378
 
505
 
    def _post_mortem(self, tb=None):
 
379
    def _post_mortem(self):
506
380
        """Start a PDB post mortem session."""
507
381
        if os.environ.get('BZR_TEST_PDB', None):
508
 
            import pdb
509
 
            pdb.post_mortem(tb)
 
382
            import pdb;pdb.post_mortem()
510
383
 
511
384
    def progress(self, offset, whence):
512
385
        """The test is adjusting the count of tests to run."""
517
390
        else:
518
391
            raise errors.BzrError("Unknown whence %r" % whence)
519
392
 
520
 
    def report_tests_starting(self):
521
 
        """Display information before the test run begins"""
522
 
        if getattr(sys, 'frozen', None) is None:
523
 
            bzr_path = osutils.realpath(sys.argv[0])
524
 
        else:
525
 
            bzr_path = sys.executable
526
 
        self.stream.write(
527
 
            'bzr selftest: %s\n' % (bzr_path,))
528
 
        self.stream.write(
529
 
            '   %s\n' % (
530
 
                    bzrlib.__path__[0],))
531
 
        self.stream.write(
532
 
            '   bzr-%s python-%s %s\n' % (
533
 
                    bzrlib.version_string,
534
 
                    bzrlib._format_version_tuple(sys.version_info),
535
 
                    platform.platform(aliased=1),
536
 
                    ))
537
 
        self.stream.write('\n')
538
 
 
539
 
    def report_test_start(self, test):
540
 
        """Display information on the test just about to be run"""
541
 
 
542
 
    def _report_thread_leak(self, test, leaked_threads, active_threads):
543
 
        """Display information on a test that leaked one or more threads"""
544
 
        # GZ 2010-09-09: A leak summary reported separately from the general
545
 
        #                thread debugging would be nice. Tests under subunit
546
 
        #                need something not using stream, perhaps adding a
547
 
        #                testtools details object would be fitting.
548
 
        if 'threads' in selftest_debug_flags:
549
 
            self.stream.write('%s is leaking, active is now %d\n' %
550
 
                (test.id(), len(active_threads)))
 
393
    def report_cleaning_up(self):
 
394
        pass
551
395
 
552
396
    def startTestRun(self):
553
397
        self.startTime = time.time()
590
434
        self.pb.finished()
591
435
        super(TextTestResult, self).stopTestRun()
592
436
 
593
 
    def report_tests_starting(self):
594
 
        super(TextTestResult, self).report_tests_starting()
 
437
    def startTestRun(self):
 
438
        super(TextTestResult, self).startTestRun()
595
439
        self.pb.update('[test 0/%d] Starting' % (self.num_tests))
596
440
 
 
441
    def printErrors(self):
 
442
        # clear the pb to make room for the error listing
 
443
        self.pb.clear()
 
444
        super(TextTestResult, self).printErrors()
 
445
 
597
446
    def _progress_prefix_text(self):
598
447
        # the longer this text, the less space we have to show the test
599
448
        # name...
621
470
        return a
622
471
 
623
472
    def report_test_start(self, test):
 
473
        self.count += 1
624
474
        self.pb.update(
625
475
                self._progress_prefix_text()
626
476
                + ' '
630
480
        return self._shortened_test_description(test)
631
481
 
632
482
    def report_error(self, test, err):
633
 
        self.stream.write('ERROR: %s\n    %s\n' % (
 
483
        ui.ui_factory.note('ERROR: %s\n    %s\n' % (
634
484
            self._test_description(test),
635
485
            err[1],
636
486
            ))
637
487
 
638
488
    def report_failure(self, test, err):
639
 
        self.stream.write('FAIL: %s\n    %s\n' % (
 
489
        ui.ui_factory.note('FAIL: %s\n    %s\n' % (
640
490
            self._test_description(test),
641
491
            err[1],
642
492
            ))
644
494
    def report_known_failure(self, test, err):
645
495
        pass
646
496
 
647
 
    def report_unexpected_success(self, test, reason):
648
 
        self.stream.write('FAIL: %s\n    %s: %s\n' % (
649
 
            self._test_description(test),
650
 
            "Unexpected success. Should have failed",
651
 
            reason,
652
 
            ))
653
 
 
654
497
    def report_skip(self, test, reason):
655
498
        pass
656
499
 
660
503
    def report_unsupported(self, test, feature):
661
504
        """test cannot be run because feature is missing."""
662
505
 
 
506
    def report_cleaning_up(self):
 
507
        self.pb.update('Cleaning up')
 
508
 
663
509
 
664
510
class VerboseTestResult(ExtendedTestResult):
665
511
    """Produce long output, with one line per test run plus times"""
672
518
            result = a_string
673
519
        return result.ljust(final_width)
674
520
 
675
 
    def report_tests_starting(self):
 
521
    def startTestRun(self):
 
522
        super(VerboseTestResult, self).startTestRun()
676
523
        self.stream.write('running %d tests...\n' % self.num_tests)
677
 
        super(VerboseTestResult, self).report_tests_starting()
678
524
 
679
525
    def report_test_start(self, test):
 
526
        self.count += 1
680
527
        name = self._shortened_test_description(test)
681
528
        width = osutils.terminal_width()
682
529
        if width is not None:
694
541
        return '%s%s' % (indent, err[1])
695
542
 
696
543
    def report_error(self, test, err):
697
 
        self.stream.write('ERROR %s\n%s\n'
 
544
        self.stream.writeln('ERROR %s\n%s'
698
545
                % (self._testTimeString(test),
699
546
                   self._error_summary(err)))
700
547
 
701
548
    def report_failure(self, test, err):
702
 
        self.stream.write(' FAIL %s\n%s\n'
 
549
        self.stream.writeln(' FAIL %s\n%s'
703
550
                % (self._testTimeString(test),
704
551
                   self._error_summary(err)))
705
552
 
706
553
    def report_known_failure(self, test, err):
707
 
        self.stream.write('XFAIL %s\n%s\n'
 
554
        self.stream.writeln('XFAIL %s\n%s'
708
555
                % (self._testTimeString(test),
709
556
                   self._error_summary(err)))
710
557
 
711
 
    def report_unexpected_success(self, test, reason):
712
 
        self.stream.write(' FAIL %s\n%s: %s\n'
713
 
                % (self._testTimeString(test),
714
 
                   "Unexpected success. Should have failed",
715
 
                   reason))
716
 
 
717
558
    def report_success(self, test):
718
 
        self.stream.write('   OK %s\n' % self._testTimeString(test))
 
559
        self.stream.writeln('   OK %s' % self._testTimeString(test))
719
560
        for bench_called, stats in getattr(test, '_benchcalls', []):
720
 
            self.stream.write('LSProf output for %s(%s, %s)\n' % bench_called)
 
561
            self.stream.writeln('LSProf output for %s(%s, %s)' % bench_called)
721
562
            stats.pprint(file=self.stream)
722
563
        # flush the stream so that we get smooth output. This verbose mode is
723
564
        # used to show the output in PQM.
724
565
        self.stream.flush()
725
566
 
726
567
    def report_skip(self, test, reason):
727
 
        self.stream.write(' SKIP %s\n%s\n'
 
568
        self.stream.writeln(' SKIP %s\n%s'
728
569
                % (self._testTimeString(test), reason))
729
570
 
730
571
    def report_not_applicable(self, test, reason):
731
 
        self.stream.write('  N/A %s\n    %s\n'
 
572
        self.stream.writeln('  N/A %s\n    %s'
732
573
                % (self._testTimeString(test), reason))
733
574
 
734
575
    def report_unsupported(self, test, feature):
735
576
        """test cannot be run because feature is missing."""
736
 
        self.stream.write("NODEP %s\n    The feature '%s' is not available.\n"
 
577
        self.stream.writeln("NODEP %s\n    The feature '%s' is not available."
737
578
                %(self._testTimeString(test), feature))
738
579
 
739
580
 
766
607
            encode = codec[0]
767
608
        else:
768
609
            encode = codec.encode
769
 
        # GZ 2010-09-08: Really we don't want to be writing arbitrary bytes,
770
 
        #                so should swap to the plain codecs.StreamWriter
771
 
        stream = osutils.UnicodeOrBytesToBytesWriter(encode, stream,
772
 
            "backslashreplace")
 
610
        stream = osutils.UnicodeOrBytesToBytesWriter(encode, stream)
773
611
        stream.encoding = new_encoding
774
 
        self.stream = stream
 
612
        self.stream = unittest._WritelnDecorator(stream)
775
613
        self.descriptions = descriptions
776
614
        self.verbosity = verbosity
777
615
        self._bench_history = bench_history
859
697
    """
860
698
 
861
699
 
 
700
class CommandFailed(Exception):
 
701
    pass
 
702
 
 
703
 
862
704
class StringIOWrapper(object):
863
705
    """A wrapper around cStringIO which just adds an encoding attribute.
864
706
 
901
743
    # XXX: Should probably unify more with CannedInputUIFactory or a
902
744
    # particular configuration of TextUIFactory, or otherwise have a clearer
903
745
    # idea of how they're supposed to be different.
904
 
    # See https://bugs.launchpad.net/bzr/+bug/408213
 
746
    # See https://bugs.edge.launchpad.net/bzr/+bug/408213
905
747
 
906
748
    def __init__(self, stdout=None, stderr=None, stdin=None):
907
749
        if stdin is not None:
925
767
        return NullProgressView()
926
768
 
927
769
 
928
 
def isolated_doctest_setUp(test):
929
 
    override_os_environ(test)
930
 
 
931
 
 
932
 
def isolated_doctest_tearDown(test):
933
 
    restore_os_environ(test)
934
 
 
935
 
 
936
 
def IsolatedDocTestSuite(*args, **kwargs):
937
 
    """Overrides doctest.DocTestSuite to handle isolation.
938
 
 
939
 
    The method is really a factory and users are expected to use it as such.
940
 
    """
941
 
 
942
 
    kwargs['setUp'] = isolated_doctest_setUp
943
 
    kwargs['tearDown'] = isolated_doctest_tearDown
944
 
    return doctest.DocTestSuite(*args, **kwargs)
945
 
 
946
 
 
947
770
class TestCase(testtools.TestCase):
948
771
    """Base class for bzr unit tests.
949
772
 
960
783
    routine, and to build and check bzr trees.
961
784
 
962
785
    In addition to the usual method of overriding tearDown(), this class also
963
 
    allows subclasses to register cleanup functions via addCleanup, which are
 
786
    allows subclasses to register functions into the _cleanups list, which is
964
787
    run in order as the object is torn down.  It's less likely this will be
965
788
    accidentally overlooked.
966
789
    """
967
790
 
968
 
    _log_file = None
 
791
    _active_threads = None
 
792
    _leaking_threads_tests = 0
 
793
    _first_thread_leaker_id = None
 
794
    _log_file_name = None
969
795
    # record lsprof data when performing benchmark calls.
970
796
    _gather_lsprof_in_benchmarks = False
971
797
 
972
798
    def __init__(self, methodName='testMethod'):
973
799
        super(TestCase, self).__init__(methodName)
 
800
        self._cleanups = []
974
801
        self._directory_isolation = True
975
802
        self.exception_handlers.insert(0,
976
803
            (UnavailableFeature, self._do_unsupported_or_skip))
981
808
        super(TestCase, self).setUp()
982
809
        for feature in getattr(self, '_test_needs_features', []):
983
810
            self.requireFeature(feature)
 
811
        self._log_contents = None
 
812
        self.addDetail("log", content.Content(content.ContentType("text",
 
813
            "plain", {"charset": "utf8"}),
 
814
            lambda:[self._get_log(keep_log_file=True)]))
984
815
        self._cleanEnvironment()
985
816
        self._silenceUI()
986
817
        self._startLogFile()
990
821
        self._track_transports()
991
822
        self._track_locks()
992
823
        self._clear_debug_flags()
993
 
        # Isolate global verbosity level, to make sure it's reproducible
994
 
        # between tests.  We should get rid of this altogether: bug 656694. --
995
 
        # mbp 20101008
996
 
        self.overrideAttr(bzrlib.trace, '_verbosity_level', 0)
997
 
        # Isolate config option expansion until its default value for bzrlib is
998
 
        # settled on or a the FIXME associated with _get_expand_default_value
999
 
        # is addressed -- vila 20110219
1000
 
        self.overrideAttr(config, '_expand_default_value', None)
1001
 
        self._log_files = set()
1002
 
        # Each key in the ``_counters`` dict holds a value for a different
1003
 
        # counter. When the test ends, addDetail() should be used to output the
1004
 
        # counter values. This happens in install_counter_hook().
1005
 
        self._counters = {}
1006
 
        if 'config_stats' in selftest_debug_flags:
1007
 
            self._install_config_stats_hooks()
 
824
        TestCase._active_threads = threading.activeCount()
 
825
        self.addCleanup(self._check_leaked_threads)
1008
826
 
1009
827
    def debug(self):
1010
828
        # debug a frame up.
1011
829
        import pdb
1012
830
        pdb.Pdb().set_trace(sys._getframe().f_back)
1013
831
 
1014
 
    def discardDetail(self, name):
1015
 
        """Extend the addDetail, getDetails api so we can remove a detail.
1016
 
 
1017
 
        eg. bzr always adds the 'log' detail at startup, but we don't want to
1018
 
        include it for skipped, xfail, etc tests.
1019
 
 
1020
 
        It is safe to call this for a detail that doesn't exist, in case this
1021
 
        gets called multiple times.
1022
 
        """
1023
 
        # We cheat. details is stored in __details which means we shouldn't
1024
 
        # touch it. but getDetails() returns the dict directly, so we can
1025
 
        # mutate it.
1026
 
        details = self.getDetails()
1027
 
        if name in details:
1028
 
            del details[name]
1029
 
 
1030
 
    def install_counter_hook(self, hooks, name, counter_name=None):
1031
 
        """Install a counting hook.
1032
 
 
1033
 
        Any hook can be counted as long as it doesn't need to return a value.
1034
 
 
1035
 
        :param hooks: Where the hook should be installed.
1036
 
 
1037
 
        :param name: The hook name that will be counted.
1038
 
 
1039
 
        :param counter_name: The counter identifier in ``_counters``, defaults
1040
 
            to ``name``.
1041
 
        """
1042
 
        _counters = self._counters # Avoid closing over self
1043
 
        if counter_name is None:
1044
 
            counter_name = name
1045
 
        if _counters.has_key(counter_name):
1046
 
            raise AssertionError('%s is already used as a counter name'
1047
 
                                  % (counter_name,))
1048
 
        _counters[counter_name] = 0
1049
 
        self.addDetail(counter_name, content.Content(content.UTF8_TEXT,
1050
 
            lambda: ['%d' % (_counters[counter_name],)]))
1051
 
        def increment_counter(*args, **kwargs):
1052
 
            _counters[counter_name] += 1
1053
 
        label = 'count %s calls' % (counter_name,)
1054
 
        hooks.install_named_hook(name, increment_counter, label)
1055
 
        self.addCleanup(hooks.uninstall_named_hook, name, label)
1056
 
 
1057
 
    def _install_config_stats_hooks(self):
1058
 
        """Install config hooks to count hook calls.
1059
 
 
1060
 
        """
1061
 
        for hook_name in ('get', 'set', 'remove', 'load', 'save'):
1062
 
            self.install_counter_hook(config.ConfigHooks, hook_name,
1063
 
                                       'config.%s' % (hook_name,))
1064
 
 
1065
 
        # The OldConfigHooks are private and need special handling to protect
1066
 
        # against recursive tests (tests that run other tests), so we just do
1067
 
        # manually what registering them into _builtin_known_hooks will provide
1068
 
        # us.
1069
 
        self.overrideAttr(config, 'OldConfigHooks', config._OldConfigHooks())
1070
 
        for hook_name in ('get', 'set', 'remove', 'load', 'save'):
1071
 
            self.install_counter_hook(config.OldConfigHooks, hook_name,
1072
 
                                      'old_config.%s' % (hook_name,))
 
832
    def _check_leaked_threads(self):
 
833
        active = threading.activeCount()
 
834
        leaked_threads = active - TestCase._active_threads
 
835
        TestCase._active_threads = active
 
836
        # If some tests make the number of threads *decrease*, we'll consider
 
837
        # that they are just observing old threads dieing, not agressively kill
 
838
        # random threads. So we don't report these tests as leaking. The risk
 
839
        # is that we have false positives that way (the test see 2 threads
 
840
        # going away but leak one) but it seems less likely than the actual
 
841
        # false positives (the test see threads going away and does not leak).
 
842
        if leaked_threads > 0:
 
843
            TestCase._leaking_threads_tests += 1
 
844
            if TestCase._first_thread_leaker_id is None:
 
845
                TestCase._first_thread_leaker_id = self.id()
1073
846
 
1074
847
    def _clear_debug_flags(self):
1075
848
        """Prevent externally set debug flags affecting tests.
1077
850
        Tests that want to use debug flags can just set them in the
1078
851
        debug_flags set during setup/teardown.
1079
852
        """
1080
 
        # Start with a copy of the current debug flags we can safely modify.
1081
 
        self.overrideAttr(debug, 'debug_flags', set(debug.debug_flags))
 
853
        self._preserved_debug_flags = set(debug.debug_flags)
1082
854
        if 'allow_debug' not in selftest_debug_flags:
1083
855
            debug.debug_flags.clear()
1084
856
        if 'disable_lock_checks' not in selftest_debug_flags:
1085
857
            debug.debug_flags.add('strict_locks')
 
858
        self.addCleanup(self._restore_debug_flags)
1086
859
 
1087
860
    def _clear_hooks(self):
1088
861
        # prevent hooks affecting tests
1089
 
        known_hooks = hooks.known_hooks
1090
862
        self._preserved_hooks = {}
1091
 
        for key, (parent, name) in known_hooks.iter_parent_objects():
1092
 
            current_hooks = getattr(parent, name)
 
863
        for key, factory in hooks.known_hooks.items():
 
864
            parent, name = hooks.known_hooks_key_to_parent_and_attribute(key)
 
865
            current_hooks = hooks.known_hooks_key_to_object(key)
1093
866
            self._preserved_hooks[parent] = (name, current_hooks)
1094
 
        self._preserved_lazy_hooks = hooks._lazy_hooks
1095
 
        hooks._lazy_hooks = {}
1096
867
        self.addCleanup(self._restoreHooks)
1097
 
        for key, (parent, name) in known_hooks.iter_parent_objects():
1098
 
            factory = known_hooks.get(key)
 
868
        for key, factory in hooks.known_hooks.items():
 
869
            parent, name = hooks.known_hooks_key_to_parent_and_attribute(key)
1099
870
            setattr(parent, name, factory())
1100
871
        # this hook should always be installed
1101
872
        request._install_hook()
1111
882
    def _silenceUI(self):
1112
883
        """Turn off UI for duration of test"""
1113
884
        # by default the UI is off; tests can turn it on if they want it.
1114
 
        self.overrideAttr(ui, 'ui_factory', ui.SilentUIFactory())
 
885
        saved = ui.ui_factory
 
886
        def _restore():
 
887
            ui.ui_factory = saved
 
888
        ui.ui_factory = ui.SilentUIFactory()
 
889
        self.addCleanup(_restore)
1115
890
 
1116
891
    def _check_locks(self):
1117
892
        """Check that all lock take/release actions have been paired."""
1130
905
        # break some locks on purpose and should be taken into account by
1131
906
        # considering that breaking a lock is just a dirty way of releasing it.
1132
907
        if len(acquired_locks) != (len(released_locks) + len(broken_locks)):
1133
 
            message = (
1134
 
                'Different number of acquired and '
1135
 
                'released or broken locks.\n'
1136
 
                'acquired=%s\n'
1137
 
                'released=%s\n'
1138
 
                'broken=%s\n' %
1139
 
                (acquired_locks, released_locks, broken_locks))
 
908
            message = ('Different number of acquired and '
 
909
                       'released or broken locks. (%s, %s + %s)' %
 
910
                       (acquired_locks, released_locks, broken_locks))
1140
911
            if not self._lock_check_thorough:
1141
912
                # Rather than fail, just warn
1142
913
                print "Broken test %s: %s" % (self, message)
1150
921
            self._lock_check_thorough = False
1151
922
        else:
1152
923
            self._lock_check_thorough = True
1153
 
 
 
924
            
1154
925
        self.addCleanup(self._check_locks)
1155
926
        _mod_lock.Lock.hooks.install_named_hook('lock_acquired',
1156
927
                                                self._lock_acquired, None)
1170
941
 
1171
942
    def permit_dir(self, name):
1172
943
        """Permit a directory to be used by this test. See permit_url."""
1173
 
        name_transport = _mod_transport.get_transport_from_path(name)
 
944
        name_transport = get_transport(name)
1174
945
        self.permit_url(name)
1175
946
        self.permit_url(name_transport.base)
1176
947
 
1199
970
            try:
1200
971
                workingtree.WorkingTree.open(path)
1201
972
            except (errors.NotBranchError, errors.NoWorkingTree):
1202
 
                raise TestSkipped('Needs a working tree of bzr sources')
 
973
                return
1203
974
        finally:
1204
975
            self.enable_directory_isolation()
1205
976
 
1255
1026
        self.addCleanup(transport_server.stop_server)
1256
1027
        # Obtain a real transport because if the server supplies a password, it
1257
1028
        # will be hidden from the base on the client side.
1258
 
        t = _mod_transport.get_transport_from_url(transport_server.get_url())
 
1029
        t = get_transport(transport_server.get_url())
1259
1030
        # Some transport servers effectively chroot the backing transport;
1260
1031
        # others like SFTPServer don't - users of the transport can walk up the
1261
1032
        # transport to read the entire backing transport. This wouldn't matter
1272
1043
        if t.base.endswith('/work/'):
1273
1044
            # we have safety net/test root/work
1274
1045
            t = t.clone('../..')
1275
 
        elif isinstance(transport_server,
1276
 
                        test_server.SmartTCPServer_for_testing):
 
1046
        elif isinstance(transport_server, server.SmartTCPServer_for_testing):
1277
1047
            # The smart server adds a path similar to work, which is traversed
1278
1048
            # up from by the client. But the server is chrooted - the actual
1279
1049
            # backing transport is not escaped from, and VFS requests to the
1317
1087
        except UnicodeError, e:
1318
1088
            # If we can't compare without getting a UnicodeError, then
1319
1089
            # obviously they are different
1320
 
            trace.mutter('UnicodeError: %s', e)
 
1090
            mutter('UnicodeError: %s', e)
1321
1091
        if message:
1322
1092
            message += '\n'
1323
1093
        raise AssertionError("%snot equal:\na = %s\nb = %s\n"
1324
1094
            % (message,
1325
 
               pprint.pformat(a), pprint.pformat(b)))
 
1095
               pformat(a), pformat(b)))
1326
1096
 
1327
1097
    assertEquals = assertEqual
1328
1098
 
1362
1132
                         'st_mtime did not match')
1363
1133
        self.assertEqual(expected.st_ctime, actual.st_ctime,
1364
1134
                         'st_ctime did not match')
1365
 
        if sys.platform == 'win32':
 
1135
        if sys.platform != 'win32':
1366
1136
            # On Win32 both 'dev' and 'ino' cannot be trusted. In python2.4 it
1367
1137
            # is 'dev' that varies, in python 2.5 (6?) it is st_ino that is
1368
 
            # odd. We just force it to always be 0 to avoid any problems.
1369
 
            self.assertEqual(0, expected.st_dev)
1370
 
            self.assertEqual(0, actual.st_dev)
1371
 
            self.assertEqual(0, expected.st_ino)
1372
 
            self.assertEqual(0, actual.st_ino)
1373
 
        else:
 
1138
            # odd. Regardless we shouldn't actually try to assert anything
 
1139
            # about their values
1374
1140
            self.assertEqual(expected.st_dev, actual.st_dev,
1375
1141
                             'st_dev did not match')
1376
1142
            self.assertEqual(expected.st_ino, actual.st_ino,
1385
1151
                length, len(obj_with_len), obj_with_len))
1386
1152
 
1387
1153
    def assertLogsError(self, exception_class, func, *args, **kwargs):
1388
 
        """Assert that `func(*args, **kwargs)` quietly logs a specific error.
 
1154
        """Assert that func(*args, **kwargs) quietly logs a specific exception.
1389
1155
        """
 
1156
        from bzrlib import trace
1390
1157
        captured = []
1391
1158
        orig_log_exception_quietly = trace.log_exception_quietly
1392
1159
        try:
1393
1160
            def capture():
1394
1161
                orig_log_exception_quietly()
1395
 
                captured.append(sys.exc_info()[1])
 
1162
                captured.append(sys.exc_info())
1396
1163
            trace.log_exception_quietly = capture
1397
1164
            func(*args, **kwargs)
1398
1165
        finally:
1399
1166
            trace.log_exception_quietly = orig_log_exception_quietly
1400
1167
        self.assertLength(1, captured)
1401
 
        err = captured[0]
 
1168
        err = captured[0][1]
1402
1169
        self.assertIsInstance(err, exception_class)
1403
1170
        return err
1404
1171
 
1437
1204
            raise AssertionError('pattern "%s" found in "%s"'
1438
1205
                    % (needle_re, haystack))
1439
1206
 
1440
 
    def assertContainsString(self, haystack, needle):
1441
 
        if haystack.find(needle) == -1:
1442
 
            self.fail("string %r not found in '''%s'''" % (needle, haystack))
1443
 
 
1444
 
    def assertNotContainsString(self, haystack, needle):
1445
 
        if haystack.find(needle) != -1:
1446
 
            self.fail("string %r found in '''%s'''" % (needle, haystack))
1447
 
 
1448
1207
    def assertSubset(self, sublist, superlist):
1449
1208
        """Assert that every entry in sublist is present in superlist."""
1450
1209
        missing = set(sublist) - set(superlist)
1539
1298
 
1540
1299
    def assertFileEqual(self, content, path):
1541
1300
        """Fail if path does not contain 'content'."""
1542
 
        self.assertPathExists(path)
 
1301
        self.failUnlessExists(path)
1543
1302
        f = file(path, 'rb')
1544
1303
        try:
1545
1304
            s = f.read()
1547
1306
            f.close()
1548
1307
        self.assertEqualDiff(content, s)
1549
1308
 
1550
 
    def assertDocstring(self, expected_docstring, obj):
1551
 
        """Fail if obj does not have expected_docstring"""
1552
 
        if __doc__ is None:
1553
 
            # With -OO the docstring should be None instead
1554
 
            self.assertIs(obj.__doc__, None)
1555
 
        else:
1556
 
            self.assertEqual(expected_docstring, obj.__doc__)
1557
 
 
1558
 
    @symbol_versioning.deprecated_method(symbol_versioning.deprecated_in((2, 4)))
1559
1309
    def failUnlessExists(self, path):
1560
 
        return self.assertPathExists(path)
1561
 
 
1562
 
    def assertPathExists(self, path):
1563
1310
        """Fail unless path or paths, which may be abs or relative, exist."""
1564
1311
        if not isinstance(path, basestring):
1565
1312
            for p in path:
1566
 
                self.assertPathExists(p)
 
1313
                self.failUnlessExists(p)
1567
1314
        else:
1568
 
            self.assertTrue(osutils.lexists(path),
1569
 
                path + " does not exist")
 
1315
            self.failUnless(osutils.lexists(path),path+" does not exist")
1570
1316
 
1571
 
    @symbol_versioning.deprecated_method(symbol_versioning.deprecated_in((2, 4)))
1572
1317
    def failIfExists(self, path):
1573
 
        return self.assertPathDoesNotExist(path)
1574
 
 
1575
 
    def assertPathDoesNotExist(self, path):
1576
1318
        """Fail if path or paths, which may be abs or relative, exist."""
1577
1319
        if not isinstance(path, basestring):
1578
1320
            for p in path:
1579
 
                self.assertPathDoesNotExist(p)
 
1321
                self.failIfExists(p)
1580
1322
        else:
1581
 
            self.assertFalse(osutils.lexists(path),
1582
 
                path + " exists")
 
1323
            self.failIf(osutils.lexists(path),path+" exists")
1583
1324
 
1584
1325
    def _capture_deprecation_warnings(self, a_callable, *args, **kwargs):
1585
1326
        """A helper for callDeprecated and applyDeprecated.
1611
1352
        not other callers that go direct to the warning module.
1612
1353
 
1613
1354
        To test that a deprecated method raises an error, do something like
1614
 
        this (remember that both assertRaises and applyDeprecated delays *args
1615
 
        and **kwargs passing)::
 
1355
        this::
1616
1356
 
1617
1357
            self.assertRaises(errors.ReservedId,
1618
1358
                self.applyDeprecated,
1700
1440
 
1701
1441
        The file is removed as the test is torn down.
1702
1442
        """
1703
 
        pseudo_log_file = StringIO()
1704
 
        def _get_log_contents_for_weird_testtools_api():
1705
 
            return [pseudo_log_file.getvalue().decode(
1706
 
                "utf-8", "replace").encode("utf-8")]
1707
 
        self.addDetail("log", content.Content(content.ContentType("text",
1708
 
            "plain", {"charset": "utf8"}),
1709
 
            _get_log_contents_for_weird_testtools_api))
1710
 
        self._log_file = pseudo_log_file
1711
 
        self._log_memento = trace.push_log_file(self._log_file)
 
1443
        fileno, name = tempfile.mkstemp(suffix='.log', prefix='testbzr')
 
1444
        self._log_file = os.fdopen(fileno, 'w+')
 
1445
        self._log_memento = bzrlib.trace.push_log_file(self._log_file)
 
1446
        self._log_file_name = name
1712
1447
        self.addCleanup(self._finishLogFile)
1713
1448
 
1714
1449
    def _finishLogFile(self):
1715
1450
        """Finished with the log file.
1716
1451
 
1717
 
        Close the file and delete it.
 
1452
        Close the file and delete it, unless setKeepLogfile was called.
1718
1453
        """
1719
 
        if trace._trace_file:
 
1454
        if bzrlib.trace._trace_file:
1720
1455
            # flush the log file, to get all content
1721
 
            trace._trace_file.flush()
1722
 
        trace.pop_log_file(self._log_memento)
 
1456
            bzrlib.trace._trace_file.flush()
 
1457
        bzrlib.trace.pop_log_file(self._log_memento)
 
1458
        # Cache the log result and delete the file on disk
 
1459
        self._get_log(False)
1723
1460
 
1724
1461
    def thisFailsStrictLockCheck(self):
1725
1462
        """It is known that this test would fail with -Dstrict_locks.
1734
1471
        """
1735
1472
        debug.debug_flags.discard('strict_locks')
1736
1473
 
1737
 
    def overrideAttr(self, obj, attr_name, new=_unitialized_attr):
1738
 
        """Overrides an object attribute restoring it after the test.
1739
 
 
1740
 
        :note: This should be used with discretion; you should think about
1741
 
        whether it's better to make the code testable without monkey-patching.
1742
 
 
1743
 
        :param obj: The object that will be mutated.
1744
 
 
1745
 
        :param attr_name: The attribute name we want to preserve/override in
1746
 
            the object.
1747
 
 
1748
 
        :param new: The optional value we want to set the attribute to.
1749
 
 
1750
 
        :returns: The actual attr value.
1751
 
        """
1752
 
        value = getattr(obj, attr_name)
1753
 
        # The actual value is captured by the call below
1754
 
        self.addCleanup(setattr, obj, attr_name, value)
1755
 
        if new is not _unitialized_attr:
1756
 
            setattr(obj, attr_name, new)
1757
 
        return value
1758
 
 
1759
 
    def overrideEnv(self, name, new):
1760
 
        """Set an environment variable, and reset it after the test.
1761
 
 
1762
 
        :param name: The environment variable name.
1763
 
 
1764
 
        :param new: The value to set the variable to. If None, the 
1765
 
            variable is deleted from the environment.
1766
 
 
1767
 
        :returns: The actual variable value.
1768
 
        """
1769
 
        value = osutils.set_or_unset_env(name, new)
1770
 
        self.addCleanup(osutils.set_or_unset_env, name, value)
1771
 
        return value
1772
 
 
1773
 
    def recordCalls(self, obj, attr_name):
1774
 
        """Monkeypatch in a wrapper that will record calls.
1775
 
 
1776
 
        The monkeypatch is automatically removed when the test concludes.
1777
 
 
1778
 
        :param obj: The namespace holding the reference to be replaced;
1779
 
            typically a module, class, or object.
1780
 
        :param attr_name: A string for the name of the attribute to 
1781
 
            patch.
1782
 
        :returns: A list that will be extended with one item every time the
1783
 
            function is called, with a tuple of (args, kwargs).
1784
 
        """
1785
 
        calls = []
1786
 
 
1787
 
        def decorator(*args, **kwargs):
1788
 
            calls.append((args, kwargs))
1789
 
            return orig(*args, **kwargs)
1790
 
        orig = self.overrideAttr(obj, attr_name, decorator)
1791
 
        return calls
 
1474
    def addCleanup(self, callable, *args, **kwargs):
 
1475
        """Arrange to run a callable when this case is torn down.
 
1476
 
 
1477
        Callables are run in the reverse of the order they are registered,
 
1478
        ie last-in first-out.
 
1479
        """
 
1480
        self._cleanups.append((callable, args, kwargs))
1792
1481
 
1793
1482
    def _cleanEnvironment(self):
1794
 
        for name, value in isolated_environ.iteritems():
1795
 
            self.overrideEnv(name, value)
 
1483
        new_env = {
 
1484
            'BZR_HOME': None, # Don't inherit BZR_HOME to all the tests.
 
1485
            'HOME': os.getcwd(),
 
1486
            # bzr now uses the Win32 API and doesn't rely on APPDATA, but the
 
1487
            # tests do check our impls match APPDATA
 
1488
            'BZR_EDITOR': None, # test_msgeditor manipulates this variable
 
1489
            'VISUAL': None,
 
1490
            'EDITOR': None,
 
1491
            'BZR_EMAIL': None,
 
1492
            'BZREMAIL': None, # may still be present in the environment
 
1493
            'EMAIL': None,
 
1494
            'BZR_PROGRESS_BAR': None,
 
1495
            'BZR_LOG': None,
 
1496
            'BZR_PLUGIN_PATH': None,
 
1497
            'BZR_CONCURRENCY': None,
 
1498
            # Make sure that any text ui tests are consistent regardless of
 
1499
            # the environment the test case is run in; you may want tests that
 
1500
            # test other combinations.  'dumb' is a reasonable guess for tests
 
1501
            # going to a pipe or a StringIO.
 
1502
            'TERM': 'dumb',
 
1503
            'LINES': '25',
 
1504
            'COLUMNS': '80',
 
1505
            'BZR_COLUMNS': '80',
 
1506
            # SSH Agent
 
1507
            'SSH_AUTH_SOCK': None,
 
1508
            # Proxies
 
1509
            'http_proxy': None,
 
1510
            'HTTP_PROXY': None,
 
1511
            'https_proxy': None,
 
1512
            'HTTPS_PROXY': None,
 
1513
            'no_proxy': None,
 
1514
            'NO_PROXY': None,
 
1515
            'all_proxy': None,
 
1516
            'ALL_PROXY': None,
 
1517
            # Nobody cares about ftp_proxy, FTP_PROXY AFAIK. So far at
 
1518
            # least. If you do (care), please update this comment
 
1519
            # -- vila 20080401
 
1520
            'ftp_proxy': None,
 
1521
            'FTP_PROXY': None,
 
1522
            'BZR_REMOTE_PATH': None,
 
1523
        }
 
1524
        self.__old_env = {}
 
1525
        self.addCleanup(self._restoreEnvironment)
 
1526
        for name, value in new_env.iteritems():
 
1527
            self._captureVar(name, value)
 
1528
 
 
1529
    def _captureVar(self, name, newvalue):
 
1530
        """Set an environment variable, and reset it when finished."""
 
1531
        self.__old_env[name] = osutils.set_or_unset_env(name, newvalue)
 
1532
 
 
1533
    def _restore_debug_flags(self):
 
1534
        debug.debug_flags.clear()
 
1535
        debug.debug_flags.update(self._preserved_debug_flags)
 
1536
 
 
1537
    def _restoreEnvironment(self):
 
1538
        for name, value in self.__old_env.iteritems():
 
1539
            osutils.set_or_unset_env(name, value)
1796
1540
 
1797
1541
    def _restoreHooks(self):
1798
1542
        for klass, (name, hooks) in self._preserved_hooks.items():
1799
1543
            setattr(klass, name, hooks)
1800
 
        self._preserved_hooks.clear()
1801
 
        bzrlib.hooks._lazy_hooks = self._preserved_lazy_hooks
1802
 
        self._preserved_lazy_hooks.clear()
1803
1544
 
1804
1545
    def knownFailure(self, reason):
1805
 
        """Declare that this test fails for a known reason
1806
 
 
1807
 
        Tests that are known to fail should generally be using expectedFailure
1808
 
        with an appropriate reverse assertion if a change could cause the test
1809
 
        to start passing. Conversely if the test has no immediate prospect of
1810
 
        succeeding then using skip is more suitable.
1811
 
 
1812
 
        When this method is called while an exception is being handled, that
1813
 
        traceback will be used, otherwise a new exception will be thrown to
1814
 
        provide one but won't be reported.
1815
 
        """
1816
 
        self._add_reason(reason)
1817
 
        try:
1818
 
            exc_info = sys.exc_info()
1819
 
            if exc_info != (None, None, None):
1820
 
                self._report_traceback(exc_info)
1821
 
            else:
1822
 
                try:
1823
 
                    raise self.failureException(reason)
1824
 
                except self.failureException:
1825
 
                    exc_info = sys.exc_info()
1826
 
            # GZ 02-08-2011: Maybe cleanup this err.exc_info attribute too?
1827
 
            raise testtools.testcase._ExpectedFailure(exc_info)
1828
 
        finally:
1829
 
            del exc_info
1830
 
 
1831
 
    def _suppress_log(self):
1832
 
        """Remove the log info from details."""
1833
 
        self.discardDetail('log')
 
1546
        """This test has failed for some known reason."""
 
1547
        raise KnownFailure(reason)
1834
1548
 
1835
1549
    def _do_skip(self, result, reason):
1836
 
        self._suppress_log()
1837
1550
        addSkip = getattr(result, 'addSkip', None)
1838
1551
        if not callable(addSkip):
1839
1552
            result.addSuccess(result)
1842
1555
 
1843
1556
    @staticmethod
1844
1557
    def _do_known_failure(self, result, e):
1845
 
        self._suppress_log()
1846
1558
        err = sys.exc_info()
1847
1559
        addExpectedFailure = getattr(result, 'addExpectedFailure', None)
1848
1560
        if addExpectedFailure is not None:
1856
1568
            reason = 'No reason given'
1857
1569
        else:
1858
1570
            reason = e.args[0]
1859
 
        self._suppress_log ()
1860
1571
        addNotApplicable = getattr(result, 'addNotApplicable', None)
1861
1572
        if addNotApplicable is not None:
1862
1573
            result.addNotApplicable(self, reason)
1864
1575
            self._do_skip(result, reason)
1865
1576
 
1866
1577
    @staticmethod
1867
 
    def _report_skip(self, result, err):
1868
 
        """Override the default _report_skip.
1869
 
 
1870
 
        We want to strip the 'log' detail. If we waint until _do_skip, it has
1871
 
        already been formatted into the 'reason' string, and we can't pull it
1872
 
        out again.
1873
 
        """
1874
 
        self._suppress_log()
1875
 
        super(TestCase, self)._report_skip(self, result, err)
1876
 
 
1877
 
    @staticmethod
1878
 
    def _report_expected_failure(self, result, err):
1879
 
        """Strip the log.
1880
 
 
1881
 
        See _report_skip for motivation.
1882
 
        """
1883
 
        self._suppress_log()
1884
 
        super(TestCase, self)._report_expected_failure(self, result, err)
1885
 
 
1886
 
    @staticmethod
1887
1578
    def _do_unsupported_or_skip(self, result, e):
1888
1579
        reason = e.args[0]
1889
 
        self._suppress_log()
1890
1580
        addNotSupported = getattr(result, 'addNotSupported', None)
1891
1581
        if addNotSupported is not None:
1892
1582
            result.addNotSupported(self, reason)
1918
1608
            self._benchtime += time.time() - start
1919
1609
 
1920
1610
    def log(self, *args):
1921
 
        trace.mutter(*args)
 
1611
        mutter(*args)
 
1612
 
 
1613
    def _get_log(self, keep_log_file=False):
 
1614
        """Internal helper to get the log from bzrlib.trace for this test.
 
1615
 
 
1616
        Please use self.getDetails, or self.get_log to access this in test case
 
1617
        code.
 
1618
 
 
1619
        :param keep_log_file: When True, if the log is still a file on disk
 
1620
            leave it as a file on disk. When False, if the log is still a file
 
1621
            on disk, the log file is deleted and the log preserved as
 
1622
            self._log_contents.
 
1623
        :return: A string containing the log.
 
1624
        """
 
1625
        if self._log_contents is not None:
 
1626
            try:
 
1627
                self._log_contents.decode('utf8')
 
1628
            except UnicodeDecodeError:
 
1629
                unicodestr = self._log_contents.decode('utf8', 'replace')
 
1630
                self._log_contents = unicodestr.encode('utf8')
 
1631
            return self._log_contents
 
1632
        import bzrlib.trace
 
1633
        if bzrlib.trace._trace_file:
 
1634
            # flush the log file, to get all content
 
1635
            bzrlib.trace._trace_file.flush()
 
1636
        if self._log_file_name is not None:
 
1637
            logfile = open(self._log_file_name)
 
1638
            try:
 
1639
                log_contents = logfile.read()
 
1640
            finally:
 
1641
                logfile.close()
 
1642
            try:
 
1643
                log_contents.decode('utf8')
 
1644
            except UnicodeDecodeError:
 
1645
                unicodestr = log_contents.decode('utf8', 'replace')
 
1646
                log_contents = unicodestr.encode('utf8')
 
1647
            if not keep_log_file:
 
1648
                self._log_file.close()
 
1649
                self._log_file = None
 
1650
                # Permit multiple calls to get_log until we clean it up in
 
1651
                # finishLogFile
 
1652
                self._log_contents = log_contents
 
1653
                try:
 
1654
                    os.remove(self._log_file_name)
 
1655
                except OSError, e:
 
1656
                    if sys.platform == 'win32' and e.errno == errno.EACCES:
 
1657
                        sys.stderr.write(('Unable to delete log file '
 
1658
                                             ' %r\n' % self._log_file_name))
 
1659
                    else:
 
1660
                        raise
 
1661
                self._log_file_name = None
 
1662
            return log_contents
 
1663
        else:
 
1664
            return "No log file content and no log file name."
1922
1665
 
1923
1666
    def get_log(self):
1924
1667
        """Get a unicode string containing the log from bzrlib.trace.
1974
1717
 
1975
1718
        try:
1976
1719
            try:
1977
 
                result = self.apply_redirected(
1978
 
                    ui.ui_factory.stdin,
 
1720
                result = self.apply_redirected(ui.ui_factory.stdin,
1979
1721
                    stdout, stderr,
1980
 
                    _mod_commands.run_bzr_catch_user_errors,
 
1722
                    bzrlib.commands.run_bzr_catch_user_errors,
1981
1723
                    args)
1982
1724
            except KeyboardInterrupt:
1983
1725
                # Reraise KeyboardInterrupt with contents of redirected stdout
2125
1867
    def start_bzr_subprocess(self, process_args, env_changes=None,
2126
1868
                             skip_if_plan_to_signal=False,
2127
1869
                             working_dir=None,
2128
 
                             allow_plugins=False, stderr=subprocess.PIPE):
 
1870
                             allow_plugins=False):
2129
1871
        """Start bzr in a subprocess for testing.
2130
1872
 
2131
1873
        This starts a new Python interpreter and runs bzr in there.
2140
1882
            variables. A value of None will unset the env variable.
2141
1883
            The values must be strings. The change will only occur in the
2142
1884
            child, so you don't need to fix the environment after running.
2143
 
        :param skip_if_plan_to_signal: raise TestSkipped when true and system
2144
 
            doesn't support signalling subprocesses.
 
1885
        :param skip_if_plan_to_signal: raise TestSkipped when true and os.kill
 
1886
            is not available.
2145
1887
        :param allow_plugins: If False (default) pass --no-plugins to bzr.
2146
 
        :param stderr: file to use for the subprocess's stderr.  Valid values
2147
 
            are those valid for the stderr argument of `subprocess.Popen`.
2148
 
            Default value is ``subprocess.PIPE``.
2149
1888
 
2150
1889
        :returns: Popen object for the started process.
2151
1890
        """
2152
1891
        if skip_if_plan_to_signal:
2153
 
            if os.name != "posix":
2154
 
                raise TestSkipped("Sending signals not supported")
 
1892
            if not getattr(os, 'kill', None):
 
1893
                raise TestSkipped("os.kill not available.")
2155
1894
 
2156
1895
        if env_changes is None:
2157
1896
            env_changes = {}
2177
1916
            # so we will avoid using it on all platforms, just to
2178
1917
            # make sure the code path is used, and we don't break on win32
2179
1918
            cleanup_environment()
2180
 
            # Include the subprocess's log file in the test details, in case
2181
 
            # the test fails due to an error in the subprocess.
2182
 
            self._add_subprocess_log(trace._get_bzr_log_filename())
2183
1919
            command = [sys.executable]
2184
1920
            # frozen executables don't need the path to bzr
2185
1921
            if getattr(sys, "frozen", None) is None:
2187
1923
            if not allow_plugins:
2188
1924
                command.append('--no-plugins')
2189
1925
            command.extend(process_args)
2190
 
            process = self._popen(command, stdin=subprocess.PIPE,
2191
 
                                  stdout=subprocess.PIPE,
2192
 
                                  stderr=stderr)
 
1926
            process = self._popen(command, stdin=PIPE, stdout=PIPE, stderr=PIPE)
2193
1927
        finally:
2194
1928
            restore_environment()
2195
1929
            if cwd is not None:
2197
1931
 
2198
1932
        return process
2199
1933
 
2200
 
    def _add_subprocess_log(self, log_file_path):
2201
 
        if len(self._log_files) == 0:
2202
 
            # Register an addCleanup func.  We do this on the first call to
2203
 
            # _add_subprocess_log rather than in TestCase.setUp so that this
2204
 
            # addCleanup is registered after any cleanups for tempdirs that
2205
 
            # subclasses might create, which will probably remove the log file
2206
 
            # we want to read.
2207
 
            self.addCleanup(self._subprocess_log_cleanup)
2208
 
        # self._log_files is a set, so if a log file is reused we won't grab it
2209
 
        # twice.
2210
 
        self._log_files.add(log_file_path)
2211
 
 
2212
 
    def _subprocess_log_cleanup(self):
2213
 
        for count, log_file_path in enumerate(self._log_files):
2214
 
            # We use buffer_now=True to avoid holding the file open beyond
2215
 
            # the life of this function, which might interfere with e.g.
2216
 
            # cleaning tempdirs on Windows.
2217
 
            # XXX: Testtools 0.9.5 doesn't have the content_from_file helper
2218
 
            #detail_content = content.content_from_file(
2219
 
            #    log_file_path, buffer_now=True)
2220
 
            with open(log_file_path, 'rb') as log_file:
2221
 
                log_file_bytes = log_file.read()
2222
 
            detail_content = content.Content(content.ContentType("text",
2223
 
                "plain", {"charset": "utf8"}), lambda: [log_file_bytes])
2224
 
            self.addDetail("start_bzr_subprocess-log-%d" % (count,),
2225
 
                detail_content)
2226
 
 
2227
1934
    def _popen(self, *args, **kwargs):
2228
1935
        """Place a call to Popen.
2229
1936
 
2230
1937
        Allows tests to override this method to intercept the calls made to
2231
1938
        Popen for introspection.
2232
1939
        """
2233
 
        return subprocess.Popen(*args, **kwargs)
 
1940
        return Popen(*args, **kwargs)
2234
1941
 
2235
1942
    def get_source_path(self):
2236
1943
        """Return the path of the directory containing bzrlib."""
2238
1945
 
2239
1946
    def get_bzr_path(self):
2240
1947
        """Return the path of the 'bzr' executable for this test suite."""
2241
 
        bzr_path = os.path.join(self.get_source_path(), "bzr")
 
1948
        bzr_path = self.get_source_path()+'/bzr'
2242
1949
        if not os.path.isfile(bzr_path):
2243
1950
            # We are probably installed. Assume sys.argv is the right file
2244
1951
            bzr_path = sys.argv[0]
2266
1973
        if retcode is not None and retcode != process.returncode:
2267
1974
            if process_args is None:
2268
1975
                process_args = "(unknown args)"
2269
 
            trace.mutter('Output of bzr %s:\n%s', process_args, out)
2270
 
            trace.mutter('Error for bzr %s:\n%s', process_args, err)
 
1976
            mutter('Output of bzr %s:\n%s', process_args, out)
 
1977
            mutter('Error for bzr %s:\n%s', process_args, err)
2271
1978
            self.fail('Command bzr %s failed with retcode %s != %s'
2272
1979
                      % (process_args, retcode, process.returncode))
2273
1980
        return [out, err]
2274
1981
 
2275
 
    def check_tree_shape(self, tree, shape):
2276
 
        """Compare a tree to a list of expected names.
 
1982
    def check_inventory_shape(self, inv, shape):
 
1983
        """Compare an inventory to a list of expected names.
2277
1984
 
2278
1985
        Fail if they are not precisely equal.
2279
1986
        """
2280
1987
        extras = []
2281
1988
        shape = list(shape)             # copy
2282
 
        for path, ie in tree.iter_entries_by_dir():
 
1989
        for path, ie in inv.entries():
2283
1990
            name = path.replace('\\', '/')
2284
1991
            if ie.kind == 'directory':
2285
1992
                name = name + '/'
2286
 
            if name == "/":
2287
 
                pass # ignore root entry
2288
 
            elif name in shape:
 
1993
            if name in shape:
2289
1994
                shape.remove(name)
2290
1995
            else:
2291
1996
                extras.append(name)
2332
2037
 
2333
2038
        Tests that expect to provoke LockContention errors should call this.
2334
2039
        """
2335
 
        self.overrideAttr(lockdir, '_DEFAULT_TIMEOUT_SECONDS', 0)
 
2040
        orig_timeout = bzrlib.lockdir._DEFAULT_TIMEOUT_SECONDS
 
2041
        def resetTimeout():
 
2042
            bzrlib.lockdir._DEFAULT_TIMEOUT_SECONDS = orig_timeout
 
2043
        self.addCleanup(resetTimeout)
 
2044
        bzrlib.lockdir._DEFAULT_TIMEOUT_SECONDS = 0
2336
2045
 
2337
2046
    def make_utf8_encoded_stringio(self, encoding_type=None):
2338
2047
        """Return a StringIOWrapper instance, that will encode Unicode
2352
2061
        request_handlers = request.request_handlers
2353
2062
        orig_method = request_handlers.get(verb)
2354
2063
        request_handlers.remove(verb)
2355
 
        self.addCleanup(request_handlers.register, verb, orig_method)
 
2064
        def restoreVerb():
 
2065
            request_handlers.register(verb, orig_method)
 
2066
        self.addCleanup(restoreVerb)
2356
2067
 
2357
2068
 
2358
2069
class CapturedCall(object):
2381
2092
class TestCaseWithMemoryTransport(TestCase):
2382
2093
    """Common test class for tests that do not need disk resources.
2383
2094
 
2384
 
    Tests that need disk resources should derive from TestCaseInTempDir
2385
 
    orTestCaseWithTransport.
 
2095
    Tests that need disk resources should derive from TestCaseWithTransport.
2386
2096
 
2387
2097
    TestCaseWithMemoryTransport sets the TEST_ROOT variable for all bzr tests.
2388
2098
 
2389
 
    For TestCaseWithMemoryTransport the ``test_home_dir`` is set to the name of
 
2099
    For TestCaseWithMemoryTransport the test_home_dir is set to the name of
2390
2100
    a directory which does not exist. This serves to help ensure test isolation
2391
 
    is preserved. ``test_dir`` is set to the TEST_ROOT, as is cwd, because they
2392
 
    must exist. However, TestCaseWithMemoryTransport does not offer local file
2393
 
    defaults for the transport in tests, nor does it obey the command line
 
2101
    is preserved. test_dir is set to the TEST_ROOT, as is cwd, because they
 
2102
    must exist. However, TestCaseWithMemoryTransport does not offer local
 
2103
    file defaults for the transport in tests, nor does it obey the command line
2394
2104
    override, so tests that accidentally write to the common directory should
2395
2105
    be rare.
2396
2106
 
2397
 
    :cvar TEST_ROOT: Directory containing all temporary directories, plus a
2398
 
        ``.bzr`` directory that stops us ascending higher into the filesystem.
 
2107
    :cvar TEST_ROOT: Directory containing all temporary directories, plus
 
2108
    a .bzr directory that stops us ascending higher into the filesystem.
2399
2109
    """
2400
2110
 
2401
2111
    TEST_ROOT = None
2419
2129
 
2420
2130
        :param relpath: a path relative to the base url.
2421
2131
        """
2422
 
        t = _mod_transport.get_transport_from_url(self.get_url(relpath))
 
2132
        t = get_transport(self.get_url(relpath))
2423
2133
        self.assertFalse(t.is_readonly())
2424
2134
        return t
2425
2135
 
2431
2141
 
2432
2142
        :param relpath: a path relative to the base url.
2433
2143
        """
2434
 
        t = _mod_transport.get_transport(self.get_readonly_url(relpath))
 
2144
        t = get_transport(self.get_readonly_url(relpath))
2435
2145
        self.assertTrue(t.is_readonly())
2436
2146
        return t
2437
2147
 
2450
2160
        if self.__readonly_server is None:
2451
2161
            if self.transport_readonly_server is None:
2452
2162
                # readonly decorator requested
2453
 
                self.__readonly_server = test_server.ReadonlyServer()
 
2163
                self.__readonly_server = ReadonlyServer()
2454
2164
            else:
2455
2165
                # explicit readonly transport.
2456
2166
                self.__readonly_server = self.create_transport_readonly_server()
2479
2189
        is no means to override it.
2480
2190
        """
2481
2191
        if self.__vfs_server is None:
2482
 
            self.__vfs_server = memory.MemoryServer()
 
2192
            self.__vfs_server = MemoryServer()
2483
2193
            self.start_server(self.__vfs_server)
2484
2194
        return self.__vfs_server
2485
2195
 
2558
2268
        real branch.
2559
2269
        """
2560
2270
        root = TestCaseWithMemoryTransport.TEST_ROOT
2561
 
        wt = bzrdir.BzrDir.create_standalone_workingtree(root)
2562
 
        # Hack for speed: remember the raw bytes of the dirstate file so that
2563
 
        # we don't need to re-open the wt to check it hasn't changed.
2564
 
        TestCaseWithMemoryTransport._SAFETY_NET_PRISTINE_DIRSTATE = (
2565
 
            wt.control_transport.get_bytes('dirstate'))
 
2271
        bzrdir.BzrDir.create_standalone_workingtree(root)
2566
2272
 
2567
2273
    def _check_safety_net(self):
2568
2274
        """Check that the safety .bzr directory have not been touched.
2571
2277
        propagating. This method ensures than a test did not leaked.
2572
2278
        """
2573
2279
        root = TestCaseWithMemoryTransport.TEST_ROOT
2574
 
        t = _mod_transport.get_transport(root)
2575
 
        self.permit_url(t.base)
2576
 
        if (t.get_bytes('.bzr/checkout/dirstate') != 
2577
 
                TestCaseWithMemoryTransport._SAFETY_NET_PRISTINE_DIRSTATE):
 
2280
        self.permit_url(get_transport(root).base)
 
2281
        wt = workingtree.WorkingTree.open(root)
 
2282
        last_rev = wt.last_revision()
 
2283
        if last_rev != 'null:':
2578
2284
            # The current test have modified the /bzr directory, we need to
2579
2285
            # recreate a new one or all the followng tests will fail.
2580
2286
            # If you need to inspect its content uncomment the following line
2622
2328
            # might be a relative or absolute path
2623
2329
            maybe_a_url = self.get_url(relpath)
2624
2330
            segments = maybe_a_url.rsplit('/', 1)
2625
 
            t = _mod_transport.get_transport(maybe_a_url)
 
2331
            t = get_transport(maybe_a_url)
2626
2332
            if len(segments) > 1 and segments[-1] not in ('', '.'):
2627
2333
                t.ensure_base()
2628
2334
            if format is None:
2645
2351
        made_control = self.make_bzrdir(relpath, format=format)
2646
2352
        return made_control.create_repository(shared=shared)
2647
2353
 
2648
 
    def make_smart_server(self, path, backing_server=None):
2649
 
        if backing_server is None:
2650
 
            backing_server = self.get_server()
2651
 
        smart_server = test_server.SmartTCPServer_for_testing()
2652
 
        self.start_server(smart_server, backing_server)
2653
 
        remote_transport = _mod_transport.get_transport_from_url(smart_server.get_url()
2654
 
                                                   ).clone(path)
 
2354
    def make_smart_server(self, path):
 
2355
        smart_server = server.SmartTCPServer_for_testing()
 
2356
        self.start_server(smart_server, self.get_server())
 
2357
        remote_transport = get_transport(smart_server.get_url()).clone(path)
2655
2358
        return remote_transport
2656
2359
 
2657
2360
    def make_branch_and_memory_tree(self, relpath, format=None):
2667
2370
        test_home_dir = self.test_home_dir
2668
2371
        if isinstance(test_home_dir, unicode):
2669
2372
            test_home_dir = test_home_dir.encode(sys.getfilesystemencoding())
2670
 
        self.overrideEnv('HOME', test_home_dir)
2671
 
        self.overrideEnv('BZR_HOME', test_home_dir)
 
2373
        os.environ['HOME'] = test_home_dir
 
2374
        os.environ['BZR_HOME'] = test_home_dir
2672
2375
 
2673
2376
    def setUp(self):
2674
2377
        super(TestCaseWithMemoryTransport, self).setUp()
2675
 
        # Ensure that ConnectedTransport doesn't leak sockets
2676
 
        def get_transport_from_url_with_cleanup(*args, **kwargs):
2677
 
            t = orig_get_transport_from_url(*args, **kwargs)
2678
 
            if isinstance(t, _mod_transport.ConnectedTransport):
2679
 
                self.addCleanup(t.disconnect)
2680
 
            return t
2681
 
 
2682
 
        orig_get_transport_from_url = self.overrideAttr(
2683
 
            _mod_transport, 'get_transport_from_url',
2684
 
            get_transport_from_url_with_cleanup)
2685
2378
        self._make_test_root()
2686
 
        self.addCleanup(os.chdir, os.getcwdu())
 
2379
        _currentdir = os.getcwdu()
 
2380
        def _leaveDirectory():
 
2381
            os.chdir(_currentdir)
 
2382
        self.addCleanup(_leaveDirectory)
2687
2383
        self.makeAndChdirToTestDir()
2688
2384
        self.overrideEnvironmentForTesting()
2689
2385
        self.__readonly_server = None
2692
2388
 
2693
2389
    def setup_smart_server_with_call_log(self):
2694
2390
        """Sets up a smart server as the transport server with a call log."""
2695
 
        self.transport_server = test_server.SmartTCPServer_for_testing
 
2391
        self.transport_server = server.SmartTCPServer_for_testing
2696
2392
        self.hpss_calls = []
2697
2393
        import traceback
2698
2394
        # Skip the current stack down to the caller of
2730
2426
 
2731
2427
    OVERRIDE_PYTHON = 'python'
2732
2428
 
2733
 
    def setUp(self):
2734
 
        super(TestCaseInTempDir, self).setUp()
2735
 
        # Remove the protection set in isolated_environ, we have a proper
2736
 
        # access to disk resources now.
2737
 
        self.overrideEnv('BZR_LOG', None)
2738
 
 
2739
2429
    def check_file_contents(self, filename, expect):
2740
2430
        self.log("check contents of file %s" % filename)
2741
 
        f = file(filename)
2742
 
        try:
2743
 
            contents = f.read()
2744
 
        finally:
2745
 
            f.close()
 
2431
        contents = file(filename, 'r').read()
2746
2432
        if contents != expect:
2747
2433
            self.log("expected: %r" % expect)
2748
2434
            self.log("actually: %r" % contents)
2822
2508
                "a list or a tuple. Got %r instead" % (shape,))
2823
2509
        # It's OK to just create them using forward slashes on windows.
2824
2510
        if transport is None or transport.is_readonly():
2825
 
            transport = _mod_transport.get_transport(".")
 
2511
            transport = get_transport(".")
2826
2512
        for name in shape:
2827
2513
            self.assertIsInstance(name, basestring)
2828
2514
            if name[-1] == '/':
2838
2524
                content = "contents of %s%s" % (name.encode('utf-8'), end)
2839
2525
                transport.put_bytes_non_atomic(urlutils.escape(name), content)
2840
2526
 
2841
 
    build_tree_contents = staticmethod(treeshape.build_tree_contents)
 
2527
    def build_tree_contents(self, shape):
 
2528
        build_tree_contents(shape)
2842
2529
 
2843
2530
    def assertInWorkingTree(self, path, root_path='.', tree=None):
2844
2531
        """Assert whether path or paths are in the WorkingTree"""
2920
2607
            # We can only make working trees locally at the moment.  If the
2921
2608
            # transport can't support them, then we keep the non-disk-backed
2922
2609
            # branch and create a local checkout.
2923
 
            if self.vfs_transport_factory is test_server.LocalURLServer:
 
2610
            if self.vfs_transport_factory is LocalURLServer:
2924
2611
                # the branch is colocated on disk, we cannot create a checkout.
2925
2612
                # hopefully callers will expect this.
2926
2613
                local_controldir= bzrdir.BzrDir.open(self.get_vfs_only_url(relpath))
2985
2672
    """
2986
2673
 
2987
2674
    def setUp(self):
2988
 
        from bzrlib.tests import http_server
2989
2675
        super(ChrootedTestCase, self).setUp()
2990
 
        if not self.vfs_transport_factory == memory.MemoryServer:
2991
 
            self.transport_readonly_server = http_server.HttpServer
 
2676
        if not self.vfs_transport_factory == MemoryServer:
 
2677
            self.transport_readonly_server = HttpServer
2992
2678
 
2993
2679
 
2994
2680
def condition_id_re(pattern):
2997
2683
    :param pattern: A regular expression string.
2998
2684
    :return: A callable that returns True if the re matches.
2999
2685
    """
3000
 
    filter_re = re.compile(pattern, 0)
 
2686
    filter_re = osutils.re_compile_checked(pattern, 0,
 
2687
        'test filter')
3001
2688
    def condition(test):
3002
2689
        test_id = test.id()
3003
2690
        return filter_re.search(test_id)
3255
2942
 
3256
2943
 
3257
2944
def fork_decorator(suite):
3258
 
    if getattr(os, "fork", None) is None:
3259
 
        raise errors.BzrCommandError("platform does not support fork,"
3260
 
            " try --parallel=subprocess instead.")
3261
2945
    concurrency = osutils.local_concurrency()
3262
2946
    if concurrency == 1:
3263
2947
        return suite
3318
3002
    return suite
3319
3003
 
3320
3004
 
3321
 
class TestDecorator(TestUtil.TestSuite):
 
3005
class TestDecorator(TestSuite):
3322
3006
    """A decorator for TestCase/TestSuite objects.
3323
3007
    
3324
3008
    Usually, subclasses should override __iter__(used when flattening test
3327
3011
    """
3328
3012
 
3329
3013
    def __init__(self, suite):
3330
 
        TestUtil.TestSuite.__init__(self)
 
3014
        TestSuite.__init__(self)
3331
3015
        self.addTest(suite)
3332
3016
 
3333
3017
    def countTestCases(self):
3452
3136
 
3453
3137
def partition_tests(suite, count):
3454
3138
    """Partition suite into count lists of tests."""
3455
 
    # This just assigns tests in a round-robin fashion.  On one hand this
3456
 
    # splits up blocks of related tests that might run faster if they shared
3457
 
    # resources, but on the other it avoids assigning blocks of slow tests to
3458
 
    # just one partition.  So the slowest partition shouldn't be much slower
3459
 
    # than the fastest.
3460
 
    partitions = [list() for i in range(count)]
3461
 
    tests = iter_suite_tests(suite)
3462
 
    for partition, test in itertools.izip(itertools.cycle(partitions), tests):
3463
 
        partition.append(test)
3464
 
    return partitions
3465
 
 
3466
 
 
3467
 
def workaround_zealous_crypto_random():
3468
 
    """Crypto.Random want to help us being secure, but we don't care here.
3469
 
 
3470
 
    This workaround some test failure related to the sftp server. Once paramiko
3471
 
    stop using the controversial API in Crypto.Random, we may get rid of it.
3472
 
    """
3473
 
    try:
3474
 
        from Crypto.Random import atfork
3475
 
        atfork()
3476
 
    except ImportError:
3477
 
        pass
 
3139
    result = []
 
3140
    tests = list(iter_suite_tests(suite))
 
3141
    tests_per_process = int(math.ceil(float(len(tests)) / count))
 
3142
    for block in range(count):
 
3143
        low_test = block * tests_per_process
 
3144
        high_test = low_test + tests_per_process
 
3145
        process_tests = tests[low_test:high_test]
 
3146
        result.append(process_tests)
 
3147
    return result
3478
3148
 
3479
3149
 
3480
3150
def fork_for_tests(suite):
3497
3167
            try:
3498
3168
                ProtocolTestCase.run(self, result)
3499
3169
            finally:
3500
 
                os.waitpid(self.pid, 0)
 
3170
                os.waitpid(self.pid, os.WNOHANG)
3501
3171
 
3502
3172
    test_blocks = partition_tests(suite, concurrency)
3503
3173
    for process_tests in test_blocks:
3504
 
        process_suite = TestUtil.TestSuite()
 
3174
        process_suite = TestSuite()
3505
3175
        process_suite.addTests(process_tests)
3506
3176
        c2pread, c2pwrite = os.pipe()
3507
3177
        pid = os.fork()
3508
3178
        if pid == 0:
3509
 
            workaround_zealous_crypto_random()
3510
3179
            try:
3511
3180
                os.close(c2pread)
3512
3181
                # Leave stderr and stdout open so we can see test noise
3573
3242
                '--subunit']
3574
3243
            if '--no-plugins' in sys.argv:
3575
3244
                argv.append('--no-plugins')
3576
 
            # stderr=subprocess.STDOUT would be ideal, but until we prevent
3577
 
            # noise on stderr it can interrupt the subunit protocol.
3578
 
            process = subprocess.Popen(argv, stdin=subprocess.PIPE,
3579
 
                                      stdout=subprocess.PIPE,
3580
 
                                      stderr=subprocess.PIPE,
3581
 
                                      bufsize=1)
 
3245
            # stderr=STDOUT would be ideal, but until we prevent noise on
 
3246
            # stderr it can interrupt the subunit protocol.
 
3247
            process = Popen(argv, stdin=PIPE, stdout=PIPE, stderr=PIPE,
 
3248
                bufsize=1)
3582
3249
            test = TestInSubprocess(process, test_list_file_name)
3583
3250
            result.append(test)
3584
3251
        except:
3587
3254
    return result
3588
3255
 
3589
3256
 
3590
 
class ProfileResult(testtools.ExtendedToOriginalDecorator):
 
3257
class ForwardingResult(unittest.TestResult):
 
3258
 
 
3259
    def __init__(self, target):
 
3260
        unittest.TestResult.__init__(self)
 
3261
        self.result = target
 
3262
 
 
3263
    def startTest(self, test):
 
3264
        self.result.startTest(test)
 
3265
 
 
3266
    def stopTest(self, test):
 
3267
        self.result.stopTest(test)
 
3268
 
 
3269
    def startTestRun(self):
 
3270
        self.result.startTestRun()
 
3271
 
 
3272
    def stopTestRun(self):
 
3273
        self.result.stopTestRun()
 
3274
 
 
3275
    def addSkip(self, test, reason):
 
3276
        self.result.addSkip(test, reason)
 
3277
 
 
3278
    def addSuccess(self, test):
 
3279
        self.result.addSuccess(test)
 
3280
 
 
3281
    def addError(self, test, err):
 
3282
        self.result.addError(test, err)
 
3283
 
 
3284
    def addFailure(self, test, err):
 
3285
        self.result.addFailure(test, err)
 
3286
ForwardingResult = testtools.ExtendedToOriginalDecorator
 
3287
 
 
3288
 
 
3289
class ProfileResult(ForwardingResult):
3591
3290
    """Generate profiling data for all activity between start and success.
3592
3291
    
3593
3292
    The profile data is appended to the test's _benchcalls attribute and can
3601
3300
 
3602
3301
    def startTest(self, test):
3603
3302
        self.profiler = bzrlib.lsprof.BzrProfiler()
3604
 
        # Prevent deadlocks in tests that use lsprof: those tests will
3605
 
        # unavoidably fail.
3606
 
        bzrlib.lsprof.BzrProfiler.profiler_block = 0
3607
3303
        self.profiler.start()
3608
 
        testtools.ExtendedToOriginalDecorator.startTest(self, test)
 
3304
        ForwardingResult.startTest(self, test)
3609
3305
 
3610
3306
    def addSuccess(self, test):
3611
3307
        stats = self.profiler.stop()
3615
3311
            test._benchcalls = []
3616
3312
            calls = test._benchcalls
3617
3313
        calls.append(((test.id(), "", ""), stats))
3618
 
        testtools.ExtendedToOriginalDecorator.addSuccess(self, test)
 
3314
        ForwardingResult.addSuccess(self, test)
3619
3315
 
3620
3316
    def stopTest(self, test):
3621
 
        testtools.ExtendedToOriginalDecorator.stopTest(self, test)
 
3317
        ForwardingResult.stopTest(self, test)
3622
3318
        self.profiler = None
3623
3319
 
3624
3320
 
3630
3326
#                           rather than failing tests. And no longer raise
3631
3327
#                           LockContention when fctnl locks are not being used
3632
3328
#                           with proper exclusion rules.
3633
 
#   -Ethreads               Will display thread ident at creation/join time to
3634
 
#                           help track thread leaks
3635
 
 
3636
 
#   -Econfig_stats          Will collect statistics using addDetail
3637
3329
selftest_debug_flags = set()
3638
3330
 
3639
3331
 
3833
3525
                key, obj, help=help, info=info, override_existing=False)
3834
3526
        except KeyError:
3835
3527
            actual = self.get(key)
3836
 
            trace.note(
3837
 
                'Test prefix alias %s is already used for %s, ignoring %s'
3838
 
                % (key, actual, obj))
 
3528
            note('Test prefix alias %s is already used for %s, ignoring %s'
 
3529
                 % (key, actual, obj))
3839
3530
 
3840
3531
    def resolve_alias(self, id_start):
3841
3532
        """Replace the alias by the prefix in the given string.
3859
3550
# appear prefixed ('bzrlib.' is "replaced" by 'bzrlib.').
3860
3551
test_prefix_alias_registry.register('bzrlib', 'bzrlib')
3861
3552
 
3862
 
# Obvious highest levels prefixes, feel free to add your own via a plugin
 
3553
# Obvious higest levels prefixes, feel free to add your own via a plugin
3863
3554
test_prefix_alias_registry.register('bd', 'bzrlib.doc')
3864
3555
test_prefix_alias_registry.register('bu', 'bzrlib.utils')
3865
3556
test_prefix_alias_registry.register('bt', 'bzrlib.tests')
3873
3564
        'bzrlib.doc',
3874
3565
        'bzrlib.tests.blackbox',
3875
3566
        'bzrlib.tests.commands',
3876
 
        'bzrlib.tests.doc_generate',
3877
3567
        'bzrlib.tests.per_branch',
3878
3568
        'bzrlib.tests.per_bzrdir',
3879
 
        'bzrlib.tests.per_controldir',
3880
 
        'bzrlib.tests.per_controldir_colo',
3881
3569
        'bzrlib.tests.per_foreign_vcs',
3882
3570
        'bzrlib.tests.per_interrepository',
3883
3571
        'bzrlib.tests.per_intertree',
3891
3579
        'bzrlib.tests.per_repository',
3892
3580
        'bzrlib.tests.per_repository_chk',
3893
3581
        'bzrlib.tests.per_repository_reference',
3894
 
        'bzrlib.tests.per_repository_vf',
3895
3582
        'bzrlib.tests.per_uifactory',
3896
3583
        'bzrlib.tests.per_versionedfile',
3897
3584
        'bzrlib.tests.per_workingtree',
3898
3585
        'bzrlib.tests.test__annotator',
3899
3586
        'bzrlib.tests.test__bencode',
3900
 
        'bzrlib.tests.test__btree_serializer',
3901
3587
        'bzrlib.tests.test__chk_map',
3902
3588
        'bzrlib.tests.test__dirstate_helpers',
3903
3589
        'bzrlib.tests.test__groupcompress',
3925
3611
        'bzrlib.tests.test_chunk_writer',
3926
3612
        'bzrlib.tests.test_clean_tree',
3927
3613
        'bzrlib.tests.test_cleanup',
3928
 
        'bzrlib.tests.test_cmdline',
3929
3614
        'bzrlib.tests.test_commands',
3930
3615
        'bzrlib.tests.test_commit',
3931
3616
        'bzrlib.tests.test_commit_merge',
3932
3617
        'bzrlib.tests.test_config',
3933
3618
        'bzrlib.tests.test_conflicts',
3934
 
        'bzrlib.tests.test_controldir',
3935
3619
        'bzrlib.tests.test_counted_lock',
3936
3620
        'bzrlib.tests.test_crash',
3937
3621
        'bzrlib.tests.test_decorators',
3938
3622
        'bzrlib.tests.test_delta',
3939
3623
        'bzrlib.tests.test_debug',
 
3624
        'bzrlib.tests.test_deprecated_graph',
3940
3625
        'bzrlib.tests.test_diff',
3941
3626
        'bzrlib.tests.test_directory_service',
3942
3627
        'bzrlib.tests.test_dirstate',
3944
3629
        'bzrlib.tests.test_eol_filters',
3945
3630
        'bzrlib.tests.test_errors',
3946
3631
        'bzrlib.tests.test_export',
3947
 
        'bzrlib.tests.test_export_pot',
3948
3632
        'bzrlib.tests.test_extract',
3949
 
        'bzrlib.tests.test_features',
3950
3633
        'bzrlib.tests.test_fetch',
3951
 
        'bzrlib.tests.test_fixtures',
3952
3634
        'bzrlib.tests.test_fifo_cache',
3953
3635
        'bzrlib.tests.test_filters',
3954
 
        'bzrlib.tests.test_filter_tree',
3955
3636
        'bzrlib.tests.test_ftp_transport',
3956
3637
        'bzrlib.tests.test_foreign',
3957
3638
        'bzrlib.tests.test_generate_docs',
3966
3647
        'bzrlib.tests.test_http',
3967
3648
        'bzrlib.tests.test_http_response',
3968
3649
        'bzrlib.tests.test_https_ca_bundle',
3969
 
        'bzrlib.tests.test_i18n',
3970
3650
        'bzrlib.tests.test_identitymap',
3971
3651
        'bzrlib.tests.test_ignores',
3972
3652
        'bzrlib.tests.test_index',
3973
 
        'bzrlib.tests.test_import_tariff',
3974
3653
        'bzrlib.tests.test_info',
3975
3654
        'bzrlib.tests.test_inv',
3976
3655
        'bzrlib.tests.test_inventory_delta',
3977
3656
        'bzrlib.tests.test_knit',
3978
3657
        'bzrlib.tests.test_lazy_import',
3979
3658
        'bzrlib.tests.test_lazy_regex',
3980
 
        'bzrlib.tests.test_library_state',
3981
3659
        'bzrlib.tests.test_lock',
3982
3660
        'bzrlib.tests.test_lockable_files',
3983
3661
        'bzrlib.tests.test_lockdir',
3985
3663
        'bzrlib.tests.test_lru_cache',
3986
3664
        'bzrlib.tests.test_lsprof',
3987
3665
        'bzrlib.tests.test_mail_client',
3988
 
        'bzrlib.tests.test_matchers',
3989
3666
        'bzrlib.tests.test_memorytree',
3990
3667
        'bzrlib.tests.test_merge',
3991
3668
        'bzrlib.tests.test_merge3',
3992
3669
        'bzrlib.tests.test_merge_core',
3993
3670
        'bzrlib.tests.test_merge_directive',
3994
 
        'bzrlib.tests.test_mergetools',
3995
3671
        'bzrlib.tests.test_missing',
3996
3672
        'bzrlib.tests.test_msgeditor',
3997
3673
        'bzrlib.tests.test_multiparent',
4006
3682
        'bzrlib.tests.test_permissions',
4007
3683
        'bzrlib.tests.test_plugins',
4008
3684
        'bzrlib.tests.test_progress',
4009
 
        'bzrlib.tests.test_pyutils',
4010
3685
        'bzrlib.tests.test_read_bundle',
4011
3686
        'bzrlib.tests.test_reconcile',
4012
3687
        'bzrlib.tests.test_reconfigure',
4021
3696
        'bzrlib.tests.test_rio',
4022
3697
        'bzrlib.tests.test_rules',
4023
3698
        'bzrlib.tests.test_sampler',
4024
 
        'bzrlib.tests.test_scenarios',
4025
3699
        'bzrlib.tests.test_script',
4026
3700
        'bzrlib.tests.test_selftest',
4027
3701
        'bzrlib.tests.test_serializer',
4043
3717
        'bzrlib.tests.test_switch',
4044
3718
        'bzrlib.tests.test_symbol_versioning',
4045
3719
        'bzrlib.tests.test_tag',
4046
 
        'bzrlib.tests.test_test_server',
4047
3720
        'bzrlib.tests.test_testament',
4048
3721
        'bzrlib.tests.test_textfile',
4049
3722
        'bzrlib.tests.test_textmerge',
4050
 
        'bzrlib.tests.test_cethread',
4051
3723
        'bzrlib.tests.test_timestamp',
4052
3724
        'bzrlib.tests.test_trace',
4053
3725
        'bzrlib.tests.test_transactions',
4056
3728
        'bzrlib.tests.test_transport_log',
4057
3729
        'bzrlib.tests.test_tree',
4058
3730
        'bzrlib.tests.test_treebuilder',
4059
 
        'bzrlib.tests.test_treeshape',
4060
3731
        'bzrlib.tests.test_tsort',
4061
3732
        'bzrlib.tests.test_tuned_gzip',
4062
3733
        'bzrlib.tests.test_ui',
4064
3735
        'bzrlib.tests.test_upgrade',
4065
3736
        'bzrlib.tests.test_upgrade_stacked',
4066
3737
        'bzrlib.tests.test_urlutils',
4067
 
        'bzrlib.tests.test_utextwrap',
4068
3738
        'bzrlib.tests.test_version',
4069
3739
        'bzrlib.tests.test_version_info',
4070
 
        'bzrlib.tests.test_versionedfile',
4071
3740
        'bzrlib.tests.test_weave',
4072
3741
        'bzrlib.tests.test_whitebox',
4073
3742
        'bzrlib.tests.test_win32utils',
4079
3748
 
4080
3749
 
4081
3750
def _test_suite_modules_to_doctest():
4082
 
    """Return the list of modules to doctest."""
4083
 
    if __doc__ is None:
4084
 
        # GZ 2009-03-31: No docstrings with -OO so there's nothing to doctest
4085
 
        return []
 
3751
    """Return the list of modules to doctest."""   
4086
3752
    return [
4087
3753
        'bzrlib',
4088
3754
        'bzrlib.branchbuilder',
4089
3755
        'bzrlib.decorators',
 
3756
        'bzrlib.export',
4090
3757
        'bzrlib.inventory',
4091
3758
        'bzrlib.iterablefile',
4092
3759
        'bzrlib.lockdir',
4093
3760
        'bzrlib.merge3',
4094
3761
        'bzrlib.option',
4095
 
        'bzrlib.pyutils',
4096
3762
        'bzrlib.symbol_versioning',
4097
3763
        'bzrlib.tests',
4098
 
        'bzrlib.tests.fixtures',
4099
3764
        'bzrlib.timestamp',
4100
 
        'bzrlib.transport.http',
4101
3765
        'bzrlib.version_info_formats.format_custom',
4102
3766
        ]
4103
3767
 
4156
3820
        try:
4157
3821
            # note that this really does mean "report only" -- doctest
4158
3822
            # still runs the rest of the examples
4159
 
            doc_suite = IsolatedDocTestSuite(
4160
 
                mod, optionflags=doctest.REPORT_ONLY_FIRST_FAILURE)
 
3823
            doc_suite = doctest.DocTestSuite(mod,
 
3824
                optionflags=doctest.REPORT_ONLY_FIRST_FAILURE)
4161
3825
        except ValueError, e:
4162
3826
            print '**failed to get doctest for: %s\n%s' % (mod, e)
4163
3827
            raise
4166
3830
        suite.addTest(doc_suite)
4167
3831
 
4168
3832
    default_encoding = sys.getdefaultencoding()
4169
 
    for name, plugin in _mod_plugin.plugins().items():
 
3833
    for name, plugin in bzrlib.plugin.plugins().items():
4170
3834
        if not interesting_module(plugin.module.__name__):
4171
3835
            continue
4172
3836
        plugin_suite = plugin.test_suite()
4178
3842
        if plugin_suite is not None:
4179
3843
            suite.addTest(plugin_suite)
4180
3844
        if default_encoding != sys.getdefaultencoding():
4181
 
            trace.warning(
 
3845
            bzrlib.trace.warning(
4182
3846
                'Plugin "%s" tried to reset default encoding to: %s', name,
4183
3847
                sys.getdefaultencoding())
4184
3848
            reload(sys)
4199
3863
            # Some tests mentioned in the list are not in the test suite. The
4200
3864
            # list may be out of date, report to the tester.
4201
3865
            for id in not_found:
4202
 
                trace.warning('"%s" not found in the test suite', id)
 
3866
                bzrlib.trace.warning('"%s" not found in the test suite', id)
4203
3867
        for id in duplicates:
4204
 
            trace.warning('"%s" is used as an id by several tests', id)
 
3868
            bzrlib.trace.warning('"%s" is used as an id by several tests', id)
4205
3869
 
4206
3870
    return suite
4207
3871
 
4208
3872
 
4209
 
def multiply_scenarios(*scenarios):
4210
 
    """Multiply two or more iterables of scenarios.
4211
 
 
4212
 
    It is safe to pass scenario generators or iterators.
4213
 
 
4214
 
    :returns: A list of compound scenarios: the cross-product of all 
4215
 
        scenarios, with the names concatenated and the parameters
4216
 
        merged together.
4217
 
    """
4218
 
    return reduce(_multiply_two_scenarios, map(list, scenarios))
4219
 
 
4220
 
 
4221
 
def _multiply_two_scenarios(scenarios_left, scenarios_right):
 
3873
def multiply_scenarios(scenarios_left, scenarios_right):
4222
3874
    """Multiply two sets of scenarios.
4223
3875
 
4224
3876
    :returns: the cartesian product of the two sets of scenarios, that is
4255
3907
    ...     bzrlib.tests.test_sampler.DemoTest('test_nothing'),
4256
3908
    ...     [('one', dict(param=1)),
4257
3909
    ...      ('two', dict(param=2))],
4258
 
    ...     TestUtil.TestSuite())
 
3910
    ...     TestSuite())
4259
3911
    >>> tests = list(iter_suite_tests(r))
4260
3912
    >>> len(tests)
4261
3913
    2
4308
3960
    :param new_id: The id to assign to it.
4309
3961
    :return: The new test.
4310
3962
    """
4311
 
    new_test = copy.copy(test)
 
3963
    new_test = copy(test)
4312
3964
    new_test.id = lambda: new_id
4313
 
    # XXX: Workaround <https://bugs.launchpad.net/testtools/+bug/637725>, which
4314
 
    # causes cloned tests to share the 'details' dict.  This makes it hard to
4315
 
    # read the test output for parameterized tests, because tracebacks will be
4316
 
    # associated with irrelevant tests.
4317
 
    try:
4318
 
        details = new_test._TestCase__details
4319
 
    except AttributeError:
4320
 
        # must be a different version of testtools than expected.  Do nothing.
4321
 
        pass
4322
 
    else:
4323
 
        # Reset the '__details' dict.
4324
 
        new_test._TestCase__details = {}
4325
3965
    return new_test
4326
3966
 
4327
3967
 
4348
3988
        the module is available.
4349
3989
    """
4350
3990
 
4351
 
    from bzrlib.tests.features import ModuleAvailableFeature
4352
 
    py_module = pyutils.get_named_object(py_module_name)
 
3991
    py_module = __import__(py_module_name, {}, {}, ['NO_SUCH_ATTRIB'])
4353
3992
    scenarios = [
4354
3993
        ('python', {'module': py_module}),
4355
3994
    ]
4388
4027
        if test_id != None:
4389
4028
            ui.ui_factory.clear_term()
4390
4029
            sys.stderr.write('\nWhile running: %s\n' % (test_id,))
4391
 
        # Ugly, but the last thing we want here is fail, so bear with it.
4392
 
        printable_e = str(e).decode(osutils.get_user_encoding(), 'replace'
4393
 
                                    ).encode('ascii', 'replace')
4394
4030
        sys.stderr.write('Unable to remove testing dir %s\n%s'
4395
 
                         % (os.path.basename(dirname), printable_e))
 
4031
                         % (os.path.basename(dirname), e))
 
4032
 
 
4033
 
 
4034
class Feature(object):
 
4035
    """An operating system Feature."""
 
4036
 
 
4037
    def __init__(self):
 
4038
        self._available = None
 
4039
 
 
4040
    def available(self):
 
4041
        """Is the feature available?
 
4042
 
 
4043
        :return: True if the feature is available.
 
4044
        """
 
4045
        if self._available is None:
 
4046
            self._available = self._probe()
 
4047
        return self._available
 
4048
 
 
4049
    def _probe(self):
 
4050
        """Implement this method in concrete features.
 
4051
 
 
4052
        :return: True if the feature is available.
 
4053
        """
 
4054
        raise NotImplementedError
 
4055
 
 
4056
    def __str__(self):
 
4057
        if getattr(self, 'feature_name', None):
 
4058
            return self.feature_name()
 
4059
        return self.__class__.__name__
 
4060
 
 
4061
 
 
4062
class _SymlinkFeature(Feature):
 
4063
 
 
4064
    def _probe(self):
 
4065
        return osutils.has_symlinks()
 
4066
 
 
4067
    def feature_name(self):
 
4068
        return 'symlinks'
 
4069
 
 
4070
SymlinkFeature = _SymlinkFeature()
 
4071
 
 
4072
 
 
4073
class _HardlinkFeature(Feature):
 
4074
 
 
4075
    def _probe(self):
 
4076
        return osutils.has_hardlinks()
 
4077
 
 
4078
    def feature_name(self):
 
4079
        return 'hardlinks'
 
4080
 
 
4081
HardlinkFeature = _HardlinkFeature()
 
4082
 
 
4083
 
 
4084
class _OsFifoFeature(Feature):
 
4085
 
 
4086
    def _probe(self):
 
4087
        return getattr(os, 'mkfifo', None)
 
4088
 
 
4089
    def feature_name(self):
 
4090
        return 'filesystem fifos'
 
4091
 
 
4092
OsFifoFeature = _OsFifoFeature()
 
4093
 
 
4094
 
 
4095
class _UnicodeFilenameFeature(Feature):
 
4096
    """Does the filesystem support Unicode filenames?"""
 
4097
 
 
4098
    def _probe(self):
 
4099
        try:
 
4100
            # Check for character combinations unlikely to be covered by any
 
4101
            # single non-unicode encoding. We use the characters
 
4102
            # - greek small letter alpha (U+03B1) and
 
4103
            # - braille pattern dots-123456 (U+283F).
 
4104
            os.stat(u'\u03b1\u283f')
 
4105
        except UnicodeEncodeError:
 
4106
            return False
 
4107
        except (IOError, OSError):
 
4108
            # The filesystem allows the Unicode filename but the file doesn't
 
4109
            # exist.
 
4110
            return True
 
4111
        else:
 
4112
            # The filesystem allows the Unicode filename and the file exists,
 
4113
            # for some reason.
 
4114
            return True
 
4115
 
 
4116
UnicodeFilenameFeature = _UnicodeFilenameFeature()
 
4117
 
 
4118
 
 
4119
class _CompatabilityThunkFeature(Feature):
 
4120
    """This feature is just a thunk to another feature.
 
4121
 
 
4122
    It issues a deprecation warning if it is accessed, to let you know that you
 
4123
    should really use a different feature.
 
4124
    """
 
4125
 
 
4126
    def __init__(self, module, name, this_name, dep_version):
 
4127
        super(_CompatabilityThunkFeature, self).__init__()
 
4128
        self._module = module
 
4129
        self._name = name
 
4130
        self._this_name = this_name
 
4131
        self._dep_version = dep_version
 
4132
        self._feature = None
 
4133
 
 
4134
    def _ensure(self):
 
4135
        if self._feature is None:
 
4136
            msg = (self._dep_version % self._this_name) + (
 
4137
                   ' Use %s.%s instead.' % (self._module, self._name))
 
4138
            symbol_versioning.warn(msg, DeprecationWarning)
 
4139
            mod = __import__(self._module, {}, {}, [self._name])
 
4140
            self._feature = getattr(mod, self._name)
 
4141
 
 
4142
    def _probe(self):
 
4143
        self._ensure()
 
4144
        return self._feature._probe()
 
4145
 
 
4146
 
 
4147
class ModuleAvailableFeature(Feature):
 
4148
    """This is a feature than describes a module we want to be available.
 
4149
 
 
4150
    Declare the name of the module in __init__(), and then after probing, the
 
4151
    module will be available as 'self.module'.
 
4152
 
 
4153
    :ivar module: The module if it is available, else None.
 
4154
    """
 
4155
 
 
4156
    def __init__(self, module_name):
 
4157
        super(ModuleAvailableFeature, self).__init__()
 
4158
        self.module_name = module_name
 
4159
 
 
4160
    def _probe(self):
 
4161
        try:
 
4162
            self._module = __import__(self.module_name, {}, {}, [''])
 
4163
            return True
 
4164
        except ImportError:
 
4165
            return False
 
4166
 
 
4167
    @property
 
4168
    def module(self):
 
4169
        if self.available(): # Make sure the probe has been done
 
4170
            return self._module
 
4171
        return None
 
4172
    
 
4173
    def feature_name(self):
 
4174
        return self.module_name
 
4175
 
 
4176
 
 
4177
# This is kept here for compatibility, it is recommended to use
 
4178
# 'bzrlib.tests.feature.paramiko' instead
 
4179
ParamikoFeature = _CompatabilityThunkFeature('bzrlib.tests.features',
 
4180
    'paramiko', 'bzrlib.tests.ParamikoFeature', deprecated_in((2,1,0)))
4396
4181
 
4397
4182
 
4398
4183
def probe_unicode_in_user_encoding():
4428
4213
    return None
4429
4214
 
4430
4215
 
 
4216
class _HTTPSServerFeature(Feature):
 
4217
    """Some tests want an https Server, check if one is available.
 
4218
 
 
4219
    Right now, the only way this is available is under python2.6 which provides
 
4220
    an ssl module.
 
4221
    """
 
4222
 
 
4223
    def _probe(self):
 
4224
        try:
 
4225
            import ssl
 
4226
            return True
 
4227
        except ImportError:
 
4228
            return False
 
4229
 
 
4230
    def feature_name(self):
 
4231
        return 'HTTPSServer'
 
4232
 
 
4233
 
 
4234
HTTPSServerFeature = _HTTPSServerFeature()
 
4235
 
 
4236
 
 
4237
class _UnicodeFilename(Feature):
 
4238
    """Does the filesystem support Unicode filenames?"""
 
4239
 
 
4240
    def _probe(self):
 
4241
        try:
 
4242
            os.stat(u'\u03b1')
 
4243
        except UnicodeEncodeError:
 
4244
            return False
 
4245
        except (IOError, OSError):
 
4246
            # The filesystem allows the Unicode filename but the file doesn't
 
4247
            # exist.
 
4248
            return True
 
4249
        else:
 
4250
            # The filesystem allows the Unicode filename and the file exists,
 
4251
            # for some reason.
 
4252
            return True
 
4253
 
 
4254
UnicodeFilename = _UnicodeFilename()
 
4255
 
 
4256
 
 
4257
class _UTF8Filesystem(Feature):
 
4258
    """Is the filesystem UTF-8?"""
 
4259
 
 
4260
    def _probe(self):
 
4261
        if osutils._fs_enc.upper() in ('UTF-8', 'UTF8'):
 
4262
            return True
 
4263
        return False
 
4264
 
 
4265
UTF8Filesystem = _UTF8Filesystem()
 
4266
 
 
4267
 
 
4268
class _BreakinFeature(Feature):
 
4269
    """Does this platform support the breakin feature?"""
 
4270
 
 
4271
    def _probe(self):
 
4272
        from bzrlib import breakin
 
4273
        if breakin.determine_signal() is None:
 
4274
            return False
 
4275
        if sys.platform == 'win32':
 
4276
            # Windows doesn't have os.kill, and we catch the SIGBREAK signal.
 
4277
            # We trigger SIGBREAK via a Console api so we need ctypes to
 
4278
            # access the function
 
4279
            try:
 
4280
                import ctypes
 
4281
            except OSError:
 
4282
                return False
 
4283
        return True
 
4284
 
 
4285
    def feature_name(self):
 
4286
        return "SIGQUIT or SIGBREAK w/ctypes on win32"
 
4287
 
 
4288
 
 
4289
BreakinFeature = _BreakinFeature()
 
4290
 
 
4291
 
 
4292
class _CaseInsCasePresFilenameFeature(Feature):
 
4293
    """Is the file-system case insensitive, but case-preserving?"""
 
4294
 
 
4295
    def _probe(self):
 
4296
        fileno, name = tempfile.mkstemp(prefix='MixedCase')
 
4297
        try:
 
4298
            # first check truly case-preserving for created files, then check
 
4299
            # case insensitive when opening existing files.
 
4300
            name = osutils.normpath(name)
 
4301
            base, rel = osutils.split(name)
 
4302
            found_rel = osutils.canonical_relpath(base, name)
 
4303
            return (found_rel == rel
 
4304
                    and os.path.isfile(name.upper())
 
4305
                    and os.path.isfile(name.lower()))
 
4306
        finally:
 
4307
            os.close(fileno)
 
4308
            os.remove(name)
 
4309
 
 
4310
    def feature_name(self):
 
4311
        return "case-insensitive case-preserving filesystem"
 
4312
 
 
4313
CaseInsCasePresFilenameFeature = _CaseInsCasePresFilenameFeature()
 
4314
 
 
4315
 
 
4316
class _CaseInsensitiveFilesystemFeature(Feature):
 
4317
    """Check if underlying filesystem is case-insensitive but *not* case
 
4318
    preserving.
 
4319
    """
 
4320
    # Note that on Windows, Cygwin, MacOS etc, the file-systems are far
 
4321
    # more likely to be case preserving, so this case is rare.
 
4322
 
 
4323
    def _probe(self):
 
4324
        if CaseInsCasePresFilenameFeature.available():
 
4325
            return False
 
4326
 
 
4327
        if TestCaseWithMemoryTransport.TEST_ROOT is None:
 
4328
            root = osutils.mkdtemp(prefix='testbzr-', suffix='.tmp')
 
4329
            TestCaseWithMemoryTransport.TEST_ROOT = root
 
4330
        else:
 
4331
            root = TestCaseWithMemoryTransport.TEST_ROOT
 
4332
        tdir = osutils.mkdtemp(prefix='case-sensitive-probe-', suffix='',
 
4333
            dir=root)
 
4334
        name_a = osutils.pathjoin(tdir, 'a')
 
4335
        name_A = osutils.pathjoin(tdir, 'A')
 
4336
        os.mkdir(name_a)
 
4337
        result = osutils.isdir(name_A)
 
4338
        _rmtree_temp_dir(tdir)
 
4339
        return result
 
4340
 
 
4341
    def feature_name(self):
 
4342
        return 'case-insensitive filesystem'
 
4343
 
 
4344
CaseInsensitiveFilesystemFeature = _CaseInsensitiveFilesystemFeature()
 
4345
 
 
4346
 
 
4347
# Kept for compatibility, use bzrlib.tests.features.subunit instead
 
4348
SubUnitFeature = _CompatabilityThunkFeature('bzrlib.tests.features', 'subunit',
 
4349
    'bzrlib.tests.SubUnitFeature', deprecated_in((2,1,0)))
4431
4350
# Only define SubUnitBzrRunner if subunit is available.
4432
4351
try:
4433
4352
    from subunit import TestProtocolClient
4434
4353
    from subunit.test_results import AutoTimingTestResultDecorator
4435
 
    class SubUnitBzrProtocolClient(TestProtocolClient):
4436
 
 
4437
 
        def addSuccess(self, test, details=None):
4438
 
            # The subunit client always includes the details in the subunit
4439
 
            # stream, but we don't want to include it in ours.
4440
 
            if details is not None and 'log' in details:
4441
 
                del details['log']
4442
 
            return super(SubUnitBzrProtocolClient, self).addSuccess(
4443
 
                test, details)
4444
 
 
4445
4354
    class SubUnitBzrRunner(TextTestRunner):
4446
4355
        def run(self, test):
4447
4356
            result = AutoTimingTestResultDecorator(
4448
 
                SubUnitBzrProtocolClient(self.stream))
 
4357
                TestProtocolClient(self.stream))
4449
4358
            test.run(result)
4450
4359
            return result
4451
4360
except ImportError:
4452
4361
    pass
4453
 
 
4454
 
 
4455
 
@deprecated_function(deprecated_in((2, 5, 0)))
4456
 
def ModuleAvailableFeature(name):
4457
 
    from bzrlib.tests import features
4458
 
    return features.ModuleAvailableFeature(name)
4459