~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/__init__.py

Merge bzr.dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006 by Canonical Ltd
2
 
 
 
1
# Copyright (C) 2005, 2006, 2007 Canonical Ltd
 
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
5
5
# the Free Software Foundation; either version 2 of the License, or
6
6
# (at your option) any later version.
7
 
 
 
7
#
8
8
# This program is distributed in the hope that it will be useful,
9
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
11
# GNU General Public License for more details.
12
 
 
 
12
#
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
29
29
import codecs
30
30
from cStringIO import StringIO
31
31
import difflib
 
32
import doctest
32
33
import errno
33
34
import logging
34
35
import os
 
36
from pprint import pformat
35
37
import re
 
38
import shlex
36
39
import stat
 
40
from subprocess import Popen, PIPE
37
41
import sys
38
42
import tempfile
39
43
import unittest
40
44
import time
41
45
 
42
46
 
 
47
from bzrlib import (
 
48
    bzrdir,
 
49
    debug,
 
50
    errors,
 
51
    memorytree,
 
52
    osutils,
 
53
    progress,
 
54
    urlutils,
 
55
    )
43
56
import bzrlib.branch
44
 
import bzrlib.bzrdir as bzrdir
45
57
import bzrlib.commands
46
 
import bzrlib.errors as errors
 
58
import bzrlib.timestamp
 
59
import bzrlib.export
47
60
import bzrlib.inventory
48
61
import bzrlib.iterablefile
49
62
import bzrlib.lockdir
55
68
from bzrlib.merge import merge_inner
56
69
import bzrlib.merge3
57
70
import bzrlib.osutils
58
 
import bzrlib.osutils as osutils
59
71
import bzrlib.plugin
60
 
import bzrlib.progress as progress
61
72
from bzrlib.revision import common_ancestor
62
73
import bzrlib.store
 
74
from bzrlib import symbol_versioning
63
75
import bzrlib.trace
64
 
from bzrlib.transport import urlescape, get_transport
 
76
from bzrlib.transport import get_transport
65
77
import bzrlib.transport
66
 
from bzrlib.transport.local import LocalRelpathServer
 
78
from bzrlib.transport.local import LocalURLServer
 
79
from bzrlib.transport.memory import MemoryServer
67
80
from bzrlib.transport.readonly import ReadonlyServer
68
 
from bzrlib.trace import mutter
69
 
from bzrlib.tests.TestUtil import TestLoader, TestSuite
 
81
from bzrlib.trace import mutter, note
 
82
from bzrlib.tests import TestUtil
 
83
from bzrlib.tests.HttpServer import HttpServer
 
84
from bzrlib.tests.TestUtil import (
 
85
                          TestSuite,
 
86
                          TestLoader,
 
87
                          )
70
88
from bzrlib.tests.treeshape import build_tree_contents
71
89
from bzrlib.workingtree import WorkingTree, WorkingTreeFormat2
72
90
 
73
 
default_transport = LocalRelpathServer
 
91
default_transport = LocalURLServer
74
92
 
75
93
MODULES_TO_TEST = []
76
94
MODULES_TO_DOCTEST = [
77
 
                      bzrlib.branch,
78
 
                      bzrlib.commands,
 
95
                      bzrlib.timestamp,
79
96
                      bzrlib.errors,
 
97
                      bzrlib.export,
80
98
                      bzrlib.inventory,
81
99
                      bzrlib.iterablefile,
82
100
                      bzrlib.lockdir,
83
101
                      bzrlib.merge3,
84
102
                      bzrlib.option,
85
 
                      bzrlib.osutils,
86
 
                      bzrlib.store
 
103
                      bzrlib.store,
87
104
                      ]
 
105
 
 
106
NUMBERED_DIRS = False   # dirs kind for TestCaseInTempDir (numbered or named)
 
107
 
 
108
 
88
109
def packages_to_test():
89
110
    """Return a list of packages to test.
90
111
 
97
118
    import bzrlib.tests.bzrdir_implementations
98
119
    import bzrlib.tests.interrepository_implementations
99
120
    import bzrlib.tests.interversionedfile_implementations
 
121
    import bzrlib.tests.intertree_implementations
100
122
    import bzrlib.tests.repository_implementations
101
123
    import bzrlib.tests.revisionstore_implementations
 
124
    import bzrlib.tests.tree_implementations
102
125
    import bzrlib.tests.workingtree_implementations
103
126
    return [
104
127
            bzrlib.doc,
107
130
            bzrlib.tests.bzrdir_implementations,
108
131
            bzrlib.tests.interrepository_implementations,
109
132
            bzrlib.tests.interversionedfile_implementations,
 
133
            bzrlib.tests.intertree_implementations,
110
134
            bzrlib.tests.repository_implementations,
111
135
            bzrlib.tests.revisionstore_implementations,
 
136
            bzrlib.tests.tree_implementations,
112
137
            bzrlib.tests.workingtree_implementations,
113
138
            ]
114
139
 
115
140
 
116
 
class _MyResult(unittest._TextTestResult):
117
 
    """Custom TestResult.
 
141
class ExtendedTestResult(unittest._TextTestResult):
 
142
    """Accepts, reports and accumulates the results of running tests.
118
143
 
119
 
    Shows output in a different format, including displaying runtime for tests.
 
144
    Compared to this unittest version this class adds support for profiling,
 
145
    benchmarking, stopping as soon as a test fails,  and skipping tests.
 
146
    There are further-specialized subclasses for different types of display.
120
147
    """
 
148
 
121
149
    stop_early = False
122
150
    
123
 
    def __init__(self, stream, descriptions, verbosity, pb=None):
 
151
    def __init__(self, stream, descriptions, verbosity,
 
152
                 bench_history=None,
 
153
                 num_tests=None,
 
154
                 ):
 
155
        """Construct new TestResult.
 
156
 
 
157
        :param bench_history: Optionally, a writable file object to accumulate
 
158
            benchmark results.
 
159
        """
124
160
        unittest._TextTestResult.__init__(self, stream, descriptions, verbosity)
125
 
        self.pb = pb
 
161
        if bench_history is not None:
 
162
            from bzrlib.version import _get_bzr_source_tree
 
163
            src_tree = _get_bzr_source_tree()
 
164
            if src_tree:
 
165
                try:
 
166
                    revision_id = src_tree.get_parent_ids()[0]
 
167
                except IndexError:
 
168
                    # XXX: if this is a brand new tree, do the same as if there
 
169
                    # is no branch.
 
170
                    revision_id = ''
 
171
            else:
 
172
                # XXX: If there's no branch, what should we do?
 
173
                revision_id = ''
 
174
            bench_history.write("--date %s %s\n" % (time.time(), revision_id))
 
175
        self._bench_history = bench_history
 
176
        self.ui = bzrlib.ui.ui_factory
 
177
        self.num_tests = num_tests
 
178
        self.error_count = 0
 
179
        self.failure_count = 0
 
180
        self.skip_count = 0
 
181
        self.count = 0
 
182
        self._overall_start_time = time.time()
126
183
    
127
184
    def extractBenchmarkTime(self, testCase):
128
185
        """Add a benchmark time for the current test case."""
138
195
                self._formatTime(self._benchmarkTime),
139
196
                self._elapsedTestTimeString())
140
197
        else:
141
 
            return "      %s" % self._elapsedTestTimeString()
 
198
            return "           %s" % self._elapsedTestTimeString()
142
199
 
143
200
    def _formatTime(self, seconds):
144
201
        """Format seconds as milliseconds with leading spaces."""
145
 
        return "%5dms" % (1000 * seconds)
 
202
        # some benchmarks can take thousands of seconds to run, so we need 8
 
203
        # places
 
204
        return "%8dms" % (1000 * seconds)
146
205
 
147
 
    def _ellipsise_unimportant_words(self, a_string, final_width,
148
 
                                   keep_start=False):
149
 
        """Add ellipses (sp?) for overly long strings.
150
 
        
151
 
        :param keep_start: If true preserve the start of a_string rather
152
 
                           than the end of it.
153
 
        """
154
 
        if keep_start:
155
 
            if len(a_string) > final_width:
156
 
                result = a_string[:final_width-3] + '...'
157
 
            else:
158
 
                result = a_string
159
 
        else:
160
 
            if len(a_string) > final_width:
161
 
                result = '...' + a_string[3-final_width:]
162
 
            else:
163
 
                result = a_string
164
 
        return result.ljust(final_width)
 
206
    def _shortened_test_description(self, test):
 
207
        what = test.id()
 
208
        what = re.sub(r'^bzrlib\.(tests|benchmarks)\.', '', what)
 
209
        return what
165
210
 
166
211
    def startTest(self, test):
167
212
        unittest.TestResult.startTest(self, test)
168
 
        # In a short description, the important words are in
169
 
        # the beginning, but in an id, the important words are
170
 
        # at the end
171
 
        SHOW_DESCRIPTIONS = False
172
 
 
173
 
        if not self.showAll and self.dots and self.pb is not None:
174
 
            final_width = 13
175
 
        else:
176
 
            final_width = osutils.terminal_width()
177
 
            final_width = final_width - 15 - 8
178
 
        what = None
179
 
        if SHOW_DESCRIPTIONS:
180
 
            what = test.shortDescription()
181
 
            if what:
182
 
                what = self._ellipsise_unimportant_words(what, final_width, keep_start=True)
183
 
        if what is None:
184
 
            what = test.id()
185
 
            if what.startswith('bzrlib.tests.'):
186
 
                what = what[13:]
187
 
            what = self._ellipsise_unimportant_words(what, final_width)
188
 
        if self.showAll:
189
 
            self.stream.write(what)
190
 
        elif self.dots and self.pb is not None:
191
 
            self.pb.update(what, self.testsRun - 1, None)
192
 
        self.stream.flush()
 
213
        self.report_test_start(test)
 
214
        test.number = self.count
193
215
        self._recordTestStartTime()
194
216
 
195
217
    def _recordTestStartTime(self):
200
222
        if isinstance(err[1], TestSkipped):
201
223
            return self.addSkipped(test, err)    
202
224
        unittest.TestResult.addError(self, test, err)
 
225
        # We can only do this if we have one of our TestCases, not if
 
226
        # we have a doctest.
 
227
        setKeepLogfile = getattr(test, 'setKeepLogfile', None)
 
228
        if setKeepLogfile is not None:
 
229
            setKeepLogfile()
203
230
        self.extractBenchmarkTime(test)
204
 
        if self.showAll:
205
 
            self.stream.writeln("ERROR %s" % self._testTimeString())
206
 
        elif self.dots and self.pb is None:
207
 
            self.stream.write('E')
208
 
        elif self.dots:
209
 
            self.pb.update(self._ellipsise_unimportant_words('ERROR', 13), self.testsRun, None)
210
 
        self.stream.flush()
 
231
        self.report_error(test, err)
211
232
        if self.stop_early:
212
233
            self.stop()
213
234
 
214
235
    def addFailure(self, test, err):
215
236
        unittest.TestResult.addFailure(self, test, err)
 
237
        # We can only do this if we have one of our TestCases, not if
 
238
        # we have a doctest.
 
239
        setKeepLogfile = getattr(test, 'setKeepLogfile', None)
 
240
        if setKeepLogfile is not None:
 
241
            setKeepLogfile()
216
242
        self.extractBenchmarkTime(test)
217
 
        if self.showAll:
218
 
            self.stream.writeln(" FAIL %s" % self._testTimeString())
219
 
        elif self.dots and self.pb is None:
220
 
            self.stream.write('F')
221
 
        elif self.dots:
222
 
            self.pb.update(self._ellipsise_unimportant_words('FAIL', 13), self.testsRun, None)
