~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/__init__.py

  • Committer: John Arbash Meinel
  • Author(s): Mark Hammond
  • Date: 2008-09-09 17:02:21 UTC
  • mto: This revision was merged to the branch mainline in revision 3697.
  • Revision ID: john@arbash-meinel.com-20080909170221-svim3jw2mrz0amp3
An updated transparent icon for bzr.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006, 2007, 2008, 2009 Canonical Ltd
 
1
# Copyright (C) 2005, 2006, 2007, 2008 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
12
12
#
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
16
 
17
17
 
18
18
# TODO: Perhaps there should be an API to find out if bzr running under the
33
33
import doctest
34
34
import errno
35
35
import logging
36
 
import math
37
36
import os
38
37
from pprint import pformat
39
38
import random
40
39
import re
41
40
import shlex
42
41
import stat
43
 
from subprocess import Popen, PIPE, STDOUT
 
42
from subprocess import Popen, PIPE
44
43
import sys
45
44
import tempfile
46
45
import threading
54
53
    bzrdir,
55
54
    debug,
56
55
    errors,
57
 
    hooks,
58
 
    lock as _mod_lock,
59
56
    memorytree,
60
57
    osutils,
61
58
    progress,
79
76
from bzrlib.merge import merge_inner
80
77
import bzrlib.merge3
81
78
import bzrlib.plugin
82
 
from bzrlib.smart import client, request, server
83
79
import bzrlib.store
84
80
from bzrlib import symbol_versioning
85
81
from bzrlib.symbol_versioning import (
102
98
                          TestLoader,
103
99
                          )
104
100
from bzrlib.tests.treeshape import build_tree_contents
105
 
from bzrlib.ui import NullProgressView
106
 
from bzrlib.ui.text import TextUIFactory
107
101
import bzrlib.version_info_formats.format_custom
108
102
from bzrlib.workingtree import WorkingTree, WorkingTreeFormat2
109
103
 
114
108
 
115
109
default_transport = LocalURLServer
116
110
 
117
 
# Subunit result codes, defined here to prevent a hard dependency on subunit.
118
 
SUBUNIT_SEEK_SET = 0
119
 
SUBUNIT_SEEK_CUR = 1
120
 
 
121
111
 
122
112
class ExtendedTestResult(unittest._TextTestResult):
123
113
    """Accepts, reports and accumulates the results of running tests.
136
126
    """
137
127
 
138
128
    stop_early = False
139
 
 
 
129
    
140
130
    def __init__(self, stream, descriptions, verbosity,
141
131
                 bench_history=None,
142
 
                 strict=False,
 
132
                 num_tests=None,
143
133
                 ):
144
134
        """Construct new TestResult.
145
135
 
163
153
            bench_history.write("--date %s %s\n" % (time.time(), revision_id))
164
154
        self._bench_history = bench_history
165
155
        self.ui = ui.ui_factory
166
 
        self.num_tests = 0
 
156
        self.num_tests = num_tests
167
157
        self.error_count = 0
168
158
        self.failure_count = 0
169
159
        self.known_failure_count = 0
172
162
        self.unsupported = {}
173
163
        self.count = 0
174
164
        self._overall_start_time = time.time()
175
 
        self._strict = strict
176
 
 
177
 
    def done(self):
178
 
        # nb: called stopTestRun in the version of this that Python merged
179
 
        # upstream, according to lifeless 20090803
180
 
        if self._strict:
181
 
            ok = self.wasStrictlySuccessful()
182
 
        else:
183
 
            ok = self.wasSuccessful()
184
 
        if ok:
185
 
            self.stream.write('tests passed\n')
186
 
        else:
187
 
            self.stream.write('tests failed\n')
188
 
        if TestCase._first_thread_leaker_id:
189
 
            self.stream.write(
190
 
                '%s is leaking threads among %d leaking tests.\n' % (
191
 
                TestCase._first_thread_leaker_id,
192
 
                TestCase._leaking_threads_tests))
193
 
 
 
165
    
194
166
    def _extractBenchmarkTime(self, testCase):
195
167
        """Add a benchmark time for the current test case."""
196
168
        return getattr(testCase, "_benchtime", None)
197
 
 
 
169
    
198
170
    def _elapsedTestTimeString(self):
199
171
        """Return a time string for the overall time the current test has taken."""
200
172
        return self._formatTime(time.time() - self._start_time)
202
174
    def _testTimeString(self, testCase):
203
175
        benchmark_time = self._extractBenchmarkTime(testCase)
204
176
        if benchmark_time is not None:
205
 
            return self._formatTime(benchmark_time) + "*"
 
177
            return "%s/%s" % (
 
178
                self._formatTime(benchmark_time),
 
179
                self._elapsedTestTimeString())
206
180
        else:
207
 
            return self._elapsedTestTimeString()
 
181
            return "           %s" % self._elapsedTestTimeString()
208
182
 
209
183
    def _formatTime(self, seconds):
210
184
        """Format seconds as milliseconds with leading spaces."""
219
193
 
220
194
    def startTest(self, test):
221
195
        unittest.TestResult.startTest(self, test)
222
 
        if self.count == 0:
223
 
            self.startTests()
224
196
        self.report_test_start(test)
225
197
        test.number = self.count
226
198
        self._recordTestStartTime()
227
199
 
228
 
    def startTests(self):
229
 
        import platform
230
 
        if getattr(sys, 'frozen', None) is None:
231
 
            bzr_path = osutils.realpath(sys.argv[0])
232
 
        else:
233
 
            bzr_path = sys.executable
234
 
        self.stream.write(
235
 
            'testing: %s\n' % (bzr_path,))
236
 
        self.stream.write(
237
 
            '   %s\n' % (
238
 
                    bzrlib.__path__[0],))
239
 
        self.stream.write(
240
 
            '   bzr-%s python-%s %s\n' % (
241
 
                    bzrlib.version_string,
242
 
                    bzrlib._format_version_tuple(sys.version_info),
243
 
                    platform.platform(aliased=1),
244
 
                    ))
245
 
        self.stream.write('\n')
246
 
 
247
200
    def _recordTestStartTime(self):
248
201
        """Record that a test has started."""
249
202
        self._start_time = time.time()
262
215
        fails with an unexpected error.
263
216
        """
264
217
        self._testConcluded(test)
265
 
        if isinstance(err[1], TestNotApplicable):
266
 
            return self._addNotApplicable(test, err)
 
218
        if isinstance(err[1], TestSkipped):
 
219
            return self._addSkipped(test, err)
267
220
        elif isinstance(err[1], UnavailableFeature):
268
221
            return self.addNotSupported(test, err[1].args[0])
269
222
        else:
323
276
        """The test will not be run because of a missing feature.
324
277
        """
325
278
        # this can be called in two different ways: it may be that the
326
 
        # test started running, and then raised (through addError)
 
279
        # test started running, and then raised (through addError) 
327
280
        # UnavailableFeature.  Alternatively this method can be called
328
281
        # while probing for features before running the tests; in that
329
282
        # case we will see startTest and stopTest, but the test will never
332
285
        self.unsupported[str(feature)] += 1
333
286
        self.report_unsupported(test, feature)
334
287
 
335
 
    def addSkip(self, test, reason):
336
 
        """A test has not run for 'reason'."""
337
 
        self.skip_count += 1
338
 
        self.report_skip(test, reason)
339
 
 
340
 
    def _addNotApplicable(self, test, skip_excinfo):
 
288
    def _addSkipped(self, test, skip_excinfo):
341
289
        if isinstance(skip_excinfo[1], TestNotApplicable):
342
290
            self.not_applicable_count += 1
343
291
            self.report_not_applicable(test, skip_excinfo)
 
292
        else:
 
293
            self.skip_count += 1
 
294
            self.report_skip(test, skip_excinfo)
344
295
        try:
345
296
            test.tearDown()
346
297
        except KeyboardInterrupt:
347
298
            raise
348
299
        except:
349
 
            self.addError(test, test.exc_info())
 
300
            self.addError(test, test._exc_info())
350
301
        else:
351
302
            # seems best to treat this as success from point-of-view of unittest
352
303
            # -- it actually does nothing so it barely matters :)
359
310
            self.stream.write("%s: " % flavour)
360
311
            self.stream.writeln(self.getDescription(test))
361
312
            if getattr(test, '_get_log', None) is not None:
362
 
                log_contents = test._get_log()
363
 
                if log_contents:
364
 
                    self.stream.write('\n')
365
 
                    self.stream.write(
366
 
                            ('vvvv[log from %s]' % test.id()).ljust(78,'-'))
367
 
                    self.stream.write('\n')
368
 
                    self.stream.write(log_contents)
369
 
                    self.stream.write('\n')
370
 
                    self.stream.write(
371
 
                            ('^^^^[log from %s]' % test.id()).ljust(78,'-'))
372
 
                    self.stream.write('\n')
 
313
                self.stream.write('\n')
 
314
                self.stream.write(
 
315
                        ('vvvv[log from %s]' % test.id()).ljust(78,'-'))
 
316
                self.stream.write('\n')
 
317
                self.stream.write(test._get_log())
 
318
                self.stream.write('\n')
 
319
                self.stream.write(
 
320
                        ('^^^^[log from %s]' % test.id()).ljust(78,'-'))
 
321
                self.stream.write('\n')
373
322
            self.stream.writeln(self.separator2)
374
323
            self.stream.writeln("%s" % err)
375
324
 
376
 
    def progress(self, offset, whence):
377
 
        """The test is adjusting the count of tests to run."""
378
 
        if whence == SUBUNIT_SEEK_SET:
379
 
            self.num_tests = offset
380
 
        elif whence == SUBUNIT_SEEK_CUR:
381
 
            self.num_tests += offset
382
 
        else:
383
 
            raise errors.BzrError("Unknown whence %r" % whence)
384
 
 
385
325
    def finished(self):
386
326
        pass
387
327
 
402
342
 
403
343
    def __init__(self, stream, descriptions, verbosity,
404
344
                 bench_history=None,
 
345
                 num_tests=None,
405
346
                 pb=None,
406
 
                 strict=None,
407
347
                 ):
408
348
        ExtendedTestResult.__init__(self, stream, descriptions, verbosity,
409
 
            bench_history, strict)
410
 
        # We no longer pass them around, but just rely on the UIFactory stack
411
 
        # for state
412
 
        if pb is not None:
413
 
            warnings.warn("Passing pb to TextTestResult is deprecated")
414
 
        self.pb = self.ui.nested_progress_bar()
 
349
            bench_history, num_tests)
 
350
        if pb is None:
 
351
            self.pb = self.ui.nested_progress_bar()
 
352
            self._supplied_pb = False
 
353
        else:
 
354
            self.pb = pb
 
355
            self._supplied_pb = True
415
356
        self.pb.show_pct = False
416
357
        self.pb.show_spinner = False
417
358
        self.pb.show_eta = False,
418
359
        self.pb.show_count = False
419
360
        self.pb.show_bar = False
420
 
        self.pb.update_latency = 0
421
 
        self.pb.show_transport_activity = False
422
 
 
423
 
    def done(self):
424
 
        # called when the tests that are going to run have run
425
 
        self.pb.clear()
426
 
        super(TextTestResult, self).done()
427
 
 
428
 
    def finished(self):
429
 
        self.pb.finished()
430
361
 
431
362
    def report_starting(self):
432
 
        self.pb.update('[test 0/%d] Starting' % (self.num_tests))
433
 
 
434
 
    def printErrors(self):
435
 
        # clear the pb to make room for the error listing
436
 
        self.pb.clear()
437
 
        super(TextTestResult, self).printErrors()
 
363
        self.pb.update('[test 0/%d] starting...' % (self.num_tests))
438
364
 
439
365
    def _progress_prefix_text(self):
440
366
        # the longer this text, the less space we have to show the test
446
372
        ##     a += ', %d skip' % self.skip_count
447
373
        ## if self.known_failure_count:
448
374
        ##     a += '+%dX' % self.known_failure_count
449
 
        if self.num_tests:
 
375
        if self.num_tests is not None:
450
376
            a +='/%d' % self.num_tests
451
377
        a += ' in '
452
378
        runtime = time.time() - self._overall_start_time
467
393
        self.count += 1
468
394
        self.pb.update(
469
395
                self._progress_prefix_text()
470
 
                + ' '
 
396
                + ' ' 
471
397
                + self._shortened_test_description(test))
472
398
 
473
399
    def _test_description(self, test):
474
400
        return self._shortened_test_description(test)
475
401
 
476
402
    def report_error(self, test, err):
477
 
        self.pb.note('ERROR: %s\n    %s\n',
 
403
        self.pb.note('ERROR: %s\n    %s\n', 
478
404
            self._test_description(test),
479
405
            err[1],
480
406
            )
481
407
 
482
408
    def report_failure(self, test, err):
483
 
        self.pb.note('FAIL: %s\n    %s\n',
 
409
        self.pb.note('FAIL: %s\n    %s\n', 
484
410
            self._test_description(test),
485
411
            err[1],
486
412
            )
489
415
        self.pb.note('XFAIL: %s\n%s\n',
490
416
            self._test_description(test), err[1])
491
417
 
492
 
    def report_skip(self, test, reason):
 
418
    def report_skip(self, test, skip_excinfo):
493
419
        pass
494
420
 
495
421
    def report_not_applicable(self, test, skip_excinfo):
497
423
 
498
424
    def report_unsupported(self, test, feature):
499
425
        """test cannot be run because feature is missing."""
500
 
 
 
426
                  
501
427
    def report_cleaning_up(self):
502
 
        self.pb.update('Cleaning up')
 
428
        self.pb.update('cleaning up...')
 
429
 
 
430
    def finished(self):
 
431
        if not self._supplied_pb:
 
432
            self.pb.finished()
503
433
 
504
434
 
505
435
class VerboseTestResult(ExtendedTestResult):
519
449
    def report_test_start(self, test):
520
450
        self.count += 1
521
451
        name = self._shortened_test_description(test)
522
 
        # width needs space for 6 char status, plus 1 for slash, plus an
523
 
        # 11-char time string, plus a trailing blank
 
452
        # width needs space for 6 char status, plus 1 for slash, plus 2 10-char
 
453
        # numbers, plus a trailing blank
524
454
        # when NUMBERED_DIRS: plus 5 chars on test number, plus 1 char on space
525
455
        self.stream.write(self._ellipsize_to_right(name,
526
 
                          osutils.terminal_width()-18))
 
456
                          osutils.terminal_width()-30))