223
 
        self.stream.flush()
 
243
        self.report_failure(test, err)
224
244
        if self.stop_early:
225
245
            self.stop()
226
246
 
227
247
    def addSuccess(self, test):
228
248
        self.extractBenchmarkTime(test)
229
 
        if self.showAll:
230
 
            self.stream.writeln('   OK %s' % self._testTimeString())
231
 
            for bench_called, stats in test._benchcalls:
232
 
                self.stream.writeln('LSProf output for %s(%s, %s)' % bench_called)
233
 
                stats.pprint(file=self.stream)
234
 
        elif self.dots and self.pb is None:
235
 
            self.stream.write('~')
236
 
        elif self.dots:
237
 
            self.pb.update(self._ellipsise_unimportant_words('OK', 13), self.testsRun, None)
238
 
        self.stream.flush()
 
249
        if self._bench_history is not None:
 
250
            if self._benchmarkTime is not None:
 
251
                self._bench_history.write("%s %s\n" % (
 
252
                    self._formatTime(self._benchmarkTime),
 
253
                    test.id()))
 
254
        self.report_success(test)
239
255
        unittest.TestResult.addSuccess(self, test)
240
256
 
241
257
    def addSkipped(self, test, skip_excinfo):
242
258
        self.extractBenchmarkTime(test)
243
 
        if self.showAll:
244
 
            print >>self.stream, ' SKIP %s' % self._testTimeString()
245
 
            print >>self.stream, '     %s' % skip_excinfo[1]
246
 
        elif self.dots and self.pb is None:
247
 
            self.stream.write('S')
248
 
        elif self.dots:
249
 
            self.pb.update(self._ellipsise_unimportant_words('SKIP', 13), self.testsRun, None)
250
 
        self.stream.flush()
 
259
        self.report_skip(test, skip_excinfo)
251
260
        # seems best to treat this as success from point-of-view of unittest
252
261
        # -- it actually does nothing so it barely matters :)
253
 
        unittest.TestResult.addSuccess(self, test)
 
262
        try:
 
263
            test.tearDown()
 
264
        except KeyboardInterrupt:
 
265
            raise
 
266
        except:
 
267
            self.addError(test, test.__exc_info())
 
268
        else:
 
269
            unittest.TestResult.addSuccess(self, test)
254
270
 
255
271
    def printErrorList(self, flavour, errors):
256
272
        for test, err in errors:
266
282
            self.stream.writeln(self.separator2)
267
283
            self.stream.writeln("%s" % err)
268
284
 
 
285
    def finished(self):
 
286
        pass
 
287
 
 
288
    def report_cleaning_up(self):
 
289
        pass
 
290
 
 
291
    def report_success(self, test):
 
292
        pass
 
293
 
 
294
 
 
295
class TextTestResult(ExtendedTestResult):
 
296
    """Displays progress and results of tests in text form"""
 
297
 
 
298
    def __init__(self, *args, **kw):
 
299
        ExtendedTestResult.__init__(self, *args, **kw)
 
300
        self.pb = self.ui.nested_progress_bar()
 
301
        self.pb.show_pct = False
 
302
        self.pb.show_spinner = False
 
303
        self.pb.show_eta = False, 
 
304
        self.pb.show_count = False
 
305
        self.pb.show_bar = False
 
306
 
 
307
    def report_starting(self):
 
308
        self.pb.update('[test 0/%d] starting...' % (self.num_tests))
 
309
 
 
310
    def _progress_prefix_text(self):
 
311
        a = '[%d' % self.count
 
312
        if self.num_tests is not None:
 
313
            a +='/%d' % self.num_tests
 
314
        a += ' in %ds' % (time.time() - self._overall_start_time)
 
315
        if self.error_count:
 
316
            a += ', %d errors' % self.error_count
 
317
        if self.failure_count:
 
318
            a += ', %d failed' % self.failure_count
 
319
        if self.skip_count:
 
320
            a += ', %d skipped' % self.skip_count
 
321
        a += ']'
 
322
        return a
 
323
 
 
324
    def report_test_start(self, test):
 
325
        self.count += 1
 
326
        self.pb.update(
 
327
                self._progress_prefix_text()
 
328
                + ' ' 
 
329
                + self._shortened_test_description(test))
 
330
 
 
331
    def _test_description(self, test):
 
332
        if NUMBERED_DIRS:
 
333
            return '#%d %s' % (self.count,
 
334
                               self._shortened_test_description(test))
 
335
        else:
 
336
            return self._shortened_test_description(test)
 
337
 
 
338
    def report_error(self, test, err):
 
339
        self.error_count += 1
 
340
        self.pb.note('ERROR: %s\n    %s\n', 
 
341
            self._test_description(test),
 
342
            err[1],
 
343
            )
 
344
 
 
345
    def report_failure(self, test, err):
 
346
        self.failure_count += 1
 
347
        self.pb.note('FAIL: %s\n    %s\n', 
 
348
            self._test_description(test),
 
349
            err[1],
 
350
            )
 
351
 
 
352
    def report_skip(self, test, skip_excinfo):
 
353
        self.skip_count += 1
 
354
        if False:
 
355
            # at the moment these are mostly not things we can fix
 
356
            # and so they just produce stipple; use the verbose reporter
 
357
            # to see them.
 
358
            if False:
 
359
                # show test and reason for skip
 
360
                self.pb.note('SKIP: %s\n    %s\n', 
 
361
                    self._shortened_test_description(test),
 
362
                    skip_excinfo[1])
 
363
            else:
 
364
                # since the class name was left behind in the still-visible
 
365
                # progress bar...
 
366
                self.pb.note('SKIP: %s', skip_excinfo[1])
 
367
 
 
368
    def report_cleaning_up(self):
 
369
        self.pb.update('cleaning up...')
 
370
 
 
371
    def finished(self):
 
372
        self.pb.finished()
 
373
 
 
374
 
 
375
class VerboseTestResult(ExtendedTestResult):
 
376
    """Produce long output, with one line per test run plus times"""
 
377
 
 
378
    def _ellipsize_to_right(self, a_string, final_width):
 
379
        """Truncate and pad a string, keeping the right hand side"""
 
380
        if len(a_string) > final_width:
 
381
            result = '...' + a_string[3-final_width:]
 
382
        else:
 
383
            result = a_string
 
384
        return result.ljust(final_width)
 
385
 
 
386
    def report_starting(self):
 
387
        self.stream.write('running %d tests...\n' % self.num_tests)
 
388
 
 
389
    def report_test_start(self, test):
 
390
        self.count += 1
 
391
        name = self._shortened_test_description(test)
 
392
        # width needs space for 6 char status, plus 1 for slash, plus 2 10-char
 
393
        # numbers, plus a trailing blank
 
394
        # when NUMBERED_DIRS: plus 5 chars on test number, plus 1 char on space
 
395
        if NUMBERED_DIRS:
 
396
            self.stream.write('%5d ' % self.count)
 
397
            self.stream.write(self._ellipsize_to_right(name,
 
398
                                osutils.terminal_width()-36))
 
399
        else:
 
400
            self.stream.write(self._ellipsize_to_right(name,
 
401
                                osutils.terminal_width()-30))
 
402
        self.stream.flush()
 
403
 
 
404
    def _error_summary(self, err):
 
405
        indent = ' ' * 4
 
406
        if NUMBERED_DIRS:
 
407
            indent += ' ' * 6
 
408
        return '%s%s' % (indent, err[1])
 
409
 
 
410
    def report_error(self, test, err):
 
411
        self.error_count += 1
 
412
        self.stream.writeln('ERROR %s\n%s'
 
413
                % (self._testTimeString(),
 
414
                   self._error_summary(err)))
 
415
 
 
416
    def report_failure(self, test, err):
 
417
        self.failure_count += 1
 
418
        self.stream.writeln(' FAIL %s\n%s'
 
419
                % (self._testTimeString(),
 
420
                   self._error_summary(err)))
 
421
 
 
422
    def report_success(self, test):
 
423
        self.stream.writeln('   OK %s' % self._testTimeString())
 
424
        for bench_called, stats in getattr(test, '_benchcalls', []):
 
425
            if NUMBERED_DIRS:
 
426
                self.stream.write(' ' * 6)
 
427
            self.stream.writeln('LSProf output for %s(%s, %s)' % bench_called)
 
428
            stats.pprint(file=self.stream)
 
429
        self.stream.flush()
 
430
 
 
431
    def report_skip(self, test, skip_excinfo):
 
432
        self.skip_count += 1
 
433
        self.stream.writeln(' SKIP %s\n%s'
 
434
                % (self._testTimeString(),
 
435
                   self._error_summary(skip_excinfo)))
 
436
 
269
437
 
270
438
class TextTestRunner(object):
271
439
    stop_on_failure = False
275
443
                 descriptions=0,
276
444
                 verbosity=1,
277
445
                 keep_output=False,
278
 
                 pb=None):
 
446
                 bench_history=None):
279
447
        self.stream = unittest._WritelnDecorator(stream)
280
448
        self.descriptions = descriptions
281
449
        self.verbosity = verbosity
282
450
        self.keep_output = keep_output
283
 
        self.pb = pb
284
 
 
285
 
    def _makeResult(self):
286
 
        result = _MyResult(self.stream,
287
 
                           self.descriptions,
288
 
                           self.verbosity,
289
 
                           pb=self.pb)
290
 
        result.stop_early = self.stop_on_failure
291
 
        return result
 
451
        self._bench_history = bench_history
292
452
 
293
453
    def run(self, test):
294
454
        "Run the given test case or test suite."
295
 
        result = self._makeResult()
296
455
        startTime = time.time()
297
 
        if self.pb is not None:
298
 
            self.pb.update('Running tests', 0, test.countTestCases())
 
456
        if self.verbosity == 1:
 
457
            result_class = TextTestResult
 
458
        elif self.verbosity >= 2:
 
459
            result_class = VerboseTestResult
 
460
        result = result_class(self.stream,
 
461
                              self.descriptions,
 
462
                              self.verbosity,
 
463
                              bench_history=self._bench_history,
 
464
                              num_tests=test.countTestCases(),
 
465
                              )
 
466
        result.stop_early = self.stop_on_failure
 
467
        result.report_starting()
299
468
        test.run(result)
300
469
        stopTime = time.time()
301
470
        timeTaken = stopTime - startTime
316
485
            self.stream.writeln(")")
317
486
        else:
318
487
            self.stream.writeln("OK")
319
 
        if self.pb is not None:
320
 
            self.pb.update('Cleaning up', 0, 1)
 
488
        if result.skip_count > 0:
 
489
            skipped = result.skip_count
 
490
            self.stream.writeln('%d test%s skipped' %
 
491
                                (skipped, skipped != 1 and "s" or ""))
 
492
        result.report_cleaning_up()
321
493
        # This is still a little bogus, 
322
494
        # but only a little. Folk not using our testrunner will
323
495
        # have to delete their temp directories themselves.
324
 
        test_root = TestCaseInTempDir.TEST_ROOT
 
496
        test_root = TestCaseWithMemoryTransport.TEST_ROOT
325
497
        if result.wasSuccessful() or not self.keep_output:
326
498
            if test_root is not None:
 
499
                # If LANG=C we probably have created some bogus paths
 
500
                # which rmtree(unicode) will fail to delete
 
501
                # so make sure we are using rmtree(str) to delete everything
 
502
                # except on win32, where rmtree(str) will fail
 
503
                # since it doesn't have the property of byte-stream paths
 
504
                # (they are either ascii or mbcs)
 
505
                if sys.platform == 'win32':
 
506
                    # make sure we are using the unicode win32 api
 