527
457
        self.stream.flush()
528
458
 
529
459
    def _error_summary(self, err):
554
484
        # used to show the output in PQM.
555
485
        self.stream.flush()
556
486
 
557
 
    def report_skip(self, test, reason):
 
487
    def report_skip(self, test, skip_excinfo):
558
488
        self.stream.writeln(' SKIP %s\n%s'
559
 
                % (self._testTimeString(test), reason))
 
489
                % (self._testTimeString(test),
 
490
                   self._error_summary(skip_excinfo)))
560
491
 
561
492
    def report_not_applicable(self, test, skip_excinfo):
562
493
        self.stream.writeln('  N/A %s\n%s'
577
508
                 descriptions=0,
578
509
                 verbosity=1,
579
510
                 bench_history=None,
580
 
                 list_only=False,
581
 
                 strict=False,
 
511
                 list_only=False
582
512
                 ):
583
513
        self.stream = unittest._WritelnDecorator(stream)
584
514
        self.descriptions = descriptions
585
515
        self.verbosity = verbosity
586
516
        self._bench_history = bench_history
587
517
        self.list_only = list_only
588
 
        self._strict = strict
589
518
 
590
519
    def run(self, test):
591
520
        "Run the given test case or test suite."
598
527
                              self.descriptions,
599
528
                              self.verbosity,
600
529
                              bench_history=self._bench_history,
601
 
                              strict=self._strict,
 
530
                              num_tests=test.countTestCases(),
602
531
                              )
603
532
        result.stop_early = self.stop_on_failure
604
533
        result.report_starting()
609
538
            for t in iter_suite_tests(test):
610
539
                self.stream.writeln("%s" % (t.id()))
611
540
                run += 1
612
 
            return None
613
 
        else:
614
 
            try:
615
 
                import testtools
616
 
            except ImportError:
617
 
                test.run(result)
618
 
            else:
619
 
                if isinstance(test, testtools.ConcurrentTestSuite):
620
 
                    # We need to catch bzr specific behaviors
621
 
                    test.run(BZRTransformingResult(result))
622
 
                else:
623
 
                    test.run(result)
 
541
            actionTaken = "Listed"
 
542
        else: 
 
543
            test.run(result)
624
544
            run = result.testsRun
625
545
            actionTaken = "Ran"
626
546
        stopTime = time.time()
663
583
 
664
584
def iter_suite_tests(suite):
665
585
    """Return all tests in a suite, recursing through nested suites"""
666
 
    if isinstance(suite, unittest.TestCase):
667
 
        yield suite
668
 
    elif isinstance(suite, unittest.TestSuite):
669
 
        for item in suite:
 
586
    for item in suite._tests:
 
587
        if isinstance(item, unittest.TestCase):
 
588
            yield item
 
589
        elif isinstance(item, unittest.TestSuite):
670
590
            for r in iter_suite_tests(item):
671
591
                yield r
672
 
    else:
673
 
        raise Exception('unknown type %r for object %r'
674
 
                        % (type(suite), suite))
 
592
        else:
 
593
            raise Exception('unknown object %r inside test suite %r'
 
594
                            % (item, suite))
675
595
 
676
596
 
677
597
class TestSkipped(Exception):
681
601
class TestNotApplicable(TestSkipped):
682
602
    """A test is not applicable to the situation where it was run.
683
603
 
684
 
    This is only normally raised by parameterized tests, if they find that
685
 
    the instance they're constructed upon does not support one aspect
 
604
    This is only normally raised by parameterized tests, if they find that 
 
605
    the instance they're constructed upon does not support one aspect 
686
606
    of its interface.
687
607
    """
688
608
 
710
630
 
711
631
class StringIOWrapper(object):
712
632
    """A wrapper around cStringIO which just adds an encoding attribute.
713
 
 
 
633
    
714
634
    Internally we can check sys.stdout to see what the output encoding
715
635
    should be. However, cStringIO has no encoding attribute that we can
716
636
    set. So we wrap it instead.
734
654
            return setattr(self._cstring, name, val)
735
655
 
736
656
 
737
 
class TestUIFactory(TextUIFactory):
 
657
class TestUIFactory(ui.CLIUIFactory):
738
658
    """A UI Factory for testing.
739
659
 
740
660
    Hide the progress bar but emit note()s.
741
661
    Redirect stdin.
742
662
    Allows get_password to be tested without real tty attached.
743
 
 
744
 
    See also CannedInputUIFactory which lets you provide programmatic input in
745
 
    a structured way.
746
663
    """
747
 
    # TODO: Capture progress events at the model level and allow them to be
748
 
    # observed by tests that care.
749
 
    #
750
 
    # XXX: Should probably unify more with CannedInputUIFactory or a
751
 
    # particular configuration of TextUIFactory, or otherwise have a clearer
752
 
    # idea of how they're supposed to be different.
753
 
    # See https://bugs.edge.launchpad.net/bzr/+bug/408213
754
664
 
755
 
    def __init__(self, stdout=None, stderr=None, stdin=None):
 
665
    def __init__(self,
 
666
                 stdout=None,
 
667
                 stderr=None,
 
668
                 stdin=None):
 
669
        super(TestUIFactory, self).__init__()
756
670
        if stdin is not None:
757
671
            # We use a StringIOWrapper to be able to test various
758
672
            # encodings, but the user is still responsible to
759
673
            # encode the string and to set the encoding attribute
760
674
            # of StringIOWrapper.
761
 
            stdin = StringIOWrapper(stdin)
762
 
        super(TestUIFactory, self).__init__(stdin, stdout, stderr)
763
 
 
764
 
    def get_non_echoed_password(self):
 
675
            self.stdin = StringIOWrapper(stdin)
 
676
        if stdout is None:
 
677
            self.stdout = sys.stdout
 
678
        else:
 
679
            self.stdout = stdout
 
680
        if stderr is None:
 
681
            self.stderr = sys.stderr
 
682
        else:
 
683
            self.stderr = stderr
 
684
 
 
685
    def clear(self):
 
686
        """See progress.ProgressBar.clear()."""
 
687
 
 
688
    def clear_term(self):
 
689
        """See progress.ProgressBar.clear_term()."""
 
690
 
 
691
    def clear_term(self):
 
692
        """See progress.ProgressBar.clear_term()."""
 
693
 
 
694
    def finished(self):
 
695
        """See progress.ProgressBar.finished()."""
 
696
 
 
697
    def note(self, fmt_string, *args, **kwargs):
 
698
        """See progress.ProgressBar.note()."""
 
699
        self.stdout.write((fmt_string + "\n") % args)
 
700
 
 
701
    def progress_bar(self):
 
702
        return self
 
703
 
 
704
    def nested_progress_bar(self):
 
705
        return self
 
706
 
 
707
    def update(self, message, count=None, total=None):
 
708
        """See progress.ProgressBar.update()."""
 
709
 
 
710
    def get_non_echoed_password(self, prompt):
765
711
        """Get password from stdin without trying to handle the echo mode"""
 
712
        if prompt:
 
713
            self.stdout.write(prompt.encode(self.stdout.encoding, 'replace'))
766
714
        password = self.stdin.readline()
767
715
        if not password:
768
716
            raise EOFError
770
718
            password = password[:-1]
771
719
        return password
772
720
 
773
 
    def make_progress_view(self):
774
 
        return NullProgressView()
 
721
 
 
722
def _report_leaked_threads():
 
723
    bzrlib.trace.warning('%s is leaking threads among %d leaking tests',
 
724
                         TestCase._first_thread_leaker_id,
 
725
                         TestCase._leaking_threads_tests)
775
726
 
776
727
 
777
728
class TestCase(unittest.TestCase):
778
729
    """Base class for bzr unit tests.
779
 
 
780
 
    Tests that need access to disk resources should subclass
 
730
    
 
731
    Tests that need access to disk resources should subclass 
781
732
    TestCaseInTempDir not TestCase.
782
733
 
783
734
    Error and debug log messages are redirected from their usual
785
736
    retrieved by _get_log().  We use a real OS file, not an in-memory object,
786
737
    so that it can also capture file IO.  When the test completes this file
787
738
    is read into memory and removed from disk.
788
 
 
 
739
       
789
740
    There are also convenience functions to invoke bzr's command-line
790
741
    routine, and to build and check bzr trees.
791
 
 
 
742
   
792
743
    In addition to the usual method of overriding tearDown(), this class also
793
744
    allows subclasses to register functions into the _cleanups list, which is
794
745
    run in order as the object is torn down.  It's less likely this will be
805
756
    _gather_lsprof_in_benchmarks = False
806
757
    attrs_to_keep = ('id', '_testMethodName', '_testMethodDoc',
807
758
                     '_log_contents', '_log_file_name', '_benchtime',
808
 
                     '_TestCase__testMethodName', '_TestCase__testMethodDoc',)
 
759
                     '_TestCase__testMethodName')
809
760
 
810
761
    def __init__(self, methodName='testMethod'):
811
762
        super(TestCase, self).__init__(methodName)
812
763
        self._cleanups = []
813
 
        self._bzr_test_setUp_run = False
814
 
        self._bzr_test_tearDown_run = False
815
764
 
816
765
    def setUp(self):
817
766
        unittest.TestCase.setUp(self)
818
 
        self._bzr_test_setUp_run = True
819
767
        self._cleanEnvironment()
820
768
        self._silenceUI()
821
769
        self._startLogFile()
822
770
        self._benchcalls = []
823
771
        self._benchtime = None
824
772
        self._clear_hooks()
825
 
        self._track_locks()
826
773
        self._clear_debug_flags()
827
774
        TestCase._active_threads = threading.activeCount()
828
775
        self.addCleanup(self._check_leaked_threads)
829
776
 
830
 
    def debug(self):
831
 
        # debug a frame up.
832
 
        import pdb
833
 
        pdb.Pdb().set_trace(sys._getframe().f_back)
834
 
 
835
777
    def _check_leaked_threads(self):
836
778
        active = threading.activeCount()
837
779
        leaked_threads = active - TestCase._active_threads
840
782
            TestCase._leaking_threads_tests += 1
841
783
            if TestCase._first_thread_leaker_id is None:
842
784
                TestCase._first_thread_leaker_id = self.id()
 
785
                # we're not specifically told when all tests are finished.
 
786
                # This will do. We use a function to avoid keeping a reference
 
787
                # to a TestCase object.
 
788
                atexit.register(_report_leaked_threads)
843
789
 
844
790
    def _clear_debug_flags(self):
845
791
        """Prevent externally set debug flags affecting tests.
846
 
 
 
792
        
847
793
        Tests that want to use debug flags can just set them in the
848
794
        debug_flags set during setup/teardown.
849
795
        """
850
 
        self._preserved_debug_flags = set(debug.debug_flags)
851
796
        if 'allow_debug' not in selftest_debug_flags:
 
797
            self._preserved_debug_flags = set(debug.debug_flags)
852
798
            debug.debug_flags.clear()
853
 
        if 'disable_lock_checks' not in selftest_debug_flags:
854
 
            debug.debug_flags.add('strict_locks')
855
 
        self.addCleanup(self._restore_debug_flags)
 
799
            self.addCleanup(self._restore_debug_flags)
856
800
 
857
801
    def _clear_hooks(self):
858
802
        # prevent hooks affecting tests
859
 
        self._preserved_hooks = {}
860
 
        for key, factory in hooks.known_hooks.items():
861
 
            parent, name = hooks.known_hooks_key_to_parent_and_attribute(key)
862
 
            current_hooks = hooks.known_hooks_key_to_object(key)
863
 
            self._preserved_hooks[parent] = (name, current_hooks)
 
803
        import bzrlib.branch
 
804
        import bzrlib.smart.server
 
805
        self._preserved_hooks = {
 
806
            bzrlib.branch.Branch: bzrlib.branch.Branch.hooks,
 
807
            bzrlib.mutabletree.MutableTree: bzrlib.mutabletree.MutableTree.hooks,
 
808
            bzrlib.smart.server.SmartTCPServer: bzrlib.smart.server.SmartTCPServer.hooks,
 
809
            }
864
810
        self.addCleanup(self._restoreHooks)
865
 
        for key, factory in hooks.known_hooks.items():
866
 
            parent, name = hooks.known_hooks_key_to_parent_and_attribute(key)
867
 
            setattr(parent, name, factory())
868
 
        # this hook should always be installed
869
 
        request._install_hook()
 
811
        # reset all hooks to an empty instance of the appropriate type
 
812
        bzrlib.branch.Branch.hooks = bzrlib.branch.BranchHooks()
 
813
        bzrlib.smart.server.SmartTCPServer.hooks = bzrlib.smart.server.SmartServerHooks()
870
814
 
871
815
    def _silenceUI(self):
872
816
        """Turn off UI for duration of test"""
877
821
        ui.ui_factory = ui.SilentUIFactory()
878
822
        self.addCleanup(_restore)
879
823
 
880
 
    def _check_locks(self):