507
                    test_root = unicode(test_root)
 
508
                else:
 
509
                    test_root = test_root.encode(
 
510
                        sys.getfilesystemencoding())
 
511
                try:
327
512
                    osutils.rmtree(test_root)
 
513
                except OSError, e:
 
514
                    if sys.platform == 'win32' and e.errno == errno.EACCES:
 
515
                        print >>sys.stderr, ('Permission denied: '
 
516
                                             'unable to remove testing dir '
 
517
                                             '%s' % os.path.basename(test_root))
 
518
                    else:
 
519
                        raise
328
520
        else:
329
 
            if self.pb is not None:
330
 
                self.pb.note("Failed tests working directories are in '%s'\n",
331
 
                             test_root)
332
 
            else:
333
 
                self.stream.writeln(
334
 
                    "Failed tests working directories are in '%s'\n" %
335
 
                    test_root)
336
 
        TestCaseInTempDir.TEST_ROOT = None
337
 
        if self.pb is not None:
338
 
            self.pb.clear()
 
521
            note("Failed tests working directories are in '%s'\n", test_root)
 
522
        TestCaseWithMemoryTransport.TEST_ROOT = None
 
523
        result.finished()
339
524
        return result
340
525
 
341
526
 
354
539
 
355
540
class TestSkipped(Exception):
356
541
    """Indicates that a test was intentionally skipped, rather than failing."""
357
 
    # XXX: Not used yet
358
542
 
359
543
 
360
544
class CommandFailed(Exception):
361
545
    pass
362
546
 
 
547
 
 
548
class StringIOWrapper(object):
 
549
    """A wrapper around cStringIO which just adds an encoding attribute.
 
550
    
 
551
    Internally we can check sys.stdout to see what the output encoding
 
552
    should be. However, cStringIO has no encoding attribute that we can
 
553
    set. So we wrap it instead.
 
554
    """
 
555
    encoding='ascii'
 
556
    _cstring = None
 
557
 
 
558
    def __init__(self, s=None):
 
559
        if s is not None:
 
560
            self.__dict__['_cstring'] = StringIO(s)
 
561
        else:
 
562
            self.__dict__['_cstring'] = StringIO()
 
563
 
 
564
    def __getattr__(self, name, getattr=getattr):
 
565
        return getattr(self.__dict__['_cstring'], name)
 
566
 
 
567
    def __setattr__(self, name, val):
 
568
        if name == 'encoding':
 
569
            self.__dict__['encoding'] = val
 
570
        else:
 
571
            return setattr(self._cstring, name, val)
 
572
 
 
573
 
363
574
class TestCase(unittest.TestCase):
364
575
    """Base class for bzr unit tests.
365
576
    
383
594
 
384
595
    _log_file_name = None
385
596
    _log_contents = ''
 
597
    _keep_log_file = False
386
598
    # record lsprof data when performing benchmark calls.
387
599
    _gather_lsprof_in_benchmarks = False
388
600
 
394
606
        unittest.TestCase.setUp(self)
395
607
        self._cleanEnvironment()
396
608
        bzrlib.trace.disable_default_logging()
 
609
        self._silenceUI()
397
610
        self._startLogFile()
398
611
        self._benchcalls = []
399
612
        self._benchtime = None
 
613
        # prevent hooks affecting tests
 
614
        self._preserved_hooks = bzrlib.branch.Branch.hooks
 
615
        self.addCleanup(self._restoreHooks)
 
616
        # this list of hooks must be kept in sync with the defaults
 
617
        # in branch.py
 
618
        bzrlib.branch.Branch.hooks = bzrlib.branch.BranchHooks()
 
619
 
 
620
    def _silenceUI(self):
 
621
        """Turn off UI for duration of test"""
 
622
        # by default the UI is off; tests can turn it on if they want it.
 
623
        saved = bzrlib.ui.ui_factory
 
624
        def _restore():
 
625
            bzrlib.ui.ui_factory = saved
 
626
        bzrlib.ui.ui_factory = bzrlib.ui.SilentUIFactory()
 
627
        self.addCleanup(_restore)
400
628
 
401
629
    def _ndiff_strings(self, a, b):
402
630
        """Return ndiff between two strings containing lines.
413
641
                                  charjunk=lambda x: False)
414
642
        return ''.join(difflines)
415
643
 
 
644
    def assertEqual(self, a, b, message=''):
 
645
        if a == b:
 
646
            return
 
647
        if message:
 
648
            message += '\n'
 
649
        raise AssertionError("%snot equal:\na = %s\nb = %s\n"
 
650
            % (message,
 
651
               pformat(a, indent=4), pformat(b, indent=4)))
 
652
 
 
653
    assertEquals = assertEqual
 
654
 
416
655
    def assertEqualDiff(self, a, b, message=None):
417
656
        """Assert two texts are equal, if not raise an exception.
418
657
        
443
682
    def assertContainsRe(self, haystack, needle_re):
444
683
        """Assert that a contains something matching a regular expression."""
445
684
        if not re.search(needle_re, haystack):
446
 
            raise AssertionError('pattern "%s" not found in "%s"'
 
685
            raise AssertionError('pattern "%r" not found in "%r"'
 
686
                    % (needle_re, haystack))
 
687
 
 
688
    def assertNotContainsRe(self, haystack, needle_re):
 
689
        """Assert that a does not match a regular expression"""
 
690
        if re.search(needle_re, haystack):
 
691
            raise AssertionError('pattern "%s" found in "%s"'
447
692
                    % (needle_re, haystack))
448
693
 
449
694
    def assertSubset(self, sublist, superlist):
456
701
            raise AssertionError("value(s) %r not present in container %r" % 
457
702
                                 (missing, superlist))
458
703
 
459
 
    def assertIs(self, left, right):
 
704
    def assertListRaises(self, excClass, func, *args, **kwargs):
 
705
        """Fail unless excClass is raised when the iterator from func is used.
 
706
        
 
707
        Many functions can return generators this makes sure
 
708
        to wrap them in a list() call to make sure the whole generator
 
709
        is run, and that the proper exception is raised.
 
710
        """
 
711
        try:
 
712
            list(func(*args, **kwargs))
 
713
        except excClass:
 
714
            return
 
715
        else:
 
716
            if getattr(excClass,'__name__', None) is not None:
 
717
                excName = excClass.__name__
 
718
            else:
 
719
                excName = str(excClass)
 
720
            raise self.failureException, "%s not raised" % excName
 
721
 
 
722
    def assertIs(self, left, right, message=None):
460
723
        if not (left is right):
461
 
            raise AssertionError("%r is not %r." % (left, right))
 
724
            if message is not None:
 
725
                raise AssertionError(message)
 
726
            else:
 
727
                raise AssertionError("%r is not %r." % (left, right))
 
728
 
 
729
    def assertIsNot(self, left, right, message=None):
 
730
        if (left is right):
 
731
            if message is not None:
 
732
                raise AssertionError(message)
 
733
            else:
 
734
                raise AssertionError("%r is %r." % (left, right))
462
735
 
463
736
    def assertTransportMode(self, transport, path, mode):
464
737
        """Fail if a path does not have mode mode.
478
751
            self.fail("%r is an instance of %s rather than %s" % (
479
752
                obj, obj.__class__, kls))
480
753
 
 
754
    def _capture_warnings(self, a_callable, *args, **kwargs):
 
755
        """A helper for callDeprecated and applyDeprecated.
 
756
 
 
757
        :param a_callable: A callable to call.
 
758
        :param args: The positional arguments for the callable
 
759
        :param kwargs: The keyword arguments for the callable
 
760
        :return: A tuple (warnings, result). result is the result of calling
 
761
            a_callable(*args, **kwargs).
 
762
        """
 
763
        local_warnings = []
 
764
        def capture_warnings(msg, cls=None, stacklevel=None):
 
765
            # we've hooked into a deprecation specific callpath,
 
766
            # only deprecations should getting sent via it.
 
767
            self.assertEqual(cls, DeprecationWarning)
 
768
            local_warnings.append(msg)
 
769
        original_warning_method = symbol_versioning.warn
 
770
        symbol_versioning.set_warning_method(capture_warnings)
 
771
        try:
 
772
            result = a_callable(*args, **kwargs)
 
773
        finally:
 
774
            symbol_versioning.set_warning_method(original_warning_method)
 
775
        return (local_warnings, result)
 
776
 
 
777
    def applyDeprecated(self, deprecation_format, a_callable, *args, **kwargs):
 
778
        """Call a deprecated callable without warning the user.
 
779
 
 
780
        :param deprecation_format: The deprecation format that the callable
 
781
            should have been deprecated with. This is the same type as the 
 
782
            parameter to deprecated_method/deprecated_function. If the 
 
783
            callable is not deprecated with this format, an assertion error
 
784
            will be raised.
 
785
        :param a_callable: A callable to call. This may be a bound method or
 
786
            a regular function. It will be called with *args and **kwargs.
 
787
        :param args: The positional arguments for the callable
 
788
        :param kwargs: The keyword arguments for the callable
 
789
        :return: The result of a_callable(*args, **kwargs)
 
790
        """
 
791
        call_warnings, result = self._capture_warnings(a_callable,
 
792
            *args, **kwargs)
 
793
        expected_first_warning = symbol_versioning.deprecation_string(
 
794
            a_callable, deprecation_format)
 
795
        if len(call_warnings) == 0:
 
796
            self.fail("No deprecation warning generated by call to %s" %
 
797
                a_callable)
 
798
        self.assertEqual(expected_first_warning, call_warnings[0])
 
799
        return result
 
800
 
 
801
    def callDeprecated(self, expected, callable, *args, **kwargs):
 
802
        """Assert that a callable is deprecated in a particular way.
 
803
 
 
804
        This is a very precise test for unusual requirements. The 
 
805
        applyDeprecated helper function is probably more suited for most tests
 
806
        as it allows you to simply specify the deprecation format being used
 
807
        and will ensure that that is issued for the function being called.
 
808
 
 
809
        :param expected: a list of the deprecation warnings expected, in order
 
810
        :param callable: The callable to call
 
811
        :param args: The positional arguments for the callable
 
812
        :param kwargs: The keyword arguments for the callable
 
813
        """
 
814
        call_warnings, result = self._capture_warnings(callable,
 
815
            *args, **kwargs)
 
816
        self.assertEqual(expected, call_warnings)
 
817
        return result
 
818
 
481
819
    def _startLogFile(self):
482
820
        """Send bzr and test log messages to a temporary file.
483
821
 
484
822
        The file is removed as the test is torn down.
485
823
        """
486
824
        fileno, name = tempfile.mkstemp(suffix='.log', prefix='testbzr')
487
 
        encoder, decoder, stream_reader, stream_writer = codecs.lookup('UTF-8')
488
 
        self._log_file = stream_writer(os.fdopen(fileno, 'w+'))
 
825
        self._log_file = os.fdopen(fileno, 'w+')
489
826
        self._log_nonce = bzrlib.trace.enable_test_log(self._log_file)
490
827
        self._log_file_name = name
491
828
        self.addCleanup(self._finishLogFile)
493
830
    def _finishLogFile(self):
494
831
        """Finished with the log file.
495
832
 
496
 
        Read contents into memory, close, and delete.
 
833
        Close the file and delete it, unless setKeepLogfile was called.
497
834
        """
 
835
        if self._log_file is None:
 
836
            return
498
837
        bzrlib.trace.disable_test_log(self._log_nonce)
499
 
        self._log_file.seek(0)
500
 
        self._log_contents = self._log_file.read()
501
838
        self._log_file.close()
502
 
        os.remove(self._log_file_name)