881
 
        """Check that all lock take/release actions have been paired."""
882
 
        # We always check for mismatched locks. If a mismatch is found, we
883
 
        # fail unless -Edisable_lock_checks is supplied to selftest, in which
884
 
        # case we just print a warning.
885
 
        # unhook:
886
 
        acquired_locks = [lock for action, lock in self._lock_actions
887
 
                          if action == 'acquired']
888
 
        released_locks = [lock for action, lock in self._lock_actions
889
 
                          if action == 'released']
890
 
        broken_locks = [lock for action, lock in self._lock_actions
891
 
                        if action == 'broken']
892
 
        # trivially, given the tests for lock acquistion and release, if we
893
 
        # have as many in each list, it should be ok. Some lock tests also
894
 
        # break some locks on purpose and should be taken into account by
895
 
        # considering that breaking a lock is just a dirty way of releasing it.
896
 
        if len(acquired_locks) != (len(released_locks) + len(broken_locks)):
897
 
            message = ('Different number of acquired and '
898
 
                       'released or broken locks. (%s, %s + %s)' %
899
 
                       (acquired_locks, released_locks, broken_locks))
900
 
            if not self._lock_check_thorough:
901
 
                # Rather than fail, just warn
902
 
                print "Broken test %s: %s" % (self, message)
903
 
                return
904
 
            self.fail(message)
905
 
 
906
 
    def _track_locks(self):
907
 
        """Track lock activity during tests."""
908
 
        self._lock_actions = []
909
 
        if 'disable_lock_checks' in selftest_debug_flags:
910
 
            self._lock_check_thorough = False
911
 
        else:
912
 
            self._lock_check_thorough = True
913
 
            
914
 
        self.addCleanup(self._check_locks)
915
 
        _mod_lock.Lock.hooks.install_named_hook('lock_acquired',
916
 
                                                self._lock_acquired, None)
917
 
        _mod_lock.Lock.hooks.install_named_hook('lock_released',
918
 
                                                self._lock_released, None)
919
 
        _mod_lock.Lock.hooks.install_named_hook('lock_broken',
920
 
                                                self._lock_broken, None)
921
 
 
922
 
    def _lock_acquired(self, result):
923
 
        self._lock_actions.append(('acquired', result))
924
 
 
925
 
    def _lock_released(self, result):
926
 
        self._lock_actions.append(('released', result))
927
 
 
928
 
    def _lock_broken(self, result):
929
 
        self._lock_actions.append(('broken', result))
930
 
 
931
824
    def _ndiff_strings(self, a, b):
932
825
        """Return ndiff between two strings containing lines.
933
 
 
 
826
        
934
827
        A trailing newline is added if missing to make the strings
935
828
        print properly."""
936
829
        if b and b[-1] != '\n':
961
854
 
962
855
    def assertEqualDiff(self, a, b, message=None):
963
856
        """Assert two texts are equal, if not raise an exception.
964
 
 
965
 
        This is intended for use with multi-line strings where it can
 
857
        
 
858
        This is intended for use with multi-line strings where it can 
966
859
        be hard to find the differences by eye.
967
860
        """
968
861
        # TODO: perhaps override assertEquals to call this for strings?
976
869
            message = 'second string is missing a final newline.\n'
977
870
        raise AssertionError(message +
978
871
                             self._ndiff_strings(a, b))
979
 
 
 
872
        
980
873
    def assertEqualMode(self, mode, mode_test):
981
874
        self.assertEqual(mode, mode_test,
982
875
                         'mode mismatch %o != %o' % (mode, mode_test))
983
876
 
984
 
    def assertEqualStat(self, expected, actual):
985
 
        """assert that expected and actual are the same stat result.
986
 
 
987
 
        :param expected: A stat result.
988
 
        :param actual: A stat result.
989
 
        :raises AssertionError: If the expected and actual stat values differ
990
 
            other than by atime.
991
 
        """
992
 
        self.assertEqual(expected.st_size, actual.st_size)
993
 
        self.assertEqual(expected.st_mtime, actual.st_mtime)
994
 
        self.assertEqual(expected.st_ctime, actual.st_ctime)
995
 
        self.assertEqual(expected.st_dev, actual.st_dev)
996
 
        self.assertEqual(expected.st_ino, actual.st_ino)
997
 
        self.assertEqual(expected.st_mode, actual.st_mode)
998
 
 
999
 
    def assertLength(self, length, obj_with_len):
1000
 
        """Assert that obj_with_len is of length length."""
1001
 
        if len(obj_with_len) != length:
1002
 
            self.fail("Incorrect length: wanted %d, got %d for %r" % (
1003
 
                length, len(obj_with_len), obj_with_len))
1004
 
 
1005
877
    def assertPositive(self, val):
1006
878
        """Assert that val is greater than 0."""
1007
879
        self.assertTrue(val > 0, 'expected a positive value, but got %s' % val)
1019
891
        if not s.endswith(suffix):
1020
892
            raise AssertionError('string %r does not end with %r' % (s, suffix))
1021
893
 
1022
 
    def assertContainsRe(self, haystack, needle_re, flags=0):
 
894
    def assertContainsRe(self, haystack, needle_re):
1023
895
        """Assert that a contains something matching a regular expression."""
1024
 
        if not re.search(needle_re, haystack, flags):
 
896
        if not re.search(needle_re, haystack):
1025
897
            if '\n' in haystack or len(haystack) > 60:
1026
898
                # a long string, format it in a more readable way
1027
899
                raise AssertionError(
1031
903
                raise AssertionError('pattern "%s" not found in "%s"'
1032
904
                        % (needle_re, haystack))
1033
905
 
1034
 
    def assertNotContainsRe(self, haystack, needle_re, flags=0):
 
906
    def assertNotContainsRe(self, haystack, needle_re):
1035
907
        """Assert that a does not match a regular expression"""
1036
 
        if re.search(needle_re, haystack, flags):
 
908
        if re.search(needle_re, haystack):
1037
909
            raise AssertionError('pattern "%s" found in "%s"'
1038
910
                    % (needle_re, haystack))
1039
911
 
1046
918
 
1047
919
    def assertListRaises(self, excClass, func, *args, **kwargs):
1048
920
        """Fail unless excClass is raised when the iterator from func is used.
1049
 
 
 
921
        
1050
922
        Many functions can return generators this makes sure
1051
923
        to wrap them in a list() call to make sure the whole generator
1052
924
        is run, and that the proper exception is raised.
1099
971
                raise AssertionError("%r is %r." % (left, right))
1100
972
 
1101
973
    def assertTransportMode(self, transport, path, mode):
1102
 
        """Fail if a path does not have mode "mode".
1103
 
 
 
974
        """Fail if a path does not have mode mode.
 
975
        
1104
976
        If modes are not supported on this transport, the assertion is ignored.
1105
977
        """
1106
978
        if not transport._can_roundtrip_unix_modebits():
1108
980
        path_stat = transport.stat(path)
1109
981
        actual_mode = stat.S_IMODE(path_stat.st_mode)
1110
982
        self.assertEqual(mode, actual_mode,
1111
 
                         'mode of %r incorrect (%s != %s)'
1112
 
                         % (path, oct(mode), oct(actual_mode)))
 
983
            'mode of %r incorrect (%o != %o)' % (path, mode, actual_mode))
1113
984
 
1114
985
    def assertIsSameRealPath(self, path1, path2):
1115
986
        """Fail if path1 and path2 points to different files"""
1117
988
                         osutils.realpath(path2),
1118
989
                         "apparent paths:\na = %s\nb = %s\n," % (path1, path2))
1119
990
 
1120
 
    def assertIsInstance(self, obj, kls, msg=None):
1121
 
        """Fail if obj is not an instance of kls
1122
 
        
1123
 
        :param msg: Supplementary message to show if the assertion fails.
1124
 
        """
 
991
    def assertIsInstance(self, obj, kls):
 
992
        """Fail if obj is not an instance of kls"""
1125
993
        if not isinstance(obj, kls):
1126
 
            m = "%r is an instance of %s rather than %s" % (
1127
 
                obj, obj.__class__, kls)
1128
 
            if msg:
1129
 
                m += ": " + msg
1130
 
            self.fail(m)
 
994
            self.fail("%r is an instance of %s rather than %s" % (
 
995
                obj, obj.__class__, kls))
1131
996
 
1132
997
    def expectFailure(self, reason, assertion, *args, **kwargs):
1133
998
        """Invoke a test, expecting it to fail for the given reason.
1266
1131
        # warnings.  It's the easiest way to insulate ourselves from -Werror,
1267
1132
        # though.  -- Andrew, 20071062
1268
1133
        wlist = []
1269
 
        def _catcher(message, category, filename, lineno, file=None, line=None):
 
1134
        def _catcher(message, category, filename, lineno, file=None):
1270
1135
            # despite the name, 'message' is normally(?) a Warning subclass
1271
1136
            # instance
1272
1137
            wlist.append(message)
1284
1149
    def callDeprecated(self, expected, callable, *args, **kwargs):
1285
1150
        """Assert that a callable is deprecated in a particular way.
1286
1151
 
1287
 
        This is a very precise test for unusual requirements. The
 
1152
        This is a very precise test for unusual requirements. The 
1288
1153
        applyDeprecated helper function is probably more suited for most tests
1289
1154
        as it allows you to simply specify the deprecation format being used
1290
1155
        and will ensure that that is issued for the function being called.
1332
1197
        """Make the logfile not be deleted when _finishLogFile is called."""
1333
1198
        self._keep_log_file = True
1334
1199
 
1335
 
    def thisFailsStrictLockCheck(self):
1336
 
        """It is known that this test would fail with -Dstrict_locks.
1337
 
 
1338
 
        By default, all tests are run with strict lock checking unless
1339
 
        -Edisable_lock_checks is supplied. However there are some tests which
1340
 
        we know fail strict locks at this point that have not been fixed.
1341
 
        They should call this function to disable the strict checking.
1342
 
 
1343
 
        This should be used sparingly, it is much better to fix the locking
1344
 
        issues rather than papering over the problem by calling this function.
1345
 
        """
1346
 
        debug.debug_flags.discard('strict_locks')
1347
 
 
1348
1200
    def addCleanup(self, callable, *args, **kwargs):
1349
1201
        """Arrange to run a callable when this case is torn down.
1350
1202
 
1351
 
        Callables are run in the reverse of the order they are registered,
 
1203
        Callables are run in the reverse of the order they are registered, 
1352
1204
        ie last-in first-out.
1353
1205
        """
1354
1206
        self._cleanups.append((callable, args, kwargs))
1357
1209
        new_env = {
1358
1210
            'BZR_HOME': None, # Don't inherit BZR_HOME to all the tests.
1359
1211
            'HOME': os.getcwd(),
1360
 
            # bzr now uses the Win32 API and doesn't rely on APPDATA, but the
1361
 
            # tests do check our impls match APPDATA
 
1212
            'APPDATA': None,  # bzr now use Win32 API and don't rely on APPDATA
1362
1213
            'BZR_EDITOR': None, # test_msgeditor manipulates this variable
1363
 
            'VISUAL': None,
1364
 
            'EDITOR': None,
1365
1214
            'BZR_EMAIL': None,
1366
1215
            'BZREMAIL': None, # may still be present in the environment
1367
1216
            'EMAIL': None,
1368
1217
            'BZR_PROGRESS_BAR': None,
1369
1218
            'BZR_LOG': None,
1370
 
            'BZR_PLUGIN_PATH': None,
1371
 
            # Make sure that any text ui tests are consistent regardless of
1372
 
            # the environment the test case is run in; you may want tests that
1373
 
            # test other combinations.  'dumb' is a reasonable guess for tests
1374
 
            # going to a pipe or a StringIO.
1375
 
            'TERM': 'dumb',
1376
 
            'LINES': '25',
1377
 
            'COLUMNS': '80',
1378
1219
            # SSH Agent
1379
1220
            'SSH_AUTH_SOCK': None,
1380
1221
            # Proxies
1386
1227
            'NO_PROXY': None,
1387
1228
            'all_proxy': None,
1388
1229
            'ALL_PROXY': None,
1389
 
            # Nobody cares about ftp_proxy, FTP_PROXY AFAIK. So far at
 
1230
            # Nobody cares about these ones AFAIK. So far at
1390
1231
            # least. If you do (care), please update this comment
1391
 
            # -- vila 20080401
 
1232
            # -- vila 20061212
1392
1233
            'ftp_proxy': None,
1393
1234
            'FTP_PROXY': None,
1394
1235
            'BZR_REMOTE_PATH': None,
1411
1252
            osutils.set_or_unset_env(name, value)
1412
1253
 
1413
1254
    def _restoreHooks(self):
1414
 
        for klass, (name, hooks) in self._preserved_hooks.items():
1415
 
            setattr(klass, name, hooks)
 
1255
        for klass, hooks in self._preserved_hooks.items():
 
1256
            setattr(klass, 'hooks', hooks)
1416
1257
 
1417
1258
    def knownFailure(self, reason):
1418
1259
        """This test has failed for some known reason."""
1419
1260
        raise KnownFailure(reason)
1420
1261
 
1421
 
    def _do_skip(self, result, reason):
1422
 
        addSkip = getattr(result, 'addSkip', None)
1423
 
        if not callable(addSkip):
1424
 
            result.addError(self, sys.exc_info())
1425
 
        else:
1426
 
            addSkip(self, reason)
1427
 
 
1428
1262
    def run(self, result=None):
1429
1263
        if result is None: result = self.defaultTestResult()
1430
1264
        for feature in getattr(self, '_test_needs_features', []):
1435
1269
                else:
1436
1270
                    result.addSuccess(self)
1437
1271
                result.stopTest(self)
1438
 
                return result
 
1272
                return
1439
1273
        try:
1440
 
            try:
1441
 
                result.startTest(self)
1442
 
                absent_attr = object()
1443
 
                # Python 2.5
1444
 
                method_name = getattr(self, '_testMethodName', absent_attr)
1445
 
                if method_name is absent_attr:
1446
 
                    # Python 2.4
1447
 
                    method_name = getattr(self, '_TestCase__testMethodName')
1448
 
                testMethod = getattr(self, method_name)
1449
 
                try:
1450
 
                    try:
1451
 
                        self.setUp()
1452
 
                        if not self._bzr_test_setUp_run:
1453
 
                            self.fail(
1454
 
                                "test setUp did not invoke "
1455
 
                                "bzrlib.tests.TestCase's setUp")
1456
 
                    except KeyboardInterrupt:
1457
 
                        self._runCleanups()
1458
 
                        raise
1459
 
                    except TestSkipped, e:
1460
 
                        self._do_skip(result, e.args[0])
1461
 
                        self.tearDown()
1462
 
                        return result
1463
 
                    except:
1464
 
                        result.addError(self, sys.exc_info())
1465
 
                        self._runCleanups()
1466
 
                        return result
1467
 
 
1468
 
                    ok = False
1469
 
                    try:
1470
 
                        testMethod()
1471
 
                        ok = True
1472
 
                    except self.failureException:
1473
 
                        result.addFailure(self, sys.exc_info())
1474
 
                    except TestSkipped, e:
1475
 
                        if not e.args:
1476
 
                            reason = "No reason given."
1477
 
                        else:
1478
 
                            reason = e.args[0]
1479
 
                        self._do_skip(result, reason)
1480
 
                    except KeyboardInterrupt:
1481
 
                        self._runCleanups()
1482
 
                        raise
1483
 
                    except:
1484
 
                        result.addError(self, sys.exc_info())
1485
 
 
1486
 
                    try:
1487
 
                        self.tearDown()
1488
 
                        if not self._bzr_test_tearDown_run:
1489
 
                            self.fail(
1490
 
                                "test tearDown did not invoke "
1491
 
                                "bzrlib.tests.TestCase's tearDown")
1492
 
                    except KeyboardInterrupt:
1493
 
                        self._runCleanups()
1494
 
                        raise
1495
 
                    except:
1496
 
                        result.addError(self, sys.exc_info())
1497
 
                        self._runCleanups()
1498
 
                        ok = False
1499
 
                    if ok: result.addSuccess(self)
1500
 
                finally:
1501
 
                    result.stopTest(self)
1502
 
                return result
1503
 
            except TestNotApplicable:
1504
 
                # Not moved from the result [yet].
1505
 
                self._runCleanups()
1506
 
                raise
1507
 
            except KeyboardInterrupt:
1508
 
                self._runCleanups()
1509
 
                raise
 
1274
            return unittest.TestCase.run(self, result)
1510
1275
        finally:
1511
1276
            saved_attrs = {}
 
1277
            absent_attr = object()
1512
1278
            for attr_name in self.attrs_to_keep:
1513
 
                if attr_name in self.__dict__:
1514
 
                    saved_attrs[attr_name] = self.__dict__[attr_name]
 
1279
                attr = getattr(self, attr_name, absent_attr)
 
1280
                if attr is not absent_attr:
 
1281
                    saved_attrs[attr_name] = attr
1515
1282
            self.__dict__ = saved_attrs
1516
1283
 
1517
1284
    def tearDown(self):
1518
1285
        self._runCleanups()
1519
 
        self._log_contents = ''
1520
 
        self._bzr_test_tearDown_run = True
1521
1286
        unittest.TestCase.tearDown(self)
1522
1287
 
1523
1288
    def time(self, callable, *args, **kwargs):
1524
1289
        """Run callable and accrue the time it takes to the benchmark time.
1525
 
 
 
1290
        
1526
1291
        If lsprofiling is enabled (i.e. by --lsprof-time to bzr selftest) then
1527
1292
        this will cause lsprofile statistics to be gathered and stored in
1528
1293
        self._benchcalls.
1543
1308
            self._benchtime += time.time() - start
1544
1309
 
1545
1310
    def _runCleanups(self):
1546
 
        """Run registered cleanup functions.
 
1311
        """Run registered cleanup functions. 
1547
1312
 
1548
1313
        This should only be called from TestCase.tearDown.
1549
1314
        """
1550
 
        # TODO: Perhaps this should keep running cleanups even if
 
1315
        # TODO: Perhaps this should keep running cleanups even if 
1551
1316
        # one of them fails?
1552
1317
 
1553
1318
        # Actually pop the cleanups from the list so tearDown running
1570
1335
        """
1571
1336
        # flush the log file, to get all content
1572
1337
        import bzrlib.trace
1573
 
        if bzrlib.trace._trace_file:
1574
 
            bzrlib.trace._trace_file.flush()
 
1338
        bzrlib.trace._trace_file.flush()
1575
1339
        if self._log_contents:
1576
1340
            # XXX: this can hardly contain the content flushed above --vila
1577
1341
            # 20080128
1618
1382
    def _run_bzr_core(self, args, retcode, encoding, stdin,
1619
1383
            working_dir):
1620
1384
        if encoding is None:
1621
 
            encoding = osutils.get_user_encoding()
 
1385
            encoding = bzrlib.user_encoding
1622
1386
        stdout = StringIOWrapper()
1623
1387
        stderr = StringIOWrapper()
1624
1388
        stdout.encoding = encoding
1669
1433
        passed in three ways:
1670
1434
 
1671
1435
        1- A list of strings, eg ["commit", "a"].  This is recommended
1672
 
        when the command contains whitespace or metacharacters, or
 
1436
        when the command contains whitespace or metacharacters, or 
1673
1437
        is built up at run time.
1674
1438
 
1675
 
        2- A single string, eg "add a".  This is the most convenient
 
1439
        2- A single string, eg "add a".  This is the most convenient 
1676
1440
        for hardcoded commands.
1677
1441
 
1678
1442
        This runs bzr through the interface that catches and reports
1700
1464
            stdin=stdin,
1701
1465
            working_dir=working_dir,
1702
1466
            )
1703
 
        self.assertIsInstance(error_regexes, (list, tuple))
1704
1467
        for regex in error_regexes:
1705
1468
            self.assertContainsRe(err, regex)
1706
1469
        return out, err
1738
1501
    def run_bzr_subprocess(self, *args, **kwargs):
1739
1502
        """Run bzr in a subprocess for testing.
1740
1503
 
1741
 
        This starts a new Python interpreter and runs bzr in there.
 
1504
        This starts a new Python interpreter and runs bzr in there. 
1742
1505
        This should only be used for tests that have a justifiable need for
1743
1506
        this isolation: e.g. they are testing startup time, or signal
1744
 
        handling, or early startup code, etc.  Subprocess code can't be
 
1507
        handling, or early startup code, etc.  Subprocess code can't be 
1745
1508
        profiled or debugged so easily.
1746
1509
 
1747
1510
        :keyword retcode: The status code that is expected.  Defaults to 0.  If
1962
1725
        sio.encoding = output_encoding
1963
1726
        return sio
1964
1727
 
1965
 
    def disable_verb(self, verb):
1966
 
        """Disable a smart server verb for one test."""
1967
 
        from bzrlib.smart import request
1968
 
        request_handlers = request.request_handlers
1969
 
        orig_method = request_handlers.get(verb)
1970
 
        request_handlers.remove(verb)
1971
 
        def restoreVerb():
1972
 
            request_handlers.register(verb, orig_method)
1973
 
        self.addCleanup(restoreVerb)
1974
 
 
1975
 
 
1976
 
class CapturedCall(object):
1977
 
    """A helper for capturing smart server calls for easy debug analysis."""
1978
 
 
1979
 
    def __init__(self, params, prefix_length):
1980
 
        """Capture the call with params and skip prefix_length stack frames."""
1981
 
        self.call = params
1982
 
        import traceback
1983
 
        # The last 5 frames are the __init__, the hook frame, and 3 smart
1984
 
        # client frames. Beyond this we could get more clever, but this is good
1985
 
        # enough for now.
1986
 
        stack = traceback.extract_stack()[prefix_length:-5]
1987
 
        self.stack = ''.join(traceback.format_list(stack))
1988
 
 
1989
 
    def __str__(self):
1990
 
        return self.call.method
1991
 
 
1992
 
    def __repr__(self):
1993
 
        return self.call.method
1994
 
 
1995
 
    def stack(self):
1996
 
        return self.stack
1997
 
 
1998
1728
 
1999
1729
class TestCaseWithMemoryTransport(TestCase):
2000
1730
    """Common test class for tests that do not need disk resources.
2020
1750
 
2021
1751
    def __init__(self, methodName='runTest'):
2022
1752
        # allow test parameterization after test construction and before test
2023
 
        # execution. Variables that the parameterizer sets need to be
 
1753
        # execution. Variables that the parameterizer sets need to be 
2024
1754
        # ones that are not set by setUp, or setUp will trash them.
2025
1755
        super(TestCaseWithMemoryTransport, self).__init__(methodName)
2026
1756
        self.vfs_transport_factory = default_transport
2033
1763
 
2034
1764
        This transport is for the test scratch space relative to
2035
1765
        "self._test_root"
2036
 
 
 
1766
        
2037
1767
        :param relpath: a path relative to the base url.
2038
1768
        """
2039
1769
        t = get_transport(self.get_url(relpath))
2042
1772
 
2043
1773
    def get_readonly_transport(self, relpath=None):
2044
1774
        """Return a readonly transport for the test scratch space
2045
 
 
 
1775
        
2046
1776
        This can be used to test that operations which should only need
2047
1777
        readonly access in fact do not try to write.
2048
1778
 
2079
1809
    def get_readonly_url(self, relpath=None):
2080
1810
        """Get a URL for the readonly transport.
2081
1811
 
2082
 
        This will either be backed by '.' or a decorator to the transport
 
1812
        This will either be backed by '.' or a decorator to the transport 
2083
1813
        used by self.get_url()
2084
1814
        relpath provides for clients to get a path relative to the base url.
2085
1815
        These should only be downwards relative, not upwards.
2218
1948
 
2219
1949
    def makeAndChdirToTestDir(self):
2220
1950
        """Create a temporary directories for this one test.
2221
 
 
 
1951
        
2222
1952
        This must set self.test_home_dir and self.test_dir and chdir to
2223
1953
        self.test_dir.
2224
 
 
 
1954
        
2225
1955
        For TestCaseWithMemoryTransport we chdir to the TEST_ROOT for this test.
2226
1956
        """
2227
1957
        os.chdir(TestCaseWithMemoryTransport.TEST_ROOT)
2228
1958
        self.test_dir = TestCaseWithMemoryTransport.TEST_ROOT
2229
1959
        self.test_home_dir = self.test_dir + "/MemoryTransportMissingHomeDir"
2230
 
 
 
1960
        
2231
1961
    def make_branch(self, relpath, format=None):
2232
1962
        """Create a branch on the transport at relpath."""
2233
1963
        repo = self.make_repository(relpath, format=format)
2251
1981
 
2252
1982
    def make_repository(self, relpath, shared=False, format=None):
2253
1983
        """Create a repository on our default transport at relpath.
2254
 
 
 
1984
        
2255
1985
        Note that relpath must be a relative path, not a full url.
2256
1986
        """
2257
1987
        # FIXME: If you create a remoterepository this returns the underlying
2258
 
        # real format, which is incorrect.  Actually we should make sure that
 
1988
        # real format, which is incorrect.  Actually we should make sure that 
2259
1989
        # RemoteBzrDir returns a RemoteRepository.
2260
1990
        # maybe  mbp 20070410
2261
1991
        made_control = self.make_bzrdir(relpath, format=format)
2262
1992
        return made_control.create_repository(shared=shared)
2263
1993
 
2264
 
    def make_smart_server(self, path):
2265
 
        smart_server = server.SmartTCPServer_for_testing()
2266
 
        smart_server.setUp(self.get_server())
2267
 
        remote_transport = get_transport(smart_server.get_url()).clone(path)
2268
 
        self.addCleanup(smart_server.tearDown)
2269
 
        return remote_transport
2270
 
 
2271
1994
    def make_branch_and_memory_tree(self, relpath, format=None):
2272
1995
        """Create a branch on the default transport and a MemoryTree for it."""
2273
1996
        b = self.make_branch(relpath, format=format)
2274
1997
        return memorytree.MemoryTree.create_on_branch(b)
2275
1998
 
2276
1999
    def make_branch_builder(self, relpath, format=None):
2277
 
        branch = self.make_branch(relpath, format=format)
2278
 
        return branchbuilder.BranchBuilder(branch=branch)
 
2000
        url = self.get_url(relpath)
 
2001
        tran = get_transport(url)
 
2002
        return branchbuilder.BranchBuilder(get_transport(url), format=format)
2279
2003
 
2280
2004
    def overrideEnvironmentForTesting(self):
2281
2005
        os.environ['HOME'] = self.test_home_dir
2282
2006
        os.environ['BZR_HOME'] = self.test_home_dir
2283
 
 
 
2007
        
2284
2008
    def setUp(self):
2285
2009
        super(TestCaseWithMemoryTransport, self).setUp()
2286
2010
        self._make_test_root()
2294
2018
        self.__server = None
2295
2019
        self.reduceLockdirTimeout()
2296
2020
 
2297
 
    def setup_smart_server_with_call_log(self):
2298
 
        """Sets up a smart server as the transport server with a call log."""
2299
 
        self.transport_server = server.SmartTCPServer_for_testing
2300
 
        self.hpss_calls = []
2301
 
        import traceback
2302
 
        # Skip the current stack down to the caller of
2303
 
        # setup_smart_server_with_call_log
2304
 
        prefix_length = len(traceback.extract_stack()) - 2
2305
 
        def capture_hpss_call(params):
2306
 
            self.hpss_calls.append(
2307
 
                CapturedCall(params, prefix_length))
2308
 
        client._SmartClient.hooks.install_named_hook(
2309
 
            'call', capture_hpss_call, None)
2310
 
 
2311
 
    def reset_smart_call_log(self):
2312
 
        self.hpss_calls = []
2313
 
 
2314
 
 
 
2021
     
2315
2022
class TestCaseInTempDir(TestCaseWithMemoryTransport):
2316
2023
    """Derived class that runs a test within a temporary directory.
2317
2024
 
2322
2029
    All test cases create their own directory within that.  If the
2323
2030
    tests complete successfully, the directory is removed.
2324
2031
 
2325
 
    :ivar test_base_dir: The path of the top-level directory for this
 
2032
    :ivar test_base_dir: The path of the top-level directory for this 
2326
2033
    test, which contains a home directory and a work directory.
2327
2034
 
2328
2035
    :ivar test_home_dir: An initially empty directory under test_base_dir
2344
2051
 
2345
2052
    def _getTestDirPrefix(self):
2346
2053
        # create a directory within the top level test directory
2347
 
        if sys.platform in ('win32', 'cygwin'):
 
2054
        if sys.platform == 'win32':
2348
2055
            name_prefix = re.sub('[<>*=+",:;_/\\-]', '_', self.id())
2349
2056
            # windows is likely to have path-length limits so use a short name
2350
2057
            name_prefix = name_prefix[-30:]
2354
2061
 
2355
2062
    def makeAndChdirToTestDir(self):
2356
2063
        """See TestCaseWithMemoryTransport.makeAndChdirToTestDir().
2357
 
 
 
2064
        
2358
2065
        For TestCaseInTempDir we create a temporary directory based on the test
2359
2066
        name and then create two subdirs - test and home under it.
2360
2067
        """
2361
 
        name_prefix = osutils.pathjoin(TestCaseWithMemoryTransport.TEST_ROOT,
2362
 
            self._getTestDirPrefix())
 
2068
        name_prefix = osutils.pathjoin(self.TEST_ROOT, self._getTestDirPrefix())
2363
2069
        name = name_prefix
2364
2070
        for i in range(100):
2365
2071
            if os.path.exists(name):
2383
2089
        self.addCleanup(self.deleteTestDir)
2384
2090
 
2385
2091
    def deleteTestDir(self):
2386
 
        os.chdir(TestCaseWithMemoryTransport.TEST_ROOT)
 
2092
        os.chdir(self.TEST_ROOT)
2387
2093
        _rmtree_temp_dir(self.test_base_dir)
2388
2094
 
2389
2095
    def build_tree(self, shape, line_endings='binary', transport=None):
2411
2117
        if transport is None or transport.is_readonly():
2412
2118
            transport = get_transport(".")
2413
2119
        for name in shape:
2414
 
            self.assertIsInstance(name, basestring)
 
2120
            self.assert_(isinstance(name, basestring))
2415
2121
            if name[-1] == '/':
2416
2122
                transport.mkdir(urlutils.escape(name[:-1]))
2417
2123
            else:
2460
2166
    ReadonlyTransportDecorator is used instead which allows the use of non disk
2461
2167
    based read write transports.
2462
2168
 
2463
 
    If an explicit class is provided for readonly access, that server and the
 
2169
    If an explicit class is provided for readonly access, that server and the 
2464
2170
    readwrite one must both define get_url() as resolving to os.getcwd().
2465
2171
    """
2466
2172
 
2552
2258
    for readonly urls.
2553
2259
 
2554
2260
    TODO RBC 20060127: make this an option to TestCaseWithTransport so it can
2555
 
                       be used without needed to redo it when a different
 
2261
                       be used without needed to redo it when a different 
2556
2262
                       subclass is in use ?
2557
2263
    """
2558
2264
 
2564
2270
 
2565
2271
def condition_id_re(pattern):
2566
2272
    """Create a condition filter which performs a re check on a test's id.
2567
 
 
 
2273
    
2568
2274
    :param pattern: A regular expression string.
2569
2275
    :return: A callable that returns True if the re matches.
2570
2276
    """
2571
 
    filter_re = osutils.re_compile_checked(pattern, 0,
2572
 
        'test filter')
 
2277
    filter_re = re.compile(pattern)
2573
2278
    def condition(test):
2574
2279
        test_id = test.id()
2575
2280
        return filter_re.search(test_id)
2578
2283
 
2579
2284
def condition_isinstance(klass_or_klass_list):
2580
2285
    """Create a condition filter which returns isinstance(param, klass).
2581
 
 
 
2286
    
2582
2287
    :return: A callable which when called with one parameter obj return the
2583
2288
        result of isinstance(obj, klass_or_klass_list).
2584
2289
    """
2589
2294
 
2590
2295
def condition_id_in_list(id_list):
2591
2296
    """Create a condition filter which verify that test's id in a list.
2592
 
 
 
2297
    
2593
2298
    :param id_list: A TestIdList object.
2594
2299
    :return: A callable that returns True if the test's id appears in the list.
2595
2300
    """
2600
2305
 
2601
2306
def condition_id_startswith(starts):
2602
2307
    """Create a condition filter verifying that test's id starts with a string.
2603
 
 
 
2308
    
2604
2309
    :param starts: A list of string.
2605
 
    :return: A callable that returns True if the test's id starts with one of
 
2310
    :return: A callable that returns True if the test's id starts with one of 
2606
2311
        the given strings.
2607
2312
    """
2608
2313
    def condition(test):
2631
2336
 
2632
2337
def filter_suite_by_condition(suite, condition):
2633
2338
    """Create a test suite by filtering another one.
2634
 
 
 
2339
    
2635
2340
    :param suite: The source suite.
2636
2341
    :param condition: A callable whose result evaluates True when called with a
2637
2342
        test case which should be included in the result.
2647
2352
 
2648
2353
def filter_suite_by_re(suite, pattern):
2649
2354
    """Create a test suite by filtering another one.
2650
 
 
 
2355
    
2651
2356
    :param suite:           the source suite
2652
2357
    :param pattern:         pattern that names must match
2653
2358
    :returns: the newly created suite
2705
2410
 
2706
2411
def randomize_suite(suite):
2707
2412
    """Return a new TestSuite with suite's tests in random order.
2708
 
 
 
2413
    
2709
2414
    The tests in the input suite are flattened into a single suite in order to
2710
2415
    accomplish this. Any nested TestSuites are removed to provide global
2711
2416
    randomness.
2717
2422
 
2718
2423
def split_suite_by_condition(suite, condition):
2719
2424
    """Split a test suite into two by a condition.
2720
 
 
 
2425
    
2721
2426
    :param suite: The suite to split.
2722
2427
    :param condition: The condition to match on. Tests that match this
2723
2428
        condition are returned in the first test suite, ones that do not match
2739
2444
 
2740
2445
def split_suite_by_re(suite, pattern):
2741
2446
    """Split a test suite into two by a regular expression.
2742
 
 
 
2447
    
2743
2448
    :param suite: The suite to split.
2744
2449
    :param pattern: A regular expression string. Test ids that match this
2745
2450
        pattern will be in the first test suite returned, and the others in the
2759
2464
              list_only=False,
2760
2465
              random_seed=None,
2761
2466
              exclude_pattern=None,
2762
 
              strict=False,
2763
 
              runner_class=None,
2764
 
              suite_decorators=None,
2765
 
              stream=None):