503
 
        self._log_file = self._log_file_name = None
 
839
        self._log_file = None
 
840
        if not self._keep_log_file:
 
841
            os.remove(self._log_file_name)
 
842
            self._log_file_name = None
 
843
 
 
844
    def setKeepLogfile(self):
 
845
        """Make the logfile not be deleted when _finishLogFile is called."""
 
846
        self._keep_log_file = True
504
847
 
505
848
    def addCleanup(self, callable):
506
849
        """Arrange to run a callable when this case is torn down.
515
858
 
516
859
    def _cleanEnvironment(self):
517
860
        new_env = {
 
861
            'BZR_HOME': None, # Don't inherit BZR_HOME to all the tests.
518
862
            'HOME': os.getcwd(),
519
 
            'APPDATA': os.getcwd(),
520
 
            'BZREMAIL': None,
 
863
            'APPDATA': None,  # bzr now use Win32 API and don't rely on APPDATA
 
864
            'BZR_EMAIL': None,
 
865
            'BZREMAIL': None, # may still be present in the environment
521
866
            'EMAIL': None,
 
867
            'BZR_PROGRESS_BAR': None,
 
868
            # Proxies
 
869
            'http_proxy': None,
 
870
            'HTTP_PROXY': None,
 
871
            'https_proxy': None,
 
872
            'HTTPS_PROXY': None,
 
873
            'no_proxy': None,
 
874
            'NO_PROXY': None,
 
875
            'all_proxy': None,
 
876
            'ALL_PROXY': None,
 
877
            # Nobody cares about these ones AFAIK. So far at
 
878
            # least. If you do (care), please update this comment
 
879
            # -- vila 20061212
 
880
            'ftp_proxy': None,
 
881
            'FTP_PROXY': None,
522
882
        }
523
883
        self.__old_env = {}
524
884
        self.addCleanup(self._restoreEnvironment)
525
885
        for name, value in new_env.iteritems():
526
886
            self._captureVar(name, value)
527
887
 
528
 
 
529
888
    def _captureVar(self, name, newvalue):
530
 
        """Set an environment variable, preparing it to be reset when finished."""
531
 
        self.__old_env[name] = os.environ.get(name, None)
532
 
        if newvalue is None:
533
 
            if name in os.environ:
534
 
                del os.environ[name]
535
 
        else:
536
 
            os.environ[name] = newvalue
537
 
 
538
 
    @staticmethod
539
 
    def _restoreVar(name, value):
540
 
        if value is None:
541
 
            if name in os.environ:
542
 
                del os.environ[name]
543
 
        else:
544
 
            os.environ[name] = value
 
889
        """Set an environment variable, and reset it when finished."""
 
890
        self.__old_env[name] = osutils.set_or_unset_env(name, newvalue)
545
891
 
546
892
    def _restoreEnvironment(self):
547
893
        for name, value in self.__old_env.iteritems():
548
 
            self._restoreVar(name, value)
 
894
            osutils.set_or_unset_env(name, value)
 
895
 
 
896
    def _restoreHooks(self):
 
897
        bzrlib.branch.Branch.hooks = self._preserved_hooks
549
898
 
550
899
    def tearDown(self):
551
900
        self._runCleanups()
586
935
    def log(self, *args):
587
936
        mutter(*args)
588
937
 
589
 
    def _get_log(self):
590
 
        """Return as a string the log for this test"""
591
 
        if self._log_file_name:
592
 
            return open(self._log_file_name).read()
593
 
        else:
 
938
    def _get_log(self, keep_log_file=False):
 
939
        """Return as a string the log for this test. If the file is still
 
940
        on disk and keep_log_file=False, delete the log file and store the
 
941
        content in self._log_contents."""
 
942
        # flush the log file, to get all content
 
943
        import bzrlib.trace
 
944
        bzrlib.trace._trace_file.flush()
 
945
        if self._log_contents:
594
946
            return self._log_contents
595
 
        # TODO: Delete the log after it's been read in
 
947
        if self._log_file_name is not None:
 
948
            logfile = open(self._log_file_name)
 
949
            try:
 
950
                log_contents = logfile.read()
 
951
            finally:
 
952
                logfile.close()
 
953
            if not keep_log_file:
 
954
                self._log_contents = log_contents
 
955
                try:
 
956
                    os.remove(self._log_file_name)
 
957
                except OSError, e:
 
958
                    if sys.platform == 'win32' and e.errno == errno.EACCES:
 
959
                        print >>sys.stderr, ('Unable to delete log file '
 
960
                                             ' %r' % self._log_file_name)
 
961
                    else:
 
962
                        raise
 
963
            return log_contents
 
964
        else:
 
965
            return "DELETED log file to reduce memory footprint"
596
966
 
597
967
    def capture(self, cmd, retcode=0):
598
968
        """Shortcut that splits cmd into words, runs, and returns stdout"""
599
969
        return self.run_bzr_captured(cmd.split(), retcode=retcode)[0]
600
970
 
601
 
    def run_bzr_captured(self, argv, retcode=0, stdin=None):
 
971
    def run_bzr_captured(self, argv, retcode=0, encoding=None, stdin=None,
 
972
                         working_dir=None):
602
973
        """Invoke bzr and return (stdout, stderr).
603
974
 
604
975
        Useful for code that wants to check the contents of the
615
986
        errors, and with logging set to something approximating the
616
987
        default, so that error reporting can be checked.
617
988
 
618
 
        argv -- arguments to invoke bzr
619
 
        retcode -- expected return code, or None for don't-care.
 
989
        :param argv: arguments to invoke bzr
 
990
        :param retcode: expected return code, or None for don't-care.
 
991
        :param encoding: encoding for sys.stdout and sys.stderr
620
992
        :param stdin: A string to be used as stdin for the command.
 
993
        :param working_dir: Change to this directory before running
621
994
        """
 
995
        if encoding is None:
 
996
            encoding = bzrlib.user_encoding
622
997
        if stdin is not None:
623
998
            stdin = StringIO(stdin)
624
 
        stdout = StringIO()
625
 
        stderr = StringIO()
626
 
        self.log('run bzr: %s', ' '.join(argv))
 
999
        stdout = StringIOWrapper()
 
1000
        stderr = StringIOWrapper()
 
1001
        stdout.encoding = encoding
 
1002
        stderr.encoding = encoding
 
1003
 
 
1004
        self.log('run bzr: %r', argv)
627
1005
        # FIXME: don't call into logging here
628
1006
        handler = logging.StreamHandler(stderr)
629
 
        handler.setFormatter(bzrlib.trace.QuietFormatter())
630
1007
        handler.setLevel(logging.INFO)
631
1008
        logger = logging.getLogger('')
632
1009
        logger.addHandler(handler)
635
1012
            stdout=stdout,
636
1013
            stderr=stderr)
637
1014
        bzrlib.ui.ui_factory.stdin = stdin
 
1015
 
 
1016
        cwd = None
 
1017
        if working_dir is not None:
 
1018
            cwd = osutils.getcwd()
 
1019
            os.chdir(working_dir)
 
1020
 
638
1021
        try:
639
 
            result = self.apply_redirected(stdin, stdout, stderr,
640
 
                                           bzrlib.commands.run_bzr_catch_errors,
641
 
                                           argv)
 
1022
            saved_debug_flags = frozenset(debug.debug_flags)
 
1023
            debug.debug_flags.clear()
 
1024
            try:
 
1025
                result = self.apply_redirected(stdin, stdout, stderr,
 
1026
                                               bzrlib.commands.run_bzr_catch_errors,
 
1027
                                               argv)
 
1028
            finally:
 
1029
                debug.debug_flags.update(saved_debug_flags)
642
1030
        finally:
643
1031
            logger.removeHandler(handler)
644
1032
            bzrlib.ui.ui_factory = old_ui_factory
 
1033
            if cwd is not None:
 
1034
                os.chdir(cwd)
 
1035
 
645
1036
        out = stdout.getvalue()
646
1037
        err = stderr.getvalue()
647
1038
        if out:
648
 
            self.log('output:\n%s', out)
 
1039
            self.log('output:\n%r', out)
649
1040
        if err:
650
 
            self.log('errors:\n%s', err)
 
1041
            self.log('errors:\n%r', err)
651
1042
        if retcode is not None:
652
 
            self.assertEquals(result, retcode)
 
1043
            self.assertEquals(retcode, result)
653
1044
        return out, err
654
1045
 
655
1046
    def run_bzr(self, *args, **kwargs):
663
1054
        where it may be useful for debugging.  See also run_captured.
664
1055
 
665
1056
        :param stdin: A string to be used as stdin for the command.
 
1057
        :param retcode: The status code the command should return
 
1058
        :param working_dir: The directory to run the command in
666
1059
        """
667
1060
        retcode = kwargs.pop('retcode', 0)
 
1061
        encoding = kwargs.pop('encoding', None)
668
1062
        stdin = kwargs.pop('stdin', None)
669
 
        return self.run_bzr_captured(args, retcode, stdin)
 
1063
        working_dir = kwargs.pop('working_dir', None)
 
1064
        return self.run_bzr_captured(args, retcode=retcode, encoding=encoding,
 
1065
                                     stdin=stdin, working_dir=working_dir)
 
1066
 
 
1067
    def run_bzr_decode(self, *args, **kwargs):
 
1068
        if 'encoding' in kwargs:
 
1069
            encoding = kwargs['encoding']
 
1070
        else:
 
1071
            encoding = bzrlib.user_encoding
 
1072
        return self.run_bzr(*args, **kwargs)[0].decode(encoding)
 
1073
 
 
1074
    def run_bzr_error(self, error_regexes, *args, **kwargs):
 
1075
        """Run bzr, and check that stderr contains the supplied regexes
 
1076
        
 
1077
        :param error_regexes: Sequence of regular expressions which 
 
1078
            must each be found in the error output. The relative ordering
 
1079
            is not enforced.
 
1080
        :param args: command-line arguments for bzr
 
1081
        :param kwargs: Keyword arguments which are interpreted by run_bzr
 
1082
            This function changes the default value of retcode to be 3,
 
1083
            since in most cases this is run when you expect bzr to fail.
 
1084
        :return: (out, err) The actual output of running the command (in case you
 
1085
                 want to do more inspection)
 
1086
 
 
1087
        Examples of use:
 
1088
            # Make sure that commit is failing because there is nothing to do
 
1089
            self.run_bzr_error(['no changes to commit'],
 
1090
                               'commit', '-m', 'my commit comment')
 
1091
            # Make sure --strict is handling an unknown file, rather than
 
1092
            # giving us the 'nothing to do' error
 
1093
            self.build_tree(['unknown'])
 
1094
            self.run_bzr_error(['Commit refused because there are unknown files'],
 
1095
                               'commit', '--strict', '-m', 'my commit comment')
 
1096
        """
 
1097
        kwargs.setdefault('retcode', 3)
 
1098
        out, err = self.run_bzr(*args, **kwargs)
 
1099
        for regex in error_regexes:
 
1100
            self.assertContainsRe(err, regex)
 
1101
        return out, err
 
1102
 
 
1103
    def run_bzr_subprocess(self, *args, **kwargs):
 
1104
        """Run bzr in a subprocess for testing.
 
1105
 
 
1106
        This starts a new Python interpreter and runs bzr in there. 
 
1107
        This should only be used for tests that have a justifiable need for
 
1108
        this isolation: e.g. they are testing startup time, or signal
 
1109
        handling, or early startup code, etc.  Subprocess code can't be 
 
1110
        profiled or debugged so easily.
 
1111
 
 
1112
        :param retcode: The status code that is expected.  Defaults to 0.  If
 
1113
            None is supplied, the status code is not checked.
 
1114
        :param env_changes: A dictionary which lists changes to environment
 
1115
            variables. A value of None will unset the env variable.
 
1116
            The values must be strings. The change will only occur in the
 
1117
            child, so you don't need to fix the environment after running.
 
1118
        :param universal_newlines: Convert CRLF => LF
 
1119
        :param allow_plugins: By default the subprocess is run with
 
1120
            --no-plugins to ensure test reproducibility. Also, it is possible
 
1121
            for system-wide plugins to create unexpected output on stderr,
 
1122
            which can cause unnecessary test failures.
 
1123
        """
 
1124
        env_changes = kwargs.get('env_changes', {})
 
1125
        working_dir = kwargs.get('working_dir', None)
 
1126
        allow_plugins = kwargs.get('allow_plugins', False)
 
1127
        process = self.start_bzr_subprocess(args, env_changes=env_changes,
 
1128
                                            working_dir=working_dir,
 
1129
                                            allow_plugins=allow_plugins)
 
1130
        # We distinguish between retcode=None and retcode not passed.
 
1131
        supplied_retcode = kwargs.get('retcode', 0)
 
1132
        return self.finish_bzr_subprocess(process, retcode=supplied_retcode,
 
1133
            universal_newlines=kwargs.get('universal_newlines', False),
 
1134
            process_args=args)
 
1135
 
 
1136
    def start_bzr_subprocess(self, process_args, env_changes=None,
 
1137
                             skip_if_plan_to_signal=False,
 
1138
                             working_dir=None,
 
1139
                             allow_plugins=False):
 
1140
        """Start bzr in a subprocess for testing.
 
1141
 
 
1142
        This starts a new Python interpreter and runs bzr in there.
 
1143
        This should only be used for tests that have a justifiable need for
 
1144
        this isolation: e.g. they are testing startup time, or signal
 
1145
        handling, or early startup code, etc.  Subprocess code can't be
 
1146
        profiled or debugged so easily.
 
1147
 
 
1148
        :param process_args: a list of arguments to pass to the bzr executable,
 
1149
            for example `['--version']`.
 
1150
        :param env_changes: A dictionary which lists changes to environment
 
1151
            variables. A value of None will unset the env variable.
 
1152
            The values must be strings. The change will only occur in the
 
1153
            child, so you don't need to fix the environment after running.
 
1154
        :param skip_if_plan_to_signal: raise TestSkipped when true and os.kill
 
1155
            is not available.
 
1156
        :param allow_plugins: If False (default) pass --no-plugins to bzr.
 
1157
 
 
1158
        :returns: Popen object for the started process.
 
1159
        """
 
1160
        if skip_if_plan_to_signal:
 
1161
            if not getattr(os, 'kill', None):
 
1162
                raise TestSkipped("os.kill not available.")
 
1163
 
 
1164
        if env_changes is None:
 
1165
            env_changes = {}
 
1166
        old_env = {}
 
1167
 
 
1168
        def cleanup_environment():
 
1169
            for env_var, value in env_changes.iteritems():
 
1170
                old_env[env_var] = osutils.set_or_unset_env(env_var, value)
 
1171
 
 
1172
        def restore_environment():
 
1173
            for env_var, value in old_env.iteritems():
 
1174
                osutils.set_or_unset_env(env_var, value)
 
1175
 
 
1176
        bzr_path = self.get_bzr_path()
 
1177
 
 
1178
        cwd = None
 
1179
        if working_dir is not None:
 
1180
            cwd = osutils.getcwd()
 
1181
            os.chdir(working_dir)
 
1182
 
 
1183
        try:
 
1184
            # win32 subprocess doesn't support preexec_fn
 
1185
            # so we will avoid using it on all platforms, just to
 
1186
            # make sure the code path is used, and we don't break on win32
 
1187
            cleanup_environment()
 
1188
            command = [sys.executable, bzr_path]
 
1189
            if not allow_plugins:
 
1190
                command.append('--no-plugins')
 
1191
            command.extend(process_args)
 
1192
            process = self._popen(command, stdin=PIPE, stdout=PIPE, stderr=PIPE)
 
1193
        finally:
 
1194
            restore_environment()
 
1195
            if cwd is not None:
 
1196
                os.chdir(cwd)
 
1197
 
 
1198
        return process
 
1199
 
 
1200
    def _popen(self, *args, **kwargs):
 
1201
        """Place a call to Popen.
 
1202
 
 
1203
        Allows tests to override this method to intercept the calls made to
 
1204
        Popen for introspection.
 
1205
        """
 
1206
        return Popen(*args, **kwargs)
 
1207
 
 
1208
    def get_bzr_path(self):
 
1209
        """Return the path of the 'bzr' executable for this test suite."""
 
1210
        bzr_path = os.path.dirname(os.path.dirname(bzrlib.__file__))+'/bzr'
 
1211
        if not os.path.isfile(bzr_path):
 
1212
            # We are probably installed. Assume sys.argv is the right file
 
1213
            bzr_path = sys.argv[0]
 
1214
        return bzr_path
 
1215
 
 
1216
    def finish_bzr_subprocess(self, process, retcode=0, send_signal=None,
 
1217
                              universal_newlines=False, process_args=None):
 
1218
        """Finish the execution of process.
 
1219
 
 
1220
        :param process: the Popen object returned from start_bzr_subprocess.
 
1221
        :param retcode: The status code that is expected.  Defaults to 0.  If
 
1222
            None is supplied, the status code is not checked.
 
1223
        :param send_signal: an optional signal to send to the process.
 
1224
        :param universal_newlines: Convert CRLF => LF
 
1225
        :returns: (stdout, stderr)
 
1226
        """
 
1227
        if send_signal is not None:
 
1228
            os.kill(process.pid, send_signal)
 
1229
        out, err = process.communicate()
 
1230
 
 
1231
        if universal_newlines:
 
1232
            out = out.replace('\r\n', '\n')
 
1233
            err = err.replace('\r\n', '\n')
 
1234
 
 
1235
        if retcode is not None and retcode != process.returncode:
 
1236
            if process_args is None:
 
1237
                process_args = "(unknown args)"
 
1238
            mutter('Output of bzr %s:\n%s', process_args, out)
 
1239
            mutter('Error for bzr %s:\n%s', process_args, err)
 
1240
            self.fail('Command bzr %s failed with retcode %s != %s'
 
1241
                      % (process_args, retcode, process.returncode))
 
1242
        return [out, err]
670
1243
 
671
1244
    def check_inventory_shape(self, inv, shape):
672
1245
        """Compare an inventory to a list of expected names.
720
1293
            sys.stderr = real_stderr
721
1294
            sys.stdin = real_stdin
722
1295
 
 
1296
    @symbol_versioning.deprecated_method(symbol_versioning.zero_eleven)
723
1297
    def merge(self, branch_from, wt_to):
724
1298
        """A helper for tests to do a ui-less merge.
725
1299
 
731
1305
        base_rev = common_ancestor(branch_from.last_revision(),
732
1306
                                   wt_to.branch.last_revision(),
733
1307
                                   wt_to.branch.repository)