2766
 
    """Run a test suite for bzr selftest.
2767
 
 
2768
 
    :param runner_class: The class of runner to use. Must support the
2769
 
        constructor arguments passed by run_suite which are more than standard
2770
 
        python uses.
2771
 
    :return: A boolean indicating success.
2772
 
    """
 
2467
              strict=False):
2773
2468
    TestCase._gather_lsprof_in_benchmarks = lsprof_timed
2774
2469
    if verbose:
2775
2470
        verbosity = 2
2776
2471
    else:
2777
2472
        verbosity = 1
2778
 
    if runner_class is None:
2779
 
        runner_class = TextTestRunner
2780
 
    if stream is None:
2781
 
        stream = sys.stdout
2782
 
    runner = runner_class(stream=stream,
 
2473
    runner = TextTestRunner(stream=sys.stdout,
2783
2474
                            descriptions=0,
2784
2475
                            verbosity=verbosity,
2785
2476
                            bench_history=bench_history,
2786
2477
                            list_only=list_only,
2787
 
                            strict=strict,
2788
2478
                            )
2789
2479
    runner.stop_on_failure=stop_on_failure
2790
 
    # built in decorator factories:
2791
 
    decorators = [
2792
 
        random_order(random_seed, runner),
2793
 
        exclude_tests(exclude_pattern),
2794
 
        ]
2795
 
    if matching_tests_first:
2796
 
        decorators.append(tests_first(pattern))
 
2480
    # Initialise the random number generator and display the seed used.
 
2481
    # We convert the seed to a long to make it reuseable across invocations.
 
2482
    random_order = False
 
2483
    if random_seed is not None:
 
2484
        random_order = True
 
2485
        if random_seed == "now":
 
2486
            random_seed = long(time.time())
 
2487
        else:
 
2488
            # Convert the seed to a long if we can
 
2489
            try:
 
2490
                random_seed = long(random_seed)
 
2491
            except:
 
2492
                pass
 
2493
        runner.stream.writeln("Randomizing test order using seed %s\n" %
 
2494
            (random_seed))
 
2495
        random.seed(random_seed)
 
2496
    # Customise the list of tests if requested
 
2497
    if exclude_pattern is not None:
 
2498
        suite = exclude_tests_by_re(suite, exclude_pattern)
 
2499
    if random_order:
 
2500
        order_changer = randomize_suite
2797
2501
    else:
2798
 
        decorators.append(filter_tests(pattern))
2799
 
    if suite_decorators:
2800
 
        decorators.extend(suite_decorators)
2801
 
    # tell the result object how many tests will be running: (except if
2802
 
    # --parallel=fork is being used. Robert said he will provide a better
2803
 
    # progress design later -- vila 20090817)
2804
 
    if fork_decorator not in decorators:
2805
 
        decorators.append(CountingDecorator)
2806
 
    for decorator in decorators:
2807
 
        suite = decorator(suite)
 
2502
        order_changer = preserve_input
 
2503
    if pattern != '.*' or random_order:
 
2504
        if matching_tests_first:
 
2505
            suites = map(order_changer, split_suite_by_re(suite, pattern))
 
2506
            suite = TestUtil.TestSuite(suites)
 
2507
        else:
 
2508
            suite = order_changer(filter_suite_by_re(suite, pattern))
 
2509
 
2808
2510
    result = runner.run(suite)
2809
 
    if list_only:
2810
 
        return True
2811
 
    result.done()
 
2511
 
2812
2512
    if strict:
2813
2513
        return result.wasStrictlySuccessful()
2814
 
    else:
2815
 
        return result.wasSuccessful()
2816
 
 
2817
 
 
2818
 
# A registry where get() returns a suite decorator.
2819
 
parallel_registry = registry.Registry()
2820
 
 
2821
 
 
2822
 
def fork_decorator(suite):
2823
 
    concurrency = osutils.local_concurrency()
2824
 
    if concurrency == 1:
2825
 
        return suite
2826
 
    from testtools import ConcurrentTestSuite
2827
 
    return ConcurrentTestSuite(suite, fork_for_tests)
2828
 
parallel_registry.register('fork', fork_decorator)
2829
 
 
2830
 
 
2831
 
def subprocess_decorator(suite):
2832
 
    concurrency = osutils.local_concurrency()
2833
 
    if concurrency == 1:
2834
 
        return suite
2835
 
    from testtools import ConcurrentTestSuite
2836
 
    return ConcurrentTestSuite(suite, reinvoke_for_tests)
2837
 
parallel_registry.register('subprocess', subprocess_decorator)
2838
 
 
2839
 
 
2840
 
def exclude_tests(exclude_pattern):
2841
 
    """Return a test suite decorator that excludes tests."""
2842
 
    if exclude_pattern is None:
2843
 
        return identity_decorator
2844
 
    def decorator(suite):
2845
 
        return ExcludeDecorator(suite, exclude_pattern)
2846
 
    return decorator
2847
 
 
2848
 
 
2849
 
def filter_tests(pattern):
2850
 
    if pattern == '.*':
2851
 
        return identity_decorator
2852
 
    def decorator(suite):
2853
 
        return FilterTestsDecorator(suite, pattern)
2854
 
    return decorator
2855
 
 
2856
 
 
2857
 
def random_order(random_seed, runner):
2858
 
    """Return a test suite decorator factory for randomising tests order.
2859
 
    
2860
 
    :param random_seed: now, a string which casts to a long, or a long.
2861
 
    :param runner: A test runner with a stream attribute to report on.
2862
 
    """
2863
 
    if random_seed is None:
2864
 
        return identity_decorator
2865
 
    def decorator(suite):
2866
 
        return RandomDecorator(suite, random_seed, runner.stream)
2867
 
    return decorator
2868
 
 
2869
 
 
2870
 
def tests_first(pattern):
2871
 
    if pattern == '.*':
2872
 
        return identity_decorator
2873
 
    def decorator(suite):
2874
 
        return TestFirstDecorator(suite, pattern)
2875
 
    return decorator
2876
 
 
2877
 
 
2878
 
def identity_decorator(suite):
2879
 
    """Return suite."""
2880
 
    return suite
2881
 
 
2882
 
 
2883
 
class TestDecorator(TestSuite):
2884
 
    """A decorator for TestCase/TestSuite objects.
2885
 
    
2886
 
    Usually, subclasses should override __iter__(used when flattening test
2887
 
    suites), which we do to filter, reorder, parallelise and so on, run() and
2888
 
    debug().
2889
 
    """
2890
 
 
2891
 
    def __init__(self, suite):
2892
 
        TestSuite.__init__(self)
2893
 
        self.addTest(suite)
2894
 
 
2895
 
    def countTestCases(self):
2896
 
        cases = 0
2897
 
        for test in self:
2898
 
            cases += test.countTestCases()
2899
 
        return cases
2900
 
 
2901
 
    def debug(self):
2902
 
        for test in self:
2903
 
            test.debug()
2904
 
 
2905
 
    def run(self, result):
2906
 
        # Use iteration on self, not self._tests, to allow subclasses to hook
2907
 
        # into __iter__.
2908
 
        for test in self:
2909
 
            if result.shouldStop:
2910
 
                break
2911
 
            test.run(result)
2912
 
        return result
2913
 
 
2914
 
 
2915
 
class CountingDecorator(TestDecorator):
2916
 
    """A decorator which calls result.progress(self.countTestCases)."""
2917
 
 
2918
 
    def run(self, result):
2919
 
        progress_method = getattr(result, 'progress', None)
2920
 
        if callable(progress_method):
2921
 
            progress_method(self.countTestCases(), SUBUNIT_SEEK_SET)
2922
 
        return super(CountingDecorator, self).run(result)
2923
 
 
2924
 
 
2925
 
class ExcludeDecorator(TestDecorator):
2926
 
    """A decorator which excludes test matching an exclude pattern."""
2927
 
 
2928
 
    def __init__(self, suite, exclude_pattern):
2929
 
        TestDecorator.__init__(self, suite)
2930
 
        self.exclude_pattern = exclude_pattern
2931
 
        self.excluded = False
2932
 
 
2933
 
    def __iter__(self):
2934
 
        if self.excluded:
2935
 
            return iter(self._tests)
2936
 
        self.excluded = True
2937
 
        suite = exclude_tests_by_re(self, self.exclude_pattern)
2938
 
        del self._tests[:]
2939
 
        self.addTests(suite)
2940
 
        return iter(self._tests)
2941
 
 
2942
 
 
2943
 
class FilterTestsDecorator(TestDecorator):
2944
 
    """A decorator which filters tests to those matching a pattern."""
2945
 
 
2946
 
    def __init__(self, suite, pattern):
2947
 
        TestDecorator.__init__(self, suite)
2948
 
        self.pattern = pattern
2949
 
        self.filtered = False
2950
 
 
2951
 
    def __iter__(self):
2952
 
        if self.filtered:
2953
 
            return iter(self._tests)
2954
 
        self.filtered = True
2955
 
        suite = filter_suite_by_re(self, self.pattern)
2956
 
        del self._tests[:]
2957
 
        self.addTests(suite)
2958
 
        return iter(self._tests)
2959
 
 
2960
 
 
2961
 
class RandomDecorator(TestDecorator):
2962
 
    """A decorator which randomises the order of its tests."""
2963
 
 
2964
 
    def __init__(self, suite, random_seed, stream):
2965
 
        TestDecorator.__init__(self, suite)
2966
 
        self.random_seed = random_seed
2967
 
        self.randomised = False
2968
 
        self.stream = stream
2969
 
 
2970
 
    def __iter__(self):
2971
 
        if self.randomised:
2972
 
            return iter(self._tests)
2973
 
        self.randomised = True
2974
 
        self.stream.writeln("Randomizing test order using seed %s\n" %
2975
 
            (self.actual_seed()))
2976
 
        # Initialise the random number generator.
2977
 
        random.seed(self.actual_seed())
2978
 
        suite = randomize_suite(self)
2979
 
        del self._tests[:]
2980
 
        self.addTests(suite)
2981
 
        return iter(self._tests)
2982
 
 
2983
 
    def actual_seed(self):
2984
 
        if self.random_seed == "now":
2985
 
            # We convert the seed to a long to make it reuseable across
2986
 
            # invocations (because the user can reenter it).
2987
 
            self.random_seed = long(time.time())
2988
 
        else:
2989
 
            # Convert the seed to a long if we can
2990
 
            try:
2991
 
                self.random_seed = long(self.random_seed)
2992
 
            except:
2993
 
                pass
2994
 
        return self.random_seed
2995
 
 
2996
 
 
2997
 
class TestFirstDecorator(TestDecorator):
2998
 
    """A decorator which moves named tests to the front."""
2999
 
 
3000
 
    def __init__(self, suite, pattern):
3001
 
        TestDecorator.__init__(self, suite)
3002
 
        self.pattern = pattern
3003
 
        self.filtered = False
3004
 
 
3005
 
    def __iter__(self):
3006
 
        if self.filtered:
3007
 
            return iter(self._tests)
3008
 
        self.filtered = True
3009
 
        suites = split_suite_by_re(self, self.pattern)
3010
 
        del self._tests[:]
3011
 
        self.addTests(suites)
3012
 
        return iter(self._tests)
3013
 
 
3014
 
 
3015
 
def partition_tests(suite, count):
3016
 
    """Partition suite into count lists of tests."""
3017
 
    result = []
3018
 
    tests = list(iter_suite_tests(suite))
3019
 
    tests_per_process = int(math.ceil(float(len(tests)) / count))
3020
 
    for block in range(count):
3021
 
        low_test = block * tests_per_process
3022
 
        high_test = low_test + tests_per_process
3023
 
        process_tests = tests[low_test:high_test]
3024
 
        result.append(process_tests)
3025
 
    return result
3026
 
 
3027
 
 
3028
 
def fork_for_tests(suite):
3029
 
    """Take suite and start up one runner per CPU by forking()
3030
 
 
3031
 
    :return: An iterable of TestCase-like objects which can each have
3032
 
        run(result) called on them to feed tests to result.
3033
 
    """
3034
 
    concurrency = osutils.local_concurrency()
3035
 
    result = []
3036
 
    from subunit import TestProtocolClient, ProtocolTestCase
3037
 
    try:
3038
 
        from subunit.test_results import AutoTimingTestResultDecorator
3039
 
    except ImportError:
3040
 
        AutoTimingTestResultDecorator = lambda x:x
3041
 
    class TestInOtherProcess(ProtocolTestCase):
3042
 
        # Should be in subunit, I think. RBC.
3043
 
        def __init__(self, stream, pid):
3044
 
            ProtocolTestCase.__init__(self, stream)
3045
 
            self.pid = pid
3046
 
 
3047
 
        def run(self, result):
3048
 
            try:
3049
 
                ProtocolTestCase.run(self, result)
3050
 
            finally:
3051
 
                os.waitpid(self.pid, os.WNOHANG)
3052
 
 
3053
 
    test_blocks = partition_tests(suite, concurrency)
3054
 
    for process_tests in test_blocks:
3055
 
        process_suite = TestSuite()
3056
 
        process_suite.addTests(process_tests)
3057
 
        c2pread, c2pwrite = os.pipe()
3058
 
        pid = os.fork()
3059
 
        if pid == 0:
3060
 
            try:
3061
 
                os.close(c2pread)
3062
 
                # Leave stderr and stdout open so we can see test noise
3063
 
                # Close stdin so that the child goes away if it decides to
3064
 
                # read from stdin (otherwise its a roulette to see what
3065
 
                # child actually gets keystrokes for pdb etc).
3066
 
                sys.stdin.close()
3067
 
                sys.stdin = None
3068
 
                stream = os.fdopen(c2pwrite, 'wb', 1)
3069
 
                subunit_result = AutoTimingTestResultDecorator(
3070
 
                    TestProtocolClient(stream))
3071
 
                process_suite.run(subunit_result)
3072
 
            finally:
3073
 
                os._exit(0)
3074
 
        else:
3075
 
            os.close(c2pwrite)
3076
 
            stream = os.fdopen(c2pread, 'rb', 1)
3077
 
            test = TestInOtherProcess(stream, pid)
3078
 
            result.append(test)
3079
 
    return result
3080
 
 
3081
 
 
3082
 
def reinvoke_for_tests(suite):
3083
 
    """Take suite and start up one runner per CPU using subprocess().
3084
 
 
3085
 
    :return: An iterable of TestCase-like objects which can each have
3086
 
        run(result) called on them to feed tests to result.
3087
 
    """
3088
 
    concurrency = osutils.local_concurrency()
3089
 
    result = []
3090
 
    from subunit import ProtocolTestCase
3091
 
    class TestInSubprocess(ProtocolTestCase):
3092
 
        def __init__(self, process, name):
3093
 
            ProtocolTestCase.__init__(self, process.stdout)
3094
 
            self.process = process
3095
 
            self.process.stdin.close()
3096
 
            self.name = name
3097
 
 
3098
 
        def run(self, result):
3099
 
            try:
3100
 
                ProtocolTestCase.run(self, result)
3101
 
            finally:
3102
 
                self.process.wait()
3103
 
                os.unlink(self.name)
3104
 
            # print "pid %d finished" % finished_process
3105
 
    test_blocks = partition_tests(suite, concurrency)
3106
 
    for process_tests in test_blocks:
3107
 
        # ugly; currently reimplement rather than reuses TestCase methods.
3108
 
        bzr_path = os.path.dirname(os.path.dirname(bzrlib.__file__))+'/bzr'
3109
 
        if not os.path.isfile(bzr_path):
3110
 
            # We are probably installed. Assume sys.argv is the right file
3111
 
            bzr_path = sys.argv[0]
3112
 
        fd, test_list_file_name = tempfile.mkstemp()
3113
 
        test_list_file = os.fdopen(fd, 'wb', 1)
3114
 
        for test in process_tests:
3115
 
            test_list_file.write(test.id() + '\n')
3116
 
        test_list_file.close()
3117
 
        try:
3118
 
            argv = [bzr_path, 'selftest', '--load-list', test_list_file_name,
3119
 
                '--subunit']
3120
 
            if '--no-plugins' in sys.argv:
3121
 
                argv.append('--no-plugins')
3122
 
            # stderr=STDOUT would be ideal, but until we prevent noise on
3123
 
            # stderr it can interrupt the subunit protocol.
3124
 
            process = Popen(argv, stdin=PIPE, stdout=PIPE, stderr=PIPE,
3125
 
                bufsize=1)
3126
 
            test = TestInSubprocess(process, test_list_file_name)
3127
 
            result.append(test)
3128
 
        except:
3129
 
            os.unlink(test_list_file_name)
3130
 
            raise
3131
 
    return result
3132
 
 
3133
 
 
3134
 
class BZRTransformingResult(unittest.TestResult):
3135
 
 
3136
 
    def __init__(self, target):
3137
 
        unittest.TestResult.__init__(self)
3138
 
        self.result = target
3139
 
 
3140
 
    def startTest(self, test):
3141
 
        self.result.startTest(test)
3142
 
 
3143
 
    def stopTest(self, test):
3144
 
        self.result.stopTest(test)
3145
 
 
3146
 
    def addError(self, test, err):
3147
 
        feature = self._error_looks_like('UnavailableFeature: ', err)
3148
 
        if feature is not None:
3149
 
            self.result.addNotSupported(test, feature)
3150
 
        else:
3151
 
            self.result.addError(test, err)
3152
 
 
3153
 
    def addFailure(self, test, err):
3154
 
        known = self._error_looks_like('KnownFailure: ', err)
3155
 
        if known is not None:
3156
 
            self.result._addKnownFailure(test, [KnownFailure,
3157
 
                                                KnownFailure(known), None])
3158
 
        else:
3159
 
            self.result.addFailure(test, err)
3160
 
 
3161
 
    def addSkip(self, test, reason):
3162
 
        self.result.addSkip(test, reason)
3163
 
 
3164
 
    def addSuccess(self, test):
3165
 
        self.result.addSuccess(test)
3166
 
 
3167
 
    def _error_looks_like(self, prefix, err):
3168
 
        """Deserialize exception and returns the stringify value."""
3169
 
        import subunit
3170
 
        value = None
3171
 
        typ, exc, _ = err
3172
 
        if isinstance(exc, subunit.RemoteException):
3173
 
            # stringify the exception gives access to the remote traceback
3174
 
            # We search the last line for 'prefix'
3175
 
            lines = str(exc).split('\n')
3176
 
            while lines and not lines[-1]:
3177
 
                lines.pop(-1)
3178
 
            if lines:
3179
 
                if lines[-1].startswith(prefix):
3180
 
                    value = lines[-1][len(prefix):]
3181
 
        return value
 
2514
 
 
2515
    return result.wasSuccessful()
3182
2516
 
3183
2517
 
3184
2518
# Controlled by "bzr selftest -E=..." option
3185
 
# Currently supported:
3186
 
#   -Eallow_debug           Will no longer clear debug.debug_flags() so it
3187
 
#                           preserves any flags supplied at the command line.
3188
 
#   -Edisable_lock_checks   Turns errors in mismatched locks into simple prints
3189
 
#                           rather than failing tests. And no longer raise
3190
 
#                           LockContention when fctnl locks are not being used
3191
 
#                           with proper exclusion rules.
3192
2519
selftest_debug_flags = set()
3193
2520
 
3194
2521
 
3205
2532
             load_list=None,
3206
2533
             debug_flags=None,
3207
2534
             starting_with=None,
3208
 
             runner_class=None,
3209
 
             suite_decorators=None,
3210
2535
             ):