734
 
        merge_inner(wt_to.branch, branch_from.basis_tree(), 
 
1308
        merge_inner(wt_to.branch, branch_from.basis_tree(),
735
1309
                    wt_to.branch.repository.revision_tree(base_rev),
736
1310
                    this_tree=wt_to)
737
 
        wt_to.add_pending_merge(branch_from.last_revision())
 
1311
        wt_to.add_parent_tree_id(branch_from.last_revision())
738
1312
 
739
1313
 
740
1314
BzrTestBase = TestCase
741
1315
 
 
1316
 
 
1317
class TestCaseWithMemoryTransport(TestCase):
 
1318
    """Common test class for tests that do not need disk resources.
 
1319
 
 
1320
    Tests that need disk resources should derive from TestCaseWithTransport.
 
1321
 
 
1322
    TestCaseWithMemoryTransport sets the TEST_ROOT variable for all bzr tests.
 
1323
 
 
1324
    For TestCaseWithMemoryTransport the test_home_dir is set to the name of
 
1325
    a directory which does not exist. This serves to help ensure test isolation
 
1326
    is preserved. test_dir is set to the TEST_ROOT, as is cwd, because they
 
1327
    must exist. However, TestCaseWithMemoryTransport does not offer local
 
1328
    file defaults for the transport in tests, nor does it obey the command line
 
1329
    override, so tests that accidentally write to the common directory should
 
1330
    be rare.
 
1331
    """
 
1332
 
 
1333
    TEST_ROOT = None
 
1334
    _TEST_NAME = 'test'
 
1335
 
 
1336
 
 
1337
    def __init__(self, methodName='runTest'):
 
1338
        # allow test parameterisation after test construction and before test
 
1339
        # execution. Variables that the parameteriser sets need to be 
 
1340
        # ones that are not set by setUp, or setUp will trash them.
 
1341
        super(TestCaseWithMemoryTransport, self).__init__(methodName)
 
1342
        self.transport_server = default_transport
 
1343
        self.transport_readonly_server = None
 
1344
 
 
1345
    def get_transport(self):
 
1346
        """Return a writeable transport for the test scratch space"""
 
1347
        t = get_transport(self.get_url())
 
1348
        self.assertFalse(t.is_readonly())
 
1349
        return t
 
1350
 
 
1351
    def get_readonly_transport(self):
 
1352
        """Return a readonly transport for the test scratch space
 
1353
        
 
1354
        This can be used to test that operations which should only need
 
1355
        readonly access in fact do not try to write.
 
1356
        """
 
1357
        t = get_transport(self.get_readonly_url())
 
1358
        self.assertTrue(t.is_readonly())
 
1359
        return t
 
1360
 
 
1361
    def create_transport_readonly_server(self):
 
1362
        """Create a transport server from class defined at init.
 
1363
 
 
1364
        This is mostly a hook for daughter classes.
 
1365
        """
 
1366
        return self.transport_readonly_server()
 
1367
 
 
1368
    def get_readonly_server(self):
 
1369
        """Get the server instance for the readonly transport
 
1370
 
 
1371
        This is useful for some tests with specific servers to do diagnostics.
 
1372
        """
 
1373
        if self.__readonly_server is None:
 
1374
            if self.transport_readonly_server is None:
 
1375
                # readonly decorator requested
 
1376
                # bring up the server
 
1377
                self.get_url()
 
1378
                self.__readonly_server = ReadonlyServer()
 
1379
                self.__readonly_server.setUp(self.__server)
 
1380
            else:
 
1381
                self.__readonly_server = self.create_transport_readonly_server()
 
1382
                self.__readonly_server.setUp()
 
1383
            self.addCleanup(self.__readonly_server.tearDown)
 
1384
        return self.__readonly_server
 
1385
 
 
1386
    def get_readonly_url(self, relpath=None):
 
1387
        """Get a URL for the readonly transport.
 
1388
 
 
1389
        This will either be backed by '.' or a decorator to the transport 
 
1390
        used by self.get_url()
 
1391
        relpath provides for clients to get a path relative to the base url.
 
1392
        These should only be downwards relative, not upwards.
 
1393
        """
 
1394
        base = self.get_readonly_server().get_url()
 
1395
        if relpath is not None:
 
1396
            if not base.endswith('/'):
 
1397
                base = base + '/'
 
1398
            base = base + relpath
 
1399
        return base
 
1400
 
 
1401
    def get_server(self):
 
1402
        """Get the read/write server instance.
 
1403
 
 
1404
        This is useful for some tests with specific servers that need
 
1405
        diagnostics.
 
1406
 
 
1407
        For TestCaseWithMemoryTransport this is always a MemoryServer, and there
 
1408
        is no means to override it.
 
1409
        """
 
1410
        if self.__server is None:
 
1411
            self.__server = MemoryServer()
 
1412
            self.__server.setUp()
 
1413
            self.addCleanup(self.__server.tearDown)
 
1414
        return self.__server
 
1415
 
 
1416
    def get_url(self, relpath=None):
 
1417
        """Get a URL (or maybe a path) for the readwrite transport.
 
1418
 
 
1419
        This will either be backed by '.' or to an equivalent non-file based
 
1420
        facility.
 
1421
        relpath provides for clients to get a path relative to the base url.
 
1422
        These should only be downwards relative, not upwards.
 
1423
        """
 
1424
        base = self.get_server().get_url()
 
1425
        if relpath is not None and relpath != '.':
 
1426
            if not base.endswith('/'):
 
1427
                base = base + '/'
 
1428
            # XXX: Really base should be a url; we did after all call
 
1429
            # get_url()!  But sometimes it's just a path (from
 
1430
            # LocalAbspathServer), and it'd be wrong to append urlescaped data
 
1431
            # to a non-escaped local path.
 
1432
            if base.startswith('./') or base.startswith('/'):
 
1433
                base += relpath
 
1434
            else:
 
1435
                base += urlutils.escape(relpath)
 
1436
        return base
 
1437
 
 
1438
    def _make_test_root(self):
 
1439
        if TestCaseWithMemoryTransport.TEST_ROOT is not None:
 
1440
            return
 
1441
        i = 0
 
1442
        while True:
 
1443
            root = u'test%04d.tmp' % i
 
1444
            try:
 
1445
                os.mkdir(root)
 
1446
            except OSError, e:
 
1447
                if e.errno == errno.EEXIST:
 
1448
                    i += 1
 
1449
                    continue
 
1450
                else:
 
1451
                    raise
 
1452
            # successfully created
 
1453
            TestCaseWithMemoryTransport.TEST_ROOT = osutils.abspath(root)
 
1454
            break
 
1455
        # make a fake bzr directory there to prevent any tests propagating
 
1456
        # up onto the source directory's real branch
 
1457
        bzrdir.BzrDir.create_standalone_workingtree(
 
1458
            TestCaseWithMemoryTransport.TEST_ROOT)
 
1459
 
 
1460
    def makeAndChdirToTestDir(self):
 
1461
        """Create a temporary directories for this one test.
 
1462
        
 
1463
        This must set self.test_home_dir and self.test_dir and chdir to
 
1464
        self.test_dir.
 
1465
        
 
1466
        For TestCaseWithMemoryTransport we chdir to the TEST_ROOT for this test.
 
1467
        """
 
1468
        os.chdir(TestCaseWithMemoryTransport.TEST_ROOT)
 
1469
        self.test_dir = TestCaseWithMemoryTransport.TEST_ROOT
 
1470
        self.test_home_dir = self.test_dir + "/MemoryTransportMissingHomeDir"
 
1471
        
 
1472
    def make_branch(self, relpath, format=None):
 
1473
        """Create a branch on the transport at relpath."""
 
1474
        repo = self.make_repository(relpath, format=format)
 
1475
        return repo.bzrdir.create_branch()
 
1476
 
 
1477
    def make_bzrdir(self, relpath, format=None):
 
1478
        try:
 
1479
            # might be a relative or absolute path
 
1480
            maybe_a_url = self.get_url(relpath)
 
1481
            segments = maybe_a_url.rsplit('/', 1)
 
1482
            t = get_transport(maybe_a_url)
 
1483
            if len(segments) > 1 and segments[-1] not in ('', '.'):
 
1484
                try:
 
1485
                    t.mkdir('.')
 
1486
                except errors.FileExists:
 
1487
                    pass
 
1488
            if format is None:
 
1489
                format = 'default'
 
1490
            if isinstance(format, basestring):
 
1491
                format = bzrdir.format_registry.make_bzrdir(format)
 
1492
            return format.initialize_on_transport(t)
 
1493
        except errors.UninitializableFormat:
 
1494
            raise TestSkipped("Format %s is not initializable." % format)
 
1495
 
 
1496
    def make_repository(self, relpath, shared=False, format=None):
 
1497
        """Create a repository on our default transport at relpath."""
 
1498
        made_control = self.make_bzrdir(relpath, format=format)
 
1499
        return made_control.create_repository(shared=shared)
 
1500
 
 
1501
    def make_branch_and_memory_tree(self, relpath, format=None):
 
1502
        """Create a branch on the default transport and a MemoryTree for it."""
 
1503
        b = self.make_branch(relpath, format=format)
 
1504
        return memorytree.MemoryTree.create_on_branch(b)
 
1505
 
 
1506
    def overrideEnvironmentForTesting(self):
 
1507
        os.environ['HOME'] = self.test_home_dir
 
1508
        os.environ['BZR_HOME'] = self.test_home_dir
 
1509
        
 
1510
    def setUp(self):
 
1511
        super(TestCaseWithMemoryTransport, self).setUp()
 
1512
        self._make_test_root()
 
1513
        _currentdir = os.getcwdu()
 
1514
        def _leaveDirectory():
 
1515
            os.chdir(_currentdir)
 
1516
        self.addCleanup(_leaveDirectory)
 
1517
        self.makeAndChdirToTestDir()
 
1518
        self.overrideEnvironmentForTesting()
 
1519
        self.__readonly_server = None
 
1520
        self.__server = None
 
1521
 
742
1522
     
743
 
class TestCaseInTempDir(TestCase):
 
1523
class TestCaseInTempDir(TestCaseWithMemoryTransport):
744
1524
    """Derived class that runs a test within a temporary directory.
745
1525
 
746
1526
    This is useful for tests that need to create a branch, etc.
753
1533
    InTempDir is an old alias for FunctionalTestCase.
754
1534
    """
755
1535
 
756
 
    TEST_ROOT = None
757
 
    _TEST_NAME = 'test'
758
1536
    OVERRIDE_PYTHON = 'python'
759
1537
 
760
1538
    def check_file_contents(self, filename, expect):
765
1543
            self.log("actually: %r" % contents)
766
1544
            self.fail("contents of %s not as expected" % filename)
767
1545
 
768
 
    def _make_test_root(self):
769
 
        if TestCaseInTempDir.TEST_ROOT is not None:
 
1546
    def makeAndChdirToTestDir(self):
 
1547
        """See TestCaseWithMemoryTransport.makeAndChdirToTestDir().
 
1548
        
 
1549
        For TestCaseInTempDir we create a temporary directory based on the test
 
1550
        name and then create two subdirs - test and home under it.
 
1551
        """
 
1552
        if NUMBERED_DIRS:       # strongly recommended on Windows
 
1553
                                # due the path length limitation (260 chars)
 
1554
            candidate_dir = '%s/%dK/%05d' % (self.TEST_ROOT,
 
1555
                                             int(self.number/1000),
 
1556
                                             self.number)
 
1557
            os.makedirs(candidate_dir)
 
1558
            self.test_home_dir = candidate_dir + '/home'
 
1559
            os.mkdir(self.test_home_dir)
 
1560
            self.test_dir = candidate_dir + '/work'
 
1561
            os.mkdir(self.test_dir)
 
1562
            os.chdir(self.test_dir)
 
1563
            # put name of test inside
 
1564
            f = file(candidate_dir + '/name', 'w')
 
1565
            f.write(self.id())
 
1566
            f.close()
770
1567
            return
771
 
        i = 0
772
 
        while True:
773
 
            root = u'test%04d.tmp' % i
774
 
            try:
775
 
                os.mkdir(root)
776
 
            except OSError, e:
777
 
                if e.errno == errno.EEXIST:
778
 
                    i += 1
779
 
                    continue
780
 
                else:
781
 
                    raise
782
 
            # successfully created
783
 
            TestCaseInTempDir.TEST_ROOT = osutils.abspath(root)
784
 
            break
785
 
        # make a fake bzr directory there to prevent any tests propagating
786
 
        # up onto the source directory's real branch
787
 
        bzrdir.BzrDir.create_standalone_workingtree(TestCaseInTempDir.TEST_ROOT)
788
 
 
789
 
    def setUp(self):
790
 
        super(TestCaseInTempDir, self).setUp()
791
 
        self._make_test_root()
792
 
        _currentdir = os.getcwdu()
 
1568
        # Else NAMED DIRS
793
1569
        # shorten the name, to avoid test failures due to path length
794
1570
        short_id = self.id().replace('bzrlib.tests.', '') \
795
1571
                   .replace('__main__.', '')[-100:]
805
1581
                i = i + 1
806
1582
                continue
807
1583
            else:
808
 
                self.test_dir = candidate_dir
 
1584
                os.mkdir(candidate_dir)
 
1585
                self.test_home_dir = candidate_dir + '/home'
 
1586
                os.mkdir(self.test_home_dir)
 
1587
                self.test_dir = candidate_dir + '/work'
809
1588
                os.mkdir(self.test_dir)
810
1589
                os.chdir(self.test_dir)
811
1590
                break
812
 
        os.environ['HOME'] = self.test_dir
813
 
        os.environ['APPDATA'] = self.test_dir
814
 
        def _leaveDirectory():
815
 
            os.chdir(_currentdir)
816
 
        self.addCleanup(_leaveDirectory)
817
 
        
818
 
    def build_tree(self, shape, line_endings='native', transport=None):
 
1591
 
 
1592
    def build_tree(self, shape, line_endings='binary', transport=None):
819
1593
        """Build a test tree according to a pattern.
820
1594
 
821
1595
        shape is a sequence of file specifications.  If the final
822
1596
        character is '/', a directory is created.
823
1597
 
 
1598
        This assumes that all the elements in the tree being built are new.
 
1599
 
824
1600
        This doesn't add anything to a branch.
825
1601
        :param line_endings: Either 'binary' or 'native'
826
1602
                             in binary mode, exact contents are written
831
1607
                          VFS's. If the transport is readonly or None,
832
1608
                          "." is opened automatically.
833
1609
        """
834
 
        # XXX: It's OK to just create them using forward slashes on windows?
 
1610
        # It's OK to just create them using forward slashes on windows.
835
1611
        if transport is None or transport.is_readonly():
836
1612
            transport = get_transport(".")
837
1613
        for name in shape:
838
1614
            self.assert_(isinstance(name, basestring))
839
1615
            if name[-1] == '/':
840
 
                transport.mkdir(urlescape(name[:-1]))
 
1616
                transport.mkdir(urlutils.escape(name[:-1]))
841
1617
            else:
842
1618
                if line_endings == 'binary':
843
1619
                    end = '\n'
844
1620
                elif line_endings == 'native':
845
1621
                    end = os.linesep
846
1622
                else:
847
 
                    raise errors.BzrError('Invalid line ending request %r' % (line_endings,))
848
 
                content = "contents of %s%s" % (name, end)
849
 
                transport.put(urlescape(name), StringIO(content))
 
1623
                    raise errors.BzrError(
 
1624
                        'Invalid line ending request %r' % line_endings)
 
1625
                content = "contents of %s%s" % (name.encode('utf-8'), end)
 
1626
                transport.put_bytes_non_atomic(urlutils.escape(name), content)
850
1627
 
851
1628
    def build_tree_contents(self, shape):
852
1629
        build_tree_contents(shape)
853
1630
 
 
1631
    def assertFileEqual(self, content, path):
 
1632
        """Fail if path does not contain 'content'."""
 
1633
        self.failUnlessExists(path)
 
1634
        # TODO: jam 20060427 Shouldn't this be 'rb'?
 
1635
        self.assertEqualDiff(content, open(path, 'r').read())
 
1636
 
854
1637
    def failUnlessExists(self, path):
855
1638
        """Fail unless path, which may be abs or relative, exists."""
856
 
        self.failUnless(osutils.lexists(path))
 
1639
        self.failUnless(osutils.lexists(path),path+" does not exist")
857
1640
 
858
1641
    def failIfExists(self, path):
859
1642
        """Fail if path, which may be abs or relative, exists."""
860
 
        self.failIf(osutils.lexists(path))
861
 
        
862
 
    def assertFileEqual(self, content, path):
863
 
        """Fail if path does not contain 'content'."""
864
 
        self.failUnless(osutils.lexists(path))
865
 
        self.assertEqualDiff(content, open(path, 'r').read())
 
1643
        self.failIf(osutils.lexists(path),path+" exists")
866
1644
 
867
1645
 
868
1646
class TestCaseWithTransport(TestCaseInTempDir):
879
1657
    readwrite one must both define get_url() as resolving to os.getcwd().
880
1658
    """
881
1659
 
882
 
    def __init__(self, methodName='testMethod'):
883
 
        super(TestCaseWithTransport, self).__init__(methodName)
884
 
        self.__readonly_server = None
885
 
        self.__server = None
886
 
        self.transport_server = default_transport
887
 
        self.transport_readonly_server = None
888
 
 
889
 
    def get_readonly_url(self, relpath=None):
890
 
        """Get a URL for the readonly transport.
891
 
 
892
 
        This will either be backed by '.' or a decorator to the transport 
893
 
        used by self.get_url()
894
 
        relpath provides for clients to get a path relative to the base url.
895
 
        These should only be downwards relative, not upwards.
896
 
        """
897
 
        base = self.get_readonly_server().get_url()
898
 
        if relpath is not None:
899
 
            if not base.endswith('/'):
900
 
                base = base + '/'
901
 
            base = base + relpath
902
 
        return base
903
 
 
904
 
    def get_readonly_server(self):
905
 
        """Get the server instance for the readonly transport
906
 
 
907
 
        This is useful for some tests with specific servers to do diagnostics.
908
 
        """
909
 
        if self.__readonly_server is None:
910
 
            if self.transport_readonly_server is None:
911
 
                # readonly decorator requested
912
 
                # bring up the server
913
 
                self.get_url()
914
 
                self.__readonly_server = ReadonlyServer()
915
 
                self.__readonly_server.setUp(self.__server)
916
 
            else:
917
 
                self.__readonly_server = self.transport_readonly_server()
918
 
                self.__readonly_server.setUp()
919
 
            self.addCleanup(self.__readonly_server.tearDown)
920
 
        return self.__readonly_server
 
1660
    def create_transport_server(self):
 
1661
        """Create a transport server from class defined at init.
 
1662
 
 
1663
        This is mostly a hook for daughter classes.
 
1664
        """
 
1665
        return self.transport_server()
921
1666
 
922
1667
    def get_server(self):
923
 
        """Get the read/write server instance.
 
1668
        """See TestCaseWithMemoryTransport.
924
1669
 
925
1670
        This is useful for some tests with specific servers that need
926
1671
        diagnostics.
927
1672
        """
928
1673
        if self.__server is None:
929
 
            self.__server = self.transport_server()
 
1674
            self.__server = self.create_transport_server()
930
1675
            self.__server.setUp()
931
1676
            self.addCleanup(self.__server.tearDown)
932
1677
        return self.__server
933
1678
 
934
 
    def get_url(self, relpath=None):
935
 
        """Get a URL for the readwrite transport.
936
 
 
937
 
        This will either be backed by '.' or to an equivalent non-file based
938
 
        facility.
939
 
        relpath provides for clients to get a path relative to the base url.
940
 
        These should only be downwards relative, not upwards.
941
 
        """
942
 
        base = self.get_server().get_url()
943
 
        if relpath is not None and relpath != '.':
944
 
            if not base.endswith('/'):
945
 
                base = base + '/'
946
 
            base = base + relpath
947
 
        return base
948
 
 
949
 
    def get_transport(self):
950
 
        """Return a writeable transport for the test scratch space"""
951
 
        t = get_transport(self.get_url())
952
 
        self.assertFalse(t.is_readonly())
953
 
        return t
954
 
 
955
 
    def get_readonly_transport(self):
956
 
        """Return a readonly transport for the test scratch space
957
 
        
958
 
        This can be used to test that operations which should only need
959
 
        readonly access in fact do not try to write.
960
 
        """
961
 
        t = get_transport(self.get_readonly_url())
962
 
        self.assertTrue(t.is_readonly())
963
 
        return t
964
 
 
965
 
    def make_branch(self, relpath, format=None):
966
 
        """Create a branch on the transport at relpath."""
967
 
        repo = self.make_repository(relpath, format=format)
968
 
        return repo.bzrdir.create_branch()
969
 
 
970
 
    def make_bzrdir(self, relpath, format=None):
971
 
        try:
972
 
            url = self.get_url(relpath)
973
 
            segments = relpath.split('/')
974
 
            if segments and segments[-1] not in ('', '.'):
975
 
                parent = self.get_url('/'.join(segments[:-1]))
976
 
                t = get_transport(parent)
977
 
                try:
978
 
                    t.mkdir(segments[-1])
979
 
                except errors.FileExists:
980
 
                    pass
981
 
            if format is None:
982
 
                format=bzrlib.bzrdir.BzrDirFormat.get_default_format()
983
 
            # FIXME: make this use a single transport someday. RBC 20060418
984
 
            return format.initialize_on_transport(get_transport(relpath))
985
 
        except errors.UninitializableFormat:
986
 
            raise TestSkipped("Format %s is not initializable." % format)
987
 
 
988
 
    def make_repository(self, relpath, shared=False, format=None):
989
 
        """Create a repository on our default transport at relpath."""
990
 
        made_control = self.make_bzrdir(relpath, format=format)
991
 
        return made_control.create_repository(shared=shared)
992
 
 
993
1679
    def make_branch_and_tree(self, relpath, format=None):
994
1680
        """Create a branch on the transport and a tree locally.
995
1681
 
996
 
        Returns the tree.
 
1682
        If the transport is not a LocalTransport, the Tree can't be created on
 
1683
        the transport.  In that case the working tree is created in the local
 
1684
        directory, and the returned tree's branch and repository will also be
 
1685
        accessed locally.
 
1686
 
 
1687
        This will fail if the original default transport for this test
 
1688
        case wasn't backed by the working directory, as the branch won't
 
1689
        be on disk for us to open it.  
 
1690
 
 
1691
        :param format: The BzrDirFormat.
 
1692
        :returns: the WorkingTree.
997
1693
        """
998
1694
        # TODO: always use the local disk path for the working tree,
999
1695
        # this obviously requires a format that supports branch references
1003
1699
        try:
1004
1700
            return b.bzrdir.create_workingtree()
1005
1701
        except errors.NotLocalUrl:
1006
 
            # new formats - catch No tree error and create
1007
 
            # a branch reference and a checkout.
1008
 
            # old formats at that point - raise TestSkipped.
1009
 
            # TODO: rbc 20060208
1010
 
            return WorkingTreeFormat2().initialize(bzrdir.BzrDir.open(relpath))
 
1702
            # We can only make working trees locally at the moment.  If the
 
1703
            # transport can't support them, then reopen the branch on a local
 
1704
            # transport, and create the working tree there.  
 
1705
            #
 
1706
            # Possibly we should instead keep
 
1707
            # the non-disk-backed branch and create a local checkout?
 
1708
            bd = bzrdir.BzrDir.open(relpath)
 
1709
            return bd.create_workingtree()
1011
1710
 
1012
1711
    def assertIsDirectory(self, relpath, transport):
1013
1712
        """Assert that relpath within transport is a directory.
1024
1723
            self.fail("path %s is not a directory; has mode %#o"
1025
1724
                      % (relpath, mode))
1026
1725
 
 
1726
    def assertTreesEqual(self, left, right):
 
1727
        """Check that left and right have the same content and properties."""
 
1728
        # we use a tree delta to check for equality of the content, and we
 
1729
        # manually check for equality of other things such as the parents list.
 
1730
        self.assertEqual(left.get_parent_ids(), right.get_parent_ids())
 
1731
        differences = left.changes_from(right)
 
1732
        self.assertFalse(differences.has_changed(),
 
1733
            "Trees %r and %r are different: %r" % (left, right, differences))
 
1734
 
 
1735
    def setUp(self):
 
1736
        super(TestCaseWithTransport, self).setUp()
 
1737
        self.__server = None
 
1738
 
1027
1739
 
1028
1740
class ChrootedTestCase(TestCaseWithTransport):
1029
1741
    """A support class that provides readonly urls outside the local namespace.
1039
1751
 
1040
1752
    def setUp(self):
1041
1753
        super(ChrootedTestCase, self).setUp()
1042
 
        if not self.transport_server == bzrlib.transport.memory.MemoryServer:
1043
 
            self.transport_readonly_server = bzrlib.transport.http.HttpServer
 
1754
        if not self.transport_server == MemoryServer:
 
1755
            self.transport_readonly_server = HttpServer
1044
1756
 
1045
1757
 
1046
1758
def filter_suite_by_re(suite, pattern):
1047
 
    result = TestSuite()
 
1759
    result = TestUtil.TestSuite()
1048
1760
    filter_re = re.compile(pattern)
1049
1761
    for test in iter_suite_tests(suite):
1050
1762
        if filter_re.search(test.id()):
1052
1764
    return result
1053
1765
 
1054
1766
 
 
1767
def sort_suite_by_re(suite, pattern):
 
1768
    first = []
 
1769
    second = []
 
1770
    filter_re = re.compile(pattern)
 
1771
    for test in iter_suite_tests(suite):
 
1772
        if filter_re.search(test.id()):
 
1773
            first.append(test)
 
1774
        else:
 
1775
            second.append(test)
 
1776
    return TestUtil.TestSuite(first + second)
 
1777
 
 
1778
 
1055
1779
def run_suite(suite, name='test', verbose=False, pattern=".*",
1056
1780
              stop_on_failure=False, keep_output=False,
1057
 
              transport=None, lsprof_timed=None):
1058
 
    TestCaseInTempDir._TEST_NAME = name
 
1781
              transport=None, lsprof_timed=None, bench_history=None,
 
1782
              matching_tests_first=None,
 
1783
              numbered_dirs=False):
 
1784
    global NUMBERED_DIRS
 
1785
    NUMBERED_DIRS = bool(numbered_dirs)
 
1786
 
1059
1787
    TestCase._gather_lsprof_in_benchmarks = lsprof_timed
1060
1788
    if verbose:
1061
1789
        verbosity = 2
1062
 
        pb = None
1063
1790
    else:
1064
1791
        verbosity = 1
1065
 
        pb = progress.ProgressBar()
1066
1792
    runner = TextTestRunner(stream=sys.stdout,
1067
1793
                            descriptions=0,
1068
1794
                            verbosity=verbosity,
1069
1795
                            keep_output=keep_output,
1070
 
                            pb=pb)
 
1796
                            bench_history=bench_history)
1071
1797
    runner.stop_on_failure=stop_on_failure
1072
1798
    if pattern != '.*':
1073
 
        suite = filter_suite_by_re(suite, pattern)
 
1799
        if matching_tests_first:
 
1800
            suite = sort_suite_by_re(suite, pattern)
 
1801
        else:
 
1802
            suite = filter_suite_by_re(suite, pattern)
1074
1803
    result = runner.run(suite)
1075
1804
    return result.wasSuccessful()
1076
1805
 
1079
1808
             keep_output=False,
1080
1809
             transport=None,
1081
1810
             test_suite_factory=None,