3211
2536
    """Run the whole test suite under the enhanced runner"""
3212
2537
    # XXX: Very ugly way to do this...
3242
2567
                     list_only=list_only,
3243
2568
                     random_seed=random_seed,
3244
2569
                     exclude_pattern=exclude_pattern,
3245
 
                     strict=strict,
3246
 
                     runner_class=runner_class,
3247
 
                     suite_decorators=suite_decorators,
3248
 
                     )
 
2570
                     strict=strict)
3249
2571
    finally:
3250
2572
        default_transport = old_transport
3251
2573
        selftest_debug_flags = old_debug_flags
3278
2600
    """Warns about tests not appearing or appearing more than once.
3279
2601
 
3280
2602
    :param test_suite: A TestSuite object.
3281
 
    :param test_id_list: The list of test ids that should be found in
 
2603
    :param test_id_list: The list of test ids that should be found in 
3282
2604
         test_suite.
3283
2605
 
3284
2606
    :return: (absents, duplicates) absents is a list containing the test found
3419
2741
    """
3420
2742
    testmod_names = [
3421
2743
                   'bzrlib.doc',
 
2744
                   'bzrlib.util.tests.test_bencode',
3422
2745
                   'bzrlib.tests.blackbox',
 
2746
                   'bzrlib.tests.branch_implementations',
 
2747
                   'bzrlib.tests.bzrdir_implementations',
3423
2748
                   'bzrlib.tests.commands',
3424
 
                   'bzrlib.tests.per_branch',
3425
 
                   'bzrlib.tests.per_bzrdir',
3426
 
                   'bzrlib.tests.per_interrepository',
3427
 
                   'bzrlib.tests.per_intertree',
3428
 
                   'bzrlib.tests.per_inventory',
3429
 
                   'bzrlib.tests.per_interbranch',
 
2749
                   'bzrlib.tests.inventory_implementations',
 
2750
                   'bzrlib.tests.interrepository_implementations',
 
2751
                   'bzrlib.tests.intertree_implementations',
3430
2752
                   'bzrlib.tests.per_lock',
3431
 
                   'bzrlib.tests.per_transport',
3432
 
                   'bzrlib.tests.per_tree',
3433
 
                   'bzrlib.tests.per_pack_repository',
3434
 
                   'bzrlib.tests.per_repository',
3435
 
                   'bzrlib.tests.per_repository_chk',
3436
 
                   'bzrlib.tests.per_repository_reference',
3437
 
                   'bzrlib.tests.per_versionedfile',
3438
 
                   'bzrlib.tests.per_workingtree',
3439
 
                   'bzrlib.tests.test__annotator',
3440
 
                   'bzrlib.tests.test__chk_map',
 
2753
                   'bzrlib.tests.repository_implementations',
3441
2754
                   'bzrlib.tests.test__dirstate_helpers',
3442
 
                   'bzrlib.tests.test__groupcompress',
3443
 
                   'bzrlib.tests.test__known_graph',
3444
 
                   'bzrlib.tests.test__rio',
3445
 
                   'bzrlib.tests.test__walkdirs_win32',
3446
2755
                   'bzrlib.tests.test_ancestry',
3447
2756
                   'bzrlib.tests.test_annotate',
3448
2757
                   'bzrlib.tests.test_api',
3449
2758
                   'bzrlib.tests.test_atomicfile',
3450
2759
                   'bzrlib.tests.test_bad_files',
3451
 
                   'bzrlib.tests.test_bencode',
3452
2760
                   'bzrlib.tests.test_bisect_multi',
3453
2761
                   'bzrlib.tests.test_branch',
3454
2762
                   'bzrlib.tests.test_branchbuilder',
3456
2764
                   'bzrlib.tests.test_bugtracker',
3457
2765
                   'bzrlib.tests.test_bundle',
3458
2766
                   'bzrlib.tests.test_bzrdir',
3459
 
                   'bzrlib.tests.test__chunks_to_lines',
3460
2767
                   'bzrlib.tests.test_cache_utf8',
3461
 
                   'bzrlib.tests.test_chk_map',
3462
 
                   'bzrlib.tests.test_chk_serializer',
3463
2768
                   'bzrlib.tests.test_chunk_writer',
3464
 
                   'bzrlib.tests.test_clean_tree',
3465
2769
                   'bzrlib.tests.test_commands',
3466
2770
                   'bzrlib.tests.test_commit',
3467
2771
                   'bzrlib.tests.test_commit_merge',
3470
2774
                   'bzrlib.tests.test_counted_lock',
3471
2775
                   'bzrlib.tests.test_decorators',
3472
2776
                   'bzrlib.tests.test_delta',
3473
 
                   'bzrlib.tests.test_debug',
3474
2777
                   'bzrlib.tests.test_deprecated_graph',
3475
2778
                   'bzrlib.tests.test_diff',
 
2779
                   'bzrlib.tests.test_dirstate',
3476
2780
                   'bzrlib.tests.test_directory_service',
3477
 
                   'bzrlib.tests.test_dirstate',
3478
2781
                   'bzrlib.tests.test_email_message',
3479
 
                   'bzrlib.tests.test_eol_filters',
3480
2782
                   'bzrlib.tests.test_errors',
3481
 
                   'bzrlib.tests.test_export',
3482
2783
                   'bzrlib.tests.test_extract',
3483
2784
                   'bzrlib.tests.test_fetch',
3484
 
                   'bzrlib.tests.test_fifo_cache',
3485
 
                   'bzrlib.tests.test_filters',
3486
2785
                   'bzrlib.tests.test_ftp_transport',
3487
 
                   'bzrlib.tests.test_foreign',
3488
2786
                   'bzrlib.tests.test_generate_docs',
3489
2787
                   'bzrlib.tests.test_generate_ids',
3490
2788
                   'bzrlib.tests.test_globbing',
3491
2789
                   'bzrlib.tests.test_gpg',
3492
2790
                   'bzrlib.tests.test_graph',
3493
 
                   'bzrlib.tests.test_groupcompress',
3494
2791
                   'bzrlib.tests.test_hashcache',
3495
2792
                   'bzrlib.tests.test_help',
3496
2793
                   'bzrlib.tests.test_hooks',
3497
2794
                   'bzrlib.tests.test_http',
 
2795
                   'bzrlib.tests.test_http_implementations',
3498
2796
                   'bzrlib.tests.test_http_response',
3499
2797
                   'bzrlib.tests.test_https_ca_bundle',
3500
2798
                   'bzrlib.tests.test_identitymap',
3502
2800
                   'bzrlib.tests.test_index',
3503
2801
                   'bzrlib.tests.test_info',
3504
2802
                   'bzrlib.tests.test_inv',
3505
 
                   'bzrlib.tests.test_inventory_delta',
3506
2803
                   'bzrlib.tests.test_knit',
3507
2804
                   'bzrlib.tests.test_lazy_import',
3508
2805
                   'bzrlib.tests.test_lazy_regex',
3509
 
                   'bzrlib.tests.test_lock',
 
2806
                   'bzrlib.tests.test_lockdir',
3510
2807
                   'bzrlib.tests.test_lockable_files',
3511
 
                   'bzrlib.tests.test_lockdir',
3512
2808
                   'bzrlib.tests.test_log',
 
2809
                   'bzrlib.tests.test_lsprof',
3513
2810
                   'bzrlib.tests.test_lru_cache',
3514
 
                   'bzrlib.tests.test_lsprof',
3515
2811
                   'bzrlib.tests.test_mail_client',
3516
2812
                   'bzrlib.tests.test_memorytree',
3517
2813
                   'bzrlib.tests.test_merge',
3527
2823
                   'bzrlib.tests.test_osutils',
3528
2824
                   'bzrlib.tests.test_osutils_encodings',
3529
2825
                   'bzrlib.tests.test_pack',
 
2826
                   'bzrlib.tests.test_pack_repository',
3530
2827
                   'bzrlib.tests.test_patch',
3531
2828
                   'bzrlib.tests.test_patches',
3532
2829
                   'bzrlib.tests.test_permissions',
3533
2830
                   'bzrlib.tests.test_plugins',
3534
2831
                   'bzrlib.tests.test_progress',
3535
2832
                   'bzrlib.tests.test_read_bundle',
 
2833
                   'bzrlib.tests.test_reconfigure',
3536
2834
                   'bzrlib.tests.test_reconcile',
3537
 
                   'bzrlib.tests.test_reconfigure',
3538
2835
                   'bzrlib.tests.test_registry',
3539
2836
                   'bzrlib.tests.test_remote',
3540
 
                   'bzrlib.tests.test_rename_map',
3541
2837
                   'bzrlib.tests.test_repository',
 
2838
                   'bzrlib.tests.per_repository_reference',
3542
2839
                   'bzrlib.tests.test_revert',
3543
2840
                   'bzrlib.tests.test_revision',
3544
2841
                   'bzrlib.tests.test_revisionspec',
3547
2844
                   'bzrlib.tests.test_rules',
3548
2845
                   'bzrlib.tests.test_sampler',
3549
2846
                   'bzrlib.tests.test_selftest',
3550
 
                   'bzrlib.tests.test_serializer',
3551
2847
                   'bzrlib.tests.test_setup',
3552
2848
                   'bzrlib.tests.test_sftp_transport',
3553
 
                   'bzrlib.tests.test_shelf',
3554
 
                   'bzrlib.tests.test_shelf_ui',
3555
2849
                   'bzrlib.tests.test_smart',
3556
2850
                   'bzrlib.tests.test_smart_add',
3557
 
                   'bzrlib.tests.test_smart_request',
3558
2851
                   'bzrlib.tests.test_smart_transport',
3559
2852
                   'bzrlib.tests.test_smtp_connection',
3560
2853
                   'bzrlib.tests.test_source',
3574
2867
                   'bzrlib.tests.test_transactions',
3575
2868
                   'bzrlib.tests.test_transform',
3576
2869
                   'bzrlib.tests.test_transport',
 
2870
                   'bzrlib.tests.test_transport_implementations',
3577
2871
                   'bzrlib.tests.test_transport_log',
3578
2872
                   'bzrlib.tests.test_tree',
3579
2873
                   'bzrlib.tests.test_treebuilder',
3584
2878
                   'bzrlib.tests.test_upgrade',
3585
2879
                   'bzrlib.tests.test_upgrade_stacked',
3586
2880
                   'bzrlib.tests.test_urlutils',
 
2881
                   'bzrlib.tests.test_versionedfile',
3587
2882
                   'bzrlib.tests.test_version',
3588
2883
                   'bzrlib.tests.test_version_info',
 
2884
                   'bzrlib.tests.test__walkdirs_win32',
3589
2885
                   'bzrlib.tests.test_weave',
3590
2886
                   'bzrlib.tests.test_whitebox',
3591
2887
                   'bzrlib.tests.test_win32utils',
3593
2889
                   'bzrlib.tests.test_workingtree_4',
3594
2890
                   'bzrlib.tests.test_wsgi',
3595
2891
                   'bzrlib.tests.test_xml',
 
2892
                   'bzrlib.tests.tree_implementations',
 
2893
                   'bzrlib.tests.workingtree_implementations',
3596
2894
                   ]