1082
 
             lsprof_timed=None):
 
1811
             lsprof_timed=None,
 
1812
             bench_history=None,
 
1813
             matching_tests_first=None,
 
1814
             numbered_dirs=False):
1083
1815
    """Run the whole test suite under the enhanced runner"""
 
1816
    # XXX: Very ugly way to do this...
 
1817
    # Disable warning about old formats because we don't want it to disturb
 
1818
    # any blackbox tests.
 
1819
    from bzrlib import repository
 
1820
    repository._deprecation_warning_done = True
 
1821
 
1084
1822
    global default_transport
1085
1823
    if transport is None:
1086
1824
        transport = default_transport
1094
1832
        return run_suite(suite, 'testbzr', verbose=verbose, pattern=pattern,
1095
1833
                     stop_on_failure=stop_on_failure, keep_output=keep_output,
1096
1834
                     transport=transport,
1097
 
                     lsprof_timed=lsprof_timed)
 
1835
                     lsprof_timed=lsprof_timed,
 
1836
                     bench_history=bench_history,
 
1837
                     matching_tests_first=matching_tests_first,
 
1838
                     numbered_dirs=numbered_dirs)
1098
1839
    finally:
1099
1840
        default_transport = old_transport
1100
1841
 
1105
1846
    This function can be replaced if you need to change the default test
1106
1847
    suite on a global basis, but it is not encouraged.
1107
1848
    """
1108
 
    from doctest import DocTestSuite
1109
 
 
1110
 
    global MODULES_TO_DOCTEST
1111
 
 
1112
 
    testmod_names = [ \
 
1849
    testmod_names = [
1113
1850
                   'bzrlib.tests.test_ancestry',
 
1851
                   'bzrlib.tests.test_annotate',
1114
1852
                   'bzrlib.tests.test_api',
 
1853
                   'bzrlib.tests.test_atomicfile',
1115
1854
                   'bzrlib.tests.test_bad_files',
1116
1855
                   'bzrlib.tests.test_branch',
 
1856
                   'bzrlib.tests.test_bundle',
1117
1857
                   'bzrlib.tests.test_bzrdir',
1118
 
                   'bzrlib.tests.test_command',
 
1858
                   'bzrlib.tests.test_cache_utf8',
 
1859
                   'bzrlib.tests.test_commands',
1119
1860
                   'bzrlib.tests.test_commit',
1120
1861
                   'bzrlib.tests.test_commit_merge',
1121
1862
                   'bzrlib.tests.test_config',
1122
1863
                   'bzrlib.tests.test_conflicts',
1123
1864
                   'bzrlib.tests.test_decorators',
 
1865
                   'bzrlib.tests.test_delta',
1124
1866
                   'bzrlib.tests.test_diff',
 
1867
                   'bzrlib.tests.test_dirstate',
1125
1868
                   'bzrlib.tests.test_doc_generate',
1126
1869
                   'bzrlib.tests.test_errors',
1127
1870
                   'bzrlib.tests.test_escaped_store',
 
1871
                   'bzrlib.tests.test_extract',
1128
1872
                   'bzrlib.tests.test_fetch',
 
1873
                   'bzrlib.tests.test_ftp_transport',
 
1874
                   'bzrlib.tests.test_generate_docs',
 
1875
                   'bzrlib.tests.test_generate_ids',
 
1876
                   'bzrlib.tests.test_globbing',
1129
1877
                   'bzrlib.tests.test_gpg',
1130
1878
                   'bzrlib.tests.test_graph',
1131
1879
                   'bzrlib.tests.test_hashcache',
1132
1880
                   'bzrlib.tests.test_http',
 
1881
                   'bzrlib.tests.test_http_response',
 
1882
                   'bzrlib.tests.test_https_ca_bundle',
1133
1883
                   'bzrlib.tests.test_identitymap',
 
1884
                   'bzrlib.tests.test_ignores',
1134
1885
                   'bzrlib.tests.test_inv',
1135
1886
                   'bzrlib.tests.test_knit',
 
1887
                   'bzrlib.tests.test_lazy_import',
 
1888
                   'bzrlib.tests.test_lazy_regex',
1136
1889
                   'bzrlib.tests.test_lockdir',
1137
1890
                   'bzrlib.tests.test_lockable_files',
1138
1891
                   'bzrlib.tests.test_log',
 
1892
                   'bzrlib.tests.test_memorytree',
1139
1893
                   'bzrlib.tests.test_merge',
1140
1894
                   'bzrlib.tests.test_merge3',
1141
1895
                   'bzrlib.tests.test_merge_core',
 
1896
                   'bzrlib.tests.test_merge_directive',
1142
1897
                   'bzrlib.tests.test_missing',
1143
1898
                   'bzrlib.tests.test_msgeditor',
1144
1899
                   'bzrlib.tests.test_nonascii',
1145
1900
                   'bzrlib.tests.test_options',
1146
1901
                   'bzrlib.tests.test_osutils',
 
1902
                   'bzrlib.tests.test_osutils_encodings',
1147
1903
                   'bzrlib.tests.test_patch',
 
1904
                   'bzrlib.tests.test_patches',
1148
1905
                   'bzrlib.tests.test_permissions',
1149
1906
                   'bzrlib.tests.test_plugins',
1150
1907
                   'bzrlib.tests.test_progress',
1151
1908
                   'bzrlib.tests.test_reconcile',
 
1909
                   'bzrlib.tests.test_registry',
1152
1910
                   'bzrlib.tests.test_repository',
 
1911
                   'bzrlib.tests.test_revert',
1153
1912
                   'bzrlib.tests.test_revision',
1154
1913
                   'bzrlib.tests.test_revisionnamespaces',
1155
 
                   'bzrlib.tests.test_revprops',
 
1914
                   'bzrlib.tests.test_revisiontree',
1156
1915
                   'bzrlib.tests.test_rio',
1157
1916
                   'bzrlib.tests.test_sampler',
1158
1917
                   'bzrlib.tests.test_selftest',
1159
1918
                   'bzrlib.tests.test_setup',
1160
1919
                   'bzrlib.tests.test_sftp_transport',
1161
1920
                   'bzrlib.tests.test_smart_add',
 
1921
                   'bzrlib.tests.test_smart_transport',
1162
1922
                   'bzrlib.tests.test_source',
1163
1923
                   'bzrlib.tests.test_status',
1164
1924
                   'bzrlib.tests.test_store',
 
1925
                   'bzrlib.tests.test_subsume',
1165
1926
                   'bzrlib.tests.test_symbol_versioning',
 
1927
                   'bzrlib.tests.test_tag',
1166
1928
                   'bzrlib.tests.test_testament',
1167
1929
                   'bzrlib.tests.test_textfile',
1168
1930
                   'bzrlib.tests.test_textmerge',
 
1931
                   'bzrlib.tests.test_timestamp',
1169
1932
                   'bzrlib.tests.test_trace',
1170
1933
                   'bzrlib.tests.test_transactions',
1171
1934
                   'bzrlib.tests.test_transform',
1172
1935
                   'bzrlib.tests.test_transport',
 
1936
                   'bzrlib.tests.test_tree',
 
1937
                   'bzrlib.tests.test_treebuilder',
1173
1938
                   'bzrlib.tests.test_tsort',
1174
1939
                   'bzrlib.tests.test_tuned_gzip',
1175
1940
                   'bzrlib.tests.test_ui',
1176
1941
                   'bzrlib.tests.test_upgrade',
 
1942
                   'bzrlib.tests.test_urlutils',
1177
1943
                   'bzrlib.tests.test_versionedfile',
 
1944
                   'bzrlib.tests.test_version',
 
1945
                   'bzrlib.tests.test_version_info',
1178
1946
                   'bzrlib.tests.test_weave',
1179
1947
                   'bzrlib.tests.test_whitebox',
1180
1948
                   'bzrlib.tests.test_workingtree',
 
1949
                   'bzrlib.tests.test_workingtree_4',
 
1950
                   'bzrlib.tests.test_wsgi',
1181
1951
                   'bzrlib.tests.test_xml',
1182
1952
                   ]
1183
1953
    test_transport_implementations = [
1184
 
        'bzrlib.tests.test_transport_implementations']
1185
 
 
1186
 
    suite = TestSuite()
 
1954
        'bzrlib.tests.test_transport_implementations',
 
1955
        'bzrlib.tests.test_read_bundle',
 
1956
        ]
 
1957
    suite = TestUtil.TestSuite()
1187
1958
    loader = TestUtil.TestLoader()
 
1959
    suite.addTest(loader.loadTestsFromModuleNames(testmod_names))
1188
1960
    from bzrlib.transport import TransportTestProviderAdapter
1189
1961
    adapter = TransportTestProviderAdapter()
1190
1962
    adapt_modules(test_transport_implementations, adapter, loader, suite)
1191
 
    suite.addTest(loader.loadTestsFromModuleNames(testmod_names))
1192
1963
    for package in packages_to_test():
1193
1964
        suite.addTest(package.test_suite())
1194
1965
    for m in MODULES_TO_TEST:
1195
1966
        suite.addTest(loader.loadTestsFromModule(m))
1196
 
    for m in (MODULES_TO_DOCTEST):
1197
 
        suite.addTest(DocTestSuite(m))
 
1967
    for m in MODULES_TO_DOCTEST:
 
1968
        try:
 
1969
            suite.addTest(doctest.DocTestSuite(m))
 
1970
        except ValueError, e:
 
1971
            print '**failed to get doctest for: %s\n%s' %(m,e)
 
1972
            raise
1198
1973
    for name, plugin in bzrlib.plugin.all_plugins().items():
1199
1974
        if getattr(plugin, 'test_suite', None) is not None:
1200
 
            suite.addTest(plugin.test_suite())
 
1975
            default_encoding = sys.getdefaultencoding()
 
1976
            try:
 
1977
                plugin_suite = plugin.test_suite()
 
1978
            except ImportError, e:
 
1979
                bzrlib.trace.warning(
 
1980
                    'Unable to test plugin "%s": %s', name, e)
 
1981
            else:
 
1982
                suite.addTest(plugin_suite)
 
1983
            if default_encoding != sys.getdefaultencoding():
 
1984
                bzrlib.trace.warning(
 
1985
                    'Plugin "%s" tried to reset default encoding to: %s', name,
 
1986
                    sys.getdefaultencoding())
 
1987
                reload(sys)
 
1988
                sys.setdefaultencoding(default_encoding)
1201
1989
    return suite
1202
1990
 
1203
1991
 
1205
1993
    """Adapt the modules in mods_list using adapter and add to suite."""
1206
1994
    for test in iter_suite_tests(loader.loadTestsFromModuleNames(mods_list)):
1207
1995
        suite.addTests(adapter.adapt(test))
 
1996
 
 
1997
 
 
1998
def clean_selftest_output(root=None, quiet=False):
 
1999
    """Remove all selftest output directories from root directory.
 
2000
 
 
2001
    :param  root:   root directory for clean
 
2002
                    (if ommitted or None then clean current directory).
 
2003
    :param  quiet:  suppress report about deleting directories
 
2004
    """
 
2005
    import re
 
2006
    import shutil
 
2007
 
 
2008
    re_dir = re.compile(r'''test\d\d\d\d\.tmp''')
 
2009
    if root is None:
 
2010
        root = u'.'
 
2011
    for i in os.listdir(root):
 
2012
        if os.path.isdir(i) and re_dir.match(i):
 
2013
            if not quiet:
 
2014
                print 'delete directory:', i
 
2015
            shutil.rmtree(i)