3597
2895
 
3598
2896
    loader = TestUtil.TestLoader()
3599
2897
 
3600
 
    if keep_only is not None:
3601
 
        id_filter = TestIdList(keep_only)
3602
2898
    if starting_with:
3603
2899
        starting_with = [test_prefix_alias_registry.resolve_alias(start)
3604
2900
                         for start in starting_with]
3617
2913
        loader = TestUtil.FilteredByModuleTestLoader(interesting_module)
3618
2914
 
3619
2915
    elif keep_only is not None:
 
2916
        id_filter = TestIdList(keep_only)
3620
2917
        loader = TestUtil.FilteredByModuleTestLoader(id_filter.refers_to)
3621
2918
        def interesting_module(name):
3622
2919
            return id_filter.refers_to(name)
3634
2931
 
3635
2932
    modules_to_doctest = [
3636
2933
        'bzrlib',
3637
 
        'bzrlib.branchbuilder',
 
2934
        'bzrlib.errors',
3638
2935
        'bzrlib.export',
3639
2936
        'bzrlib.inventory',
3640
2937
        'bzrlib.iterablefile',
3641
2938
        'bzrlib.lockdir',
3642
2939
        'bzrlib.merge3',
3643
2940
        'bzrlib.option',
 
2941
        'bzrlib.store',
3644
2942
        'bzrlib.symbol_versioning',
3645
2943
        'bzrlib.tests',
3646
2944
        'bzrlib.timestamp',
3652
2950
            # No tests to keep here, move along
3653
2951
            continue
3654
2952
        try:
3655
 
            # note that this really does mean "report only" -- doctest
3656
 
            # still runs the rest of the examples
3657
 
            doc_suite = doctest.DocTestSuite(mod,
3658
 
                optionflags=doctest.REPORT_ONLY_FIRST_FAILURE)
 
2953
            doc_suite = doctest.DocTestSuite(mod)
3659
2954
        except ValueError, e:
3660
2955
            print '**failed to get doctest for: %s\n%s' % (mod, e)
3661
2956
            raise
3662
 
        if len(doc_suite._tests) == 0:
3663
 
            raise errors.BzrError("no doctests found in %s" % (mod,))
3664
2957
        suite.addTest(doc_suite)
3665
2958
 
3666
2959
    default_encoding = sys.getdefaultencoding()
3707
3000
    return suite
3708
3001
 
3709
3002
 
 
3003
def multiply_tests_from_modules(module_name_list, scenario_iter, loader=None):
 
3004
    """Adapt all tests in some given modules to given scenarios.
 
3005
 
 
3006
    This is the recommended public interface for test parameterization.
 
3007
    Typically the test_suite() method for a per-implementation test
 
3008
    suite will call multiply_tests_from_modules and return the 
 
3009
    result.
 
3010
 
 
3011
    :param module_name_list: List of fully-qualified names of test
 
3012
        modules.
 
3013
    :param scenario_iter: Iterable of pairs of (scenario_name, 
 
3014
        scenario_param_dict).
 
3015
    :param loader: If provided, will be used instead of a new 
 
3016
        bzrlib.tests.TestLoader() instance.
 
3017
 
 
3018
    This returns a new TestSuite containing the cross product of
 
3019
    all the tests in all the modules, each repeated for each scenario.
 
3020
    Each test is adapted by adding the scenario name at the end 
 
3021
    of its name, and updating the test object's __dict__ with the
 
3022
    scenario_param_dict.
 
3023
 
 
3024
    >>> r = multiply_tests_from_modules(
 
3025
    ...     ['bzrlib.tests.test_sampler'],
 
3026
    ...     [('one', dict(param=1)), 
 
3027
    ...      ('two', dict(param=2))])
 
3028
    >>> tests = list(iter_suite_tests(r))
 
3029
    >>> len(tests)
 
3030
    2
 
3031
    >>> tests[0].id()
 
3032
    'bzrlib.tests.test_sampler.DemoTest.test_nothing(one)'
 
3033
    >>> tests[0].param
 
3034
    1
 
3035
    >>> tests[1].param
 
3036
    2
 
3037
    """
 
3038
    # XXX: Isn't load_tests() a better way to provide the same functionality
 
3039
    # without forcing a predefined TestScenarioApplier ? --vila 080215
 
3040
    if loader is None:
 
3041
        loader = TestUtil.TestLoader()
 
3042
 
 
3043
    suite = loader.suiteClass()
 
3044
 
 
3045
    adapter = TestScenarioApplier()
 
3046
    adapter.scenarios = list(scenario_iter)
 
3047
    adapt_modules(module_name_list, adapter, loader, suite)
 
3048
    return suite
 
3049
 
 
3050
 
3710
3051
def multiply_scenarios(scenarios_left, scenarios_right):
3711
3052
    """Multiply two sets of scenarios.
3712
3053
 
3721
3062
        for right_name, right_dict in scenarios_right]
3722
3063
 
3723
3064
 
3724
 
def multiply_tests(tests, scenarios, result):
3725
 
    """Multiply tests_list by scenarios into result.
3726
 
 
3727
 
    This is the core workhorse for test parameterisation.
3728
 
 
3729
 
    Typically the load_tests() method for a per-implementation test suite will
3730
 
    call multiply_tests and return the result.
3731
 
 
3732
 
    :param tests: The tests to parameterise.
3733
 
    :param scenarios: The scenarios to apply: pairs of (scenario_name,
3734
 
        scenario_param_dict).
3735
 
    :param result: A TestSuite to add created tests to.
3736
 
 
3737
 
    This returns the passed in result TestSuite with the cross product of all
3738
 
    the tests repeated once for each scenario.  Each test is adapted by adding
3739
 
    the scenario name at the end of its id(), and updating the test object's
3740
 
    __dict__ with the scenario_param_dict.
3741
 
 
3742
 
    >>> import bzrlib.tests.test_sampler
3743
 
    >>> r = multiply_tests(
3744
 
    ...     bzrlib.tests.test_sampler.DemoTest('test_nothing'),
3745
 
    ...     [('one', dict(param=1)),
3746
 
    ...      ('two', dict(param=2))],
3747
 
    ...     TestSuite())
3748
 
    >>> tests = list(iter_suite_tests(r))
3749
 
    >>> len(tests)
3750
 
    2
3751
 
    >>> tests[0].id()
3752
 
    'bzrlib.tests.test_sampler.DemoTest.test_nothing(one)'
3753
 
    >>> tests[0].param
3754
 
    1
3755
 
    >>> tests[1].param
3756
 
    2
3757
 
    """
3758
 
    for test in iter_suite_tests(tests):
3759
 
        apply_scenarios(test, scenarios, result)
3760
 
    return result
3761
 
 
3762
 
 
3763
 
def apply_scenarios(test, scenarios, result):
3764
 
    """Apply the scenarios in scenarios to test and add to result.
3765
 
 
3766
 
    :param test: The test to apply scenarios to.
3767
 
    :param scenarios: An iterable of scenarios to apply to test.
3768
 
    :return: result
3769
 
    :seealso: apply_scenario
3770
 
    """
3771
 
    for scenario in scenarios:
3772
 
        result.addTest(apply_scenario(test, scenario))
3773
 
    return result
3774
 
 
3775
 
 
3776
 
def apply_scenario(test, scenario):
3777
 
    """Copy test and apply scenario to it.
3778
 
 
3779
 
    :param test: A test to adapt.
3780
 
    :param scenario: A tuple describing the scenarion.
3781
 
        The first element of the tuple is the new test id.
3782
 
        The second element is a dict containing attributes to set on the
3783
 
        test.
3784
 
    :return: The adapted test.
3785
 
    """
3786
 
    new_id = "%s(%s)" % (test.id(), scenario[0])
3787
 
    new_test = clone_test(test, new_id)
3788
 
    for name, value in scenario[1].items():
3789
 
        setattr(new_test, name, value)
3790
 
    return new_test
3791
 
 
3792
 
 
3793
 
def clone_test(test, new_id):
3794
 
    """Clone a test giving it a new id.
3795
 
 
3796
 
    :param test: The test to clone.
3797
 
    :param new_id: The id to assign to it.
3798
 
    :return: The new test.
3799
 
    """
3800
 
    from copy import deepcopy
3801
 
    new_test = deepcopy(test)
3802
 
    new_test.id = lambda: new_id
3803
 
    return new_test
 
3065
 
 
3066
def adapt_modules(mods_list, adapter, loader, suite):
 
3067
    """Adapt the modules in mods_list using adapter and add to suite."""
 
3068
    tests = loader.loadTestsFromModuleNames(mods_list)
 
3069
    adapt_tests(tests, adapter, suite)
 
3070
 
 
3071
 
 
3072
def adapt_tests(tests_list, adapter, suite):
 
3073
    """Adapt the tests in tests_list using adapter and add to suite."""
 
3074
    for test in iter_suite_tests(tests_list):
 
3075
        suite.addTests(adapter.adapt(test))
3804
3076
 
3805
3077
 
3806
3078
def _rmtree_temp_dir(dirname):
3818
3090
    try:
3819
3091
        osutils.rmtree(dirname)
3820
3092
    except OSError, e:
3821
 
        # We don't want to fail here because some useful display will be lost
3822
 
        # otherwise. Polluting the tmp dir is bad, but not giving all the
3823
 
        # possible info to the test runner is even worse.
3824
 
        sys.stderr.write('Unable to remove testing dir %s\n%s'
3825
 
                         % (os.path.basename(dirname), e))
 
3093
        if sys.platform == 'win32' and e.errno == errno.EACCES:
 
3094
            sys.stderr.write(('Permission denied: '
 
3095
                                 'unable to remove testing dir '
 
3096
                                 '%s\n' % os.path.basename(dirname)))
 
3097
        else:
 
3098
            raise
3826
3099
 
3827
3100
 
3828
3101
class Feature(object):
3910
3183
UnicodeFilenameFeature = _UnicodeFilenameFeature()
3911
3184
 
3912
3185
 
 
3186
class TestScenarioApplier(object):
 
3187
    """A tool to apply scenarios to tests."""
 
3188
 
 
3189
    def adapt(self, test):
 
3190
        """Return a TestSuite containing a copy of test for each scenario."""
 
3191
        result = unittest.TestSuite()
 
3192
        for scenario in self.scenarios:
 
3193
            result.addTest(self.adapt_test_to_scenario(test, scenario))
 
3194
        return result
 
3195
 
 
3196
    def adapt_test_to_scenario(self, test, scenario):
 
3197
        """Copy test and apply scenario to it.
 
3198
 
 
3199
        :param test: A test to adapt.
 
3200
        :param scenario: A tuple describing the scenarion.
 
3201
            The first element of the tuple is the new test id.
 
3202
            The second element is a dict containing attributes to set on the
 
3203
            test.
 
3204
        :return: The adapted test.
 
3205
        """
 
3206
        from copy import deepcopy
 
3207
        new_test = deepcopy(test)
 
3208
        for name, value in scenario[1].items():
 
3209
            setattr(new_test, name, value)
 
3210
        new_id = "%s(%s)" % (new_test.id(), scenario[0])
 
3211
        new_test.id = lambda: new_id
 
3212
        return new_test
 
3213
 
 
3214
 
3913
3215
def probe_unicode_in_user_encoding():
3914
3216
    """Try to encode several unicode strings to use in unicode-aware tests.
3915
3217
    Return first successfull match.
3919
3221
    possible_vals = [u'm\xb5', u'\xe1', u'\u0410']
3920
3222
    for uni_val in possible_vals:
3921
3223
        try:
3922
 
            str_val = uni_val.encode(osutils.get_user_encoding())
 
3224
            str_val = uni_val.encode(bzrlib.user_encoding)
3923
3225
        except UnicodeEncodeError:
3924
3226
            # Try a different character
3925
3227
            pass
3943
3245
    return None
3944
3246
 
3945
3247
 
3946
 
class _HTTPSServerFeature(Feature):
3947
 
    """Some tests want an https Server, check if one is available.
 
3248
class _FTPServerFeature(Feature):
 
3249
    """Some tests want an FTP Server, check if one is available.
3948
3250
 
3949
 
    Right now, the only way this is available is under python2.6 which provides
3950
 
    an ssl module.
 
3251
    Right now, the only way this is available is if 'medusa' is installed.
 
3252
    http://www.amk.ca/python/code/medusa.html
3951
3253
    """
3952
3254
 
3953
3255
    def _probe(self):
3954
3256
        try:
3955
 
            import ssl
 
3257
            import bzrlib.tests.ftp_server
3956
3258
            return True
3957
3259
        except ImportError:
3958
3260
            return False
3959
3261
 
3960
3262
    def feature_name(self):
3961
 
        return 'HTTPSServer'
3962
 
 
3963
 
 
3964
 
HTTPSServerFeature = _HTTPSServerFeature()
 
3263
        return 'FTPServer'
 
3264
 
 
3265
FTPServerFeature = _FTPServerFeature()
3965
3266
 
3966
3267
 
3967
3268
class _UnicodeFilename(Feature):
3995
3296
UTF8Filesystem = _UTF8Filesystem()
3996
3297
 
3997
3298
 
3998
 
class _CaseInsCasePresFilenameFeature(Feature):
3999
 
    """Is the file-system case insensitive, but case-preserving?"""
4000
 
 
4001
 
    def _probe(self):
4002
 
        fileno, name = tempfile.mkstemp(prefix='MixedCase')
4003
 
        try:
4004
 
            # first check truly case-preserving for created files, then check
4005
 
            # case insensitive when opening existing files.
4006
 
            name = osutils.normpath(name)
4007
 
            base, rel = osutils.split(name)
4008
 
            found_rel = osutils.canonical_relpath(base, name)
4009
 
            return (found_rel == rel
4010
 
                    and os.path.isfile(name.upper())
4011
 
                    and os.path.isfile(name.lower()))
4012
 
        finally:
4013
 
            os.close(fileno)
4014
 
            os.remove(name)
4015
 
 
4016
 
    def feature_name(self):
4017
 
        return "case-insensitive case-preserving filesystem"
4018
 
 
4019
 
CaseInsCasePresFilenameFeature = _CaseInsCasePresFilenameFeature()
4020
 
 
4021
 
 
4022
3299
class _CaseInsensitiveFilesystemFeature(Feature):
4023
 
    """Check if underlying filesystem is case-insensitive but *not* case
4024
 
    preserving.
 
3300
    """Check if underlying filesystem is case-insensitive
 
3301
    (e.g. on Windows, Cygwin, MacOS)
4025
3302
    """
4026
 
    # Note that on Windows, Cygwin, MacOS etc, the file-systems are far
4027
 
    # more likely to be case preserving, so this case is rare.
4028
3303
 
4029
3304
    def _probe(self):
4030
 
        if CaseInsCasePresFilenameFeature.available():
4031
 
            return False
4032
 
 
4033
3305
        if TestCaseWithMemoryTransport.TEST_ROOT is None:
4034
3306
            root = osutils.mkdtemp(prefix='testbzr-', suffix='.tmp')
4035
3307
            TestCaseWithMemoryTransport.TEST_ROOT = root
4048
3320
        return 'case-insensitive filesystem'
4049
3321
 
4050
3322
CaseInsensitiveFilesystemFeature = _CaseInsensitiveFilesystemFeature()
4051
 
 
4052
 
 
4053
 
class _SubUnitFeature(Feature):
4054
 
    """Check if subunit is available."""
4055
 
 
4056
 
    def _probe(self):
4057
 
        try:
4058
 
            import subunit
4059
 
            return True
4060
 
        except ImportError:
4061
 
            return False
4062
 
 
4063
 
    def feature_name(self):
4064
 
        return 'subunit'
4065
 
 
4066
 
SubUnitFeature = _SubUnitFeature()
4067
 
# Only define SubUnitBzrRunner if subunit is available.
4068
 
try:
4069
 
    from subunit import TestProtocolClient
4070
 
    try:
4071
 
        from subunit.test_results import AutoTimingTestResultDecorator
4072
 
    except ImportError:
4073
 
        AutoTimingTestResultDecorator = lambda x:x
4074
 
    class SubUnitBzrRunner(TextTestRunner):
4075
 
        def run(self, test):
4076
 
            result = AutoTimingTestResultDecorator(
4077
 
                TestProtocolClient(self.stream))
4078
 
            test.run(result)
4079
 
            return result
4080
 
except ImportError:
4081
 
    pass