~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_selftest.py

  • Committer: John Arbash Meinel
  • Date: 2011-01-12 16:45:49 UTC
  • mto: This revision was merged to the branch mainline in revision 5599.
  • Revision ID: john@arbash-meinel.com-20110112164549-6buxl1yr8vosoh1t
Add to What's New

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005 by Canonical Ltd
 
1
# Copyright (C) 2005-2011 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
 
# it under the terms of the GNU General Public License version 2 as published by
5
 
# the Free Software Foundation.
 
4
# it under the terms of the GNU General Public License as published by
 
5
# the Free Software Foundation; either version 2 of the License, or
 
6
# (at your option) any later version.
6
7
#
7
8
# This program is distributed in the hope that it will be useful,
8
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
12
#
12
13
# You should have received a copy of the GNU General Public License
13
14
# along with this program; if not, write to the Free Software
14
 
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
15
 
 
16
 
"""Tests for the test framework
17
 
"""
18
 
 
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
16
 
 
17
"""Tests for the test framework."""
 
18
 
 
19
from cStringIO import StringIO
 
20
import doctest
19
21
import os
 
22
import signal
20
23
import sys
21
 
 
22
 
from bzrlib.tests import TestCase, _load_module_by_name
23
 
 
24
 
 
25
 
class SelftestTests(TestCase):
26
 
 
27
 
    def test_import_tests(self):
28
 
        mod = _load_module_by_name('bzrlib.tests.test_selftest')
29
 
        self.assertEqual(mod.SelftestTests, SelftestTests)
30
 
 
31
 
    def test_import_test_failure(self):
32
 
        self.assertRaises(ImportError,
33
 
                          _load_module_by_name,
34
 
                          'bzrlib.no-name-yet')
35
 
 
36
 
 
37
 
class MetaTestLog(TestCase):
 
24
import threading
 
25
import time
 
26
import unittest
 
27
import warnings
 
28
 
 
29
from testtools import (
 
30
    ExtendedToOriginalDecorator,
 
31
    MultiTestResult,
 
32
    )
 
33
from testtools.content import Content
 
34
from testtools.content_type import ContentType
 
35
from testtools.matchers import (
 
36
    DocTestMatches,
 
37
    Equals,
 
38
    )
 
39
import testtools.tests.helpers
 
40
 
 
41
import bzrlib
 
42
from bzrlib import (
 
43
    branchbuilder,
 
44
    bzrdir,
 
45
    errors,
 
46
    lockdir,
 
47
    memorytree,
 
48
    osutils,
 
49
    remote,
 
50
    repository,
 
51
    symbol_versioning,
 
52
    tests,
 
53
    transport,
 
54
    workingtree,
 
55
    )
 
56
from bzrlib.repofmt import (
 
57
    groupcompress_repo,
 
58
    weaverepo,
 
59
    )
 
60
from bzrlib.symbol_versioning import (
 
61
    deprecated_function,
 
62
    deprecated_in,
 
63
    deprecated_method,
 
64
    )
 
65
from bzrlib.tests import (
 
66
    features,
 
67
    test_lsprof,
 
68
    test_server,
 
69
    TestUtil,
 
70
    )
 
71
from bzrlib.trace import note, mutter
 
72
from bzrlib.transport import memory
 
73
 
 
74
 
 
75
def _test_ids(test_suite):
 
76
    """Get the ids for the tests in a test suite."""
 
77
    return [t.id() for t in tests.iter_suite_tests(test_suite)]
 
78
 
 
79
 
 
80
class MetaTestLog(tests.TestCase):
 
81
 
38
82
    def test_logging(self):
39
83
        """Test logs are captured when a test fails."""
40
84
        self.log('a test message')
41
 
        self._log_file.flush()
42
 
        self.assertContainsRe(self._get_log(), 'a test message\n')
 
85
        details = self.getDetails()
 
86
        log = details['log']
 
87
        self.assertThat(log.content_type, Equals(ContentType(
 
88
            "text", "plain", {"charset": "utf8"})))
 
89
        self.assertThat(u"".join(log.iter_text()), Equals(self.get_log()))
 
90
        self.assertThat(self.get_log(),
 
91
            DocTestMatches(u"...a test message\n", doctest.ELLIPSIS))
 
92
 
 
93
 
 
94
class TestUnicodeFilename(tests.TestCase):
 
95
 
 
96
    def test_probe_passes(self):
 
97
        """UnicodeFilename._probe passes."""
 
98
        # We can't test much more than that because the behaviour depends
 
99
        # on the platform.
 
100
        tests.UnicodeFilename._probe()
 
101
 
 
102
 
 
103
class TestTreeShape(tests.TestCaseInTempDir):
 
104
 
 
105
    def test_unicode_paths(self):
 
106
        self.requireFeature(tests.UnicodeFilename)
 
107
 
 
108
        filename = u'hell\u00d8'
 
109
        self.build_tree_contents([(filename, 'contents of hello')])
 
110
        self.failUnlessExists(filename)
 
111
 
 
112
 
 
113
class TestClassesAvailable(tests.TestCase):
 
114
    """As a convenience we expose Test* classes from bzrlib.tests"""
 
115
 
 
116
    def test_test_case(self):
 
117
        from bzrlib.tests import TestCase
 
118
 
 
119
    def test_test_loader(self):
 
120
        from bzrlib.tests import TestLoader
 
121
 
 
122
    def test_test_suite(self):
 
123
        from bzrlib.tests import TestSuite
 
124
 
 
125
 
 
126
class TestTransportScenarios(tests.TestCase):
 
127
    """A group of tests that test the transport implementation adaption core.
 
128
 
 
129
    This is a meta test that the tests are applied to all available
 
130
    transports.
 
131
 
 
132
    This will be generalised in the future which is why it is in this
 
133
    test file even though it is specific to transport tests at the moment.
 
134
    """
 
135
 
 
136
    def test_get_transport_permutations(self):
 
137
        # this checks that get_test_permutations defined by the module is
 
138
        # called by the get_transport_test_permutations function.
 
139
        class MockModule(object):
 
140
            def get_test_permutations(self):
 
141
                return sample_permutation
 
142
        sample_permutation = [(1,2), (3,4)]
 
143
        from bzrlib.tests.per_transport import get_transport_test_permutations
 
144
        self.assertEqual(sample_permutation,
 
145
                         get_transport_test_permutations(MockModule()))
 
146
 
 
147
    def test_scenarios_include_all_modules(self):
 
148
        # this checks that the scenario generator returns as many permutations
 
149
        # as there are in all the registered transport modules - we assume if
 
150
        # this matches its probably doing the right thing especially in
 
151
        # combination with the tests for setting the right classes below.
 
152
        from bzrlib.tests.per_transport import transport_test_permutations
 
153
        from bzrlib.transport import _get_transport_modules
 
154
        modules = _get_transport_modules()
 
155
        permutation_count = 0
 
156
        for module in modules:
 
157
            try:
 
158
                permutation_count += len(reduce(getattr,
 
159
                    (module + ".get_test_permutations").split('.')[1:],
 
160
                     __import__(module))())
 
161
            except errors.DependencyNotPresent:
 
162
                pass
 
163
        scenarios = transport_test_permutations()
 
164
        self.assertEqual(permutation_count, len(scenarios))
 
165
 
 
166
    def test_scenarios_include_transport_class(self):
 
167
        # This test used to know about all the possible transports and the
 
168
        # order they were returned but that seems overly brittle (mbp
 
169
        # 20060307)
 
170
        from bzrlib.tests.per_transport import transport_test_permutations
 
171
        scenarios = transport_test_permutations()
 
172
        # there are at least that many builtin transports
 
173
        self.assertTrue(len(scenarios) > 6)
 
174
        one_scenario = scenarios[0]
 
175
        self.assertIsInstance(one_scenario[0], str)
 
176
        self.assertTrue(issubclass(one_scenario[1]["transport_class"],
 
177
                                   bzrlib.transport.Transport))
 
178
        self.assertTrue(issubclass(one_scenario[1]["transport_server"],
 
179
                                   bzrlib.transport.Server))
 
180
 
 
181
 
 
182
class TestBranchScenarios(tests.TestCase):
 
183
 
 
184
    def test_scenarios(self):
 
185
        # check that constructor parameters are passed through to the adapted
 
186
        # test.
 
187
        from bzrlib.tests.per_branch import make_scenarios
 
188
        server1 = "a"
 
189
        server2 = "b"
 
190
        formats = [("c", "C"), ("d", "D")]
 
191
        scenarios = make_scenarios(server1, server2, formats)
 
192
        self.assertEqual(2, len(scenarios))
 
193
        self.assertEqual([
 
194
            ('str',
 
195
             {'branch_format': 'c',
 
196
              'bzrdir_format': 'C',
 
197
              'transport_readonly_server': 'b',
 
198
              'transport_server': 'a'}),
 
199
            ('str',
 
200
             {'branch_format': 'd',
 
201
              'bzrdir_format': 'D',
 
202
              'transport_readonly_server': 'b',
 
203
              'transport_server': 'a'})],
 
204
            scenarios)
 
205
 
 
206
 
 
207
class TestBzrDirScenarios(tests.TestCase):
 
208
 
 
209
    def test_scenarios(self):
 
210
        # check that constructor parameters are passed through to the adapted
 
211
        # test.
 
212
        from bzrlib.tests.per_controldir import make_scenarios
 
213
        vfs_factory = "v"
 
214
        server1 = "a"
 
215
        server2 = "b"
 
216
        formats = ["c", "d"]
 
217
        scenarios = make_scenarios(vfs_factory, server1, server2, formats)
 
218
        self.assertEqual([
 
219
            ('str',
 
220
             {'bzrdir_format': 'c',
 
221
              'transport_readonly_server': 'b',
 
222
              'transport_server': 'a',
 
223
              'vfs_transport_factory': 'v'}),
 
224
            ('str',
 
225
             {'bzrdir_format': 'd',
 
226
              'transport_readonly_server': 'b',
 
227
              'transport_server': 'a',
 
228
              'vfs_transport_factory': 'v'})],
 
229
            scenarios)
 
230
 
 
231
 
 
232
class TestRepositoryScenarios(tests.TestCase):
 
233
 
 
234
    def test_formats_to_scenarios(self):
 
235
        from bzrlib.tests.per_repository import formats_to_scenarios
 
236
        formats = [("(c)", remote.RemoteRepositoryFormat()),
 
237
                   ("(d)", repository.format_registry.get(
 
238
                    'Bazaar repository format 2a (needs bzr 1.16 or later)\n'))]
 
239
        no_vfs_scenarios = formats_to_scenarios(formats, "server", "readonly",
 
240
            None)
 
241
        vfs_scenarios = formats_to_scenarios(formats, "server", "readonly",
 
242
            vfs_transport_factory="vfs")
 
243
        # no_vfs generate scenarios without vfs_transport_factory
 
244
        expected = [
 
245
            ('RemoteRepositoryFormat(c)',
 
246
             {'bzrdir_format': remote.RemoteBzrDirFormat(),
 
247
              'repository_format': remote.RemoteRepositoryFormat(),
 
248
              'transport_readonly_server': 'readonly',
 
249
              'transport_server': 'server'}),
 
250
            ('RepositoryFormat2a(d)',
 
251
             {'bzrdir_format': bzrdir.BzrDirMetaFormat1(),
 
252
              'repository_format': groupcompress_repo.RepositoryFormat2a(),
 
253
              'transport_readonly_server': 'readonly',
 
254
              'transport_server': 'server'})]
 
255
        self.assertEqual(expected, no_vfs_scenarios)
 
256
        self.assertEqual([
 
257
            ('RemoteRepositoryFormat(c)',
 
258
             {'bzrdir_format': remote.RemoteBzrDirFormat(),
 
259
              'repository_format': remote.RemoteRepositoryFormat(),
 
260
              'transport_readonly_server': 'readonly',
 
261
              'transport_server': 'server',
 
262
              'vfs_transport_factory': 'vfs'}),
 
263
            ('RepositoryFormat2a(d)',
 
264
             {'bzrdir_format': bzrdir.BzrDirMetaFormat1(),
 
265
              'repository_format': groupcompress_repo.RepositoryFormat2a(),
 
266
              'transport_readonly_server': 'readonly',
 
267
              'transport_server': 'server',
 
268
              'vfs_transport_factory': 'vfs'})],
 
269
            vfs_scenarios)
 
270
 
 
271
 
 
272
class TestTestScenarioApplication(tests.TestCase):
 
273
    """Tests for the test adaption facilities."""
 
274
 
 
275
    def test_apply_scenario(self):
 
276
        from bzrlib.tests import apply_scenario
 
277
        input_test = TestTestScenarioApplication("test_apply_scenario")
 
278
        # setup two adapted tests
 
279
        adapted_test1 = apply_scenario(input_test,
 
280
            ("new id",
 
281
            {"bzrdir_format":"bzr_format",
 
282
             "repository_format":"repo_fmt",
 
283
             "transport_server":"transport_server",
 
284
             "transport_readonly_server":"readonly-server"}))
 
285
        adapted_test2 = apply_scenario(input_test,
 
286
            ("new id 2", {"bzrdir_format":None}))
 
287
        # input_test should have been altered.
 
288
        self.assertRaises(AttributeError, getattr, input_test, "bzrdir_format")
 
289
        # the new tests are mutually incompatible, ensuring it has
 
290
        # made new ones, and unspecified elements in the scenario
 
291
        # should not have been altered.
 
292
        self.assertEqual("bzr_format", adapted_test1.bzrdir_format)
 
293
        self.assertEqual("repo_fmt", adapted_test1.repository_format)
 
294
        self.assertEqual("transport_server", adapted_test1.transport_server)
 
295
        self.assertEqual("readonly-server",
 
296
            adapted_test1.transport_readonly_server)
 
297
        self.assertEqual(
 
298
            "bzrlib.tests.test_selftest.TestTestScenarioApplication."
 
299
            "test_apply_scenario(new id)",
 
300
            adapted_test1.id())
 
301
        self.assertEqual(None, adapted_test2.bzrdir_format)
 
302
        self.assertEqual(
 
303
            "bzrlib.tests.test_selftest.TestTestScenarioApplication."
 
304
            "test_apply_scenario(new id 2)",
 
305
            adapted_test2.id())
 
306
 
 
307
 
 
308
class TestInterRepositoryScenarios(tests.TestCase):
 
309
 
 
310
    def test_scenarios(self):
 
311
        # check that constructor parameters are passed through to the adapted
 
312
        # test.
 
313
        from bzrlib.tests.per_interrepository import make_scenarios
 
314
        server1 = "a"
 
315
        server2 = "b"
 
316
        formats = [("C0", "C1", "C2", "C3"), ("D0", "D1", "D2", "D3")]
 
317
        scenarios = make_scenarios(server1, server2, formats)
 
318
        self.assertEqual([
 
319
            ('C0,str,str',
 
320
             {'repository_format': 'C1',
 
321
              'repository_format_to': 'C2',
 
322
              'transport_readonly_server': 'b',
 
323
              'transport_server': 'a',
 
324
              'extra_setup': 'C3'}),
 
325
            ('D0,str,str',
 
326
             {'repository_format': 'D1',
 
327
              'repository_format_to': 'D2',
 
328
              'transport_readonly_server': 'b',
 
329
              'transport_server': 'a',
 
330
              'extra_setup': 'D3'})],
 
331
            scenarios)
 
332
 
 
333
 
 
334
class TestWorkingTreeScenarios(tests.TestCase):
 
335
 
 
336
    def test_scenarios(self):
 
337
        # check that constructor parameters are passed through to the adapted
 
338
        # test.
 
339
        from bzrlib.tests.per_workingtree import make_scenarios
 
340
        server1 = "a"
 
341
        server2 = "b"
 
342
        formats = [workingtree.WorkingTreeFormat2(),
 
343
                   workingtree.WorkingTreeFormat3(),]
 
344
        scenarios = make_scenarios(server1, server2, formats)
 
345
        self.assertEqual([
 
346
            ('WorkingTreeFormat2',
 
347
             {'bzrdir_format': formats[0]._matchingbzrdir,
 
348
              'transport_readonly_server': 'b',
 
349
              'transport_server': 'a',
 
350
              'workingtree_format': formats[0]}),
 
351
            ('WorkingTreeFormat3',
 
352
             {'bzrdir_format': formats[1]._matchingbzrdir,
 
353
              'transport_readonly_server': 'b',
 
354
              'transport_server': 'a',
 
355
              'workingtree_format': formats[1]})],
 
356
            scenarios)
 
357
 
 
358
 
 
359
class TestTreeScenarios(tests.TestCase):
 
360
 
 
361
    def test_scenarios(self):
 
362
        # the tree implementation scenario generator is meant to setup one
 
363
        # instance for each working tree format, and one additional instance
 
364
        # that will use the default wt format, but create a revision tree for
 
365
        # the tests.  this means that the wt ones should have the
 
366
        # workingtree_to_test_tree attribute set to 'return_parameter' and the
 
367
        # revision one set to revision_tree_from_workingtree.
 
368
 
 
369
        from bzrlib.tests.per_tree import (
 
370
            _dirstate_tree_from_workingtree,
 
371
            make_scenarios,
 
372
            preview_tree_pre,
 
373
            preview_tree_post,
 
374
            return_parameter,
 
375
            revision_tree_from_workingtree
 
376
            )
 
377
        server1 = "a"
 
378
        server2 = "b"
 
379
        formats = [workingtree.WorkingTreeFormat2(),
 
380
                   workingtree.WorkingTreeFormat3(),]
 
381
        scenarios = make_scenarios(server1, server2, formats)
 
382
        self.assertEqual(7, len(scenarios))
 
383
        default_wt_format = workingtree.WorkingTreeFormat4._default_format
 
384
        wt4_format = workingtree.WorkingTreeFormat4()
 
385
        wt5_format = workingtree.WorkingTreeFormat5()
 
386
        expected_scenarios = [
 
387
            ('WorkingTreeFormat2',
 
388
             {'bzrdir_format': formats[0]._matchingbzrdir,
 
389
              'transport_readonly_server': 'b',
 
390
              'transport_server': 'a',
 
391
              'workingtree_format': formats[0],
 
392
              '_workingtree_to_test_tree': return_parameter,
 
393
              }),
 
394
            ('WorkingTreeFormat3',
 
395
             {'bzrdir_format': formats[1]._matchingbzrdir,
 
396
              'transport_readonly_server': 'b',
 
397
              'transport_server': 'a',
 
398
              'workingtree_format': formats[1],
 
399
              '_workingtree_to_test_tree': return_parameter,
 
400
             }),
 
401
            ('RevisionTree',
 
402
             {'_workingtree_to_test_tree': revision_tree_from_workingtree,
 
403
              'bzrdir_format': default_wt_format._matchingbzrdir,
 
404
              'transport_readonly_server': 'b',
 
405
              'transport_server': 'a',
 
406
              'workingtree_format': default_wt_format,
 
407
             }),
 
408
            ('DirStateRevisionTree,WT4',
 
409
             {'_workingtree_to_test_tree': _dirstate_tree_from_workingtree,
 
410
              'bzrdir_format': wt4_format._matchingbzrdir,
 
411
              'transport_readonly_server': 'b',
 
412
              'transport_server': 'a',
 
413
              'workingtree_format': wt4_format,
 
414
             }),
 
415
            ('DirStateRevisionTree,WT5',
 
416
             {'_workingtree_to_test_tree': _dirstate_tree_from_workingtree,
 
417
              'bzrdir_format': wt5_format._matchingbzrdir,
 
418
              'transport_readonly_server': 'b',
 
419
              'transport_server': 'a',
 
420
              'workingtree_format': wt5_format,
 
421
             }),
 
422
            ('PreviewTree',
 
423
             {'_workingtree_to_test_tree': preview_tree_pre,
 
424
              'bzrdir_format': default_wt_format._matchingbzrdir,
 
425
              'transport_readonly_server': 'b',
 
426
              'transport_server': 'a',
 
427
              'workingtree_format': default_wt_format}),
 
428
            ('PreviewTreePost',
 
429
             {'_workingtree_to_test_tree': preview_tree_post,
 
430
              'bzrdir_format': default_wt_format._matchingbzrdir,
 
431
              'transport_readonly_server': 'b',
 
432
              'transport_server': 'a',
 
433
              'workingtree_format': default_wt_format}),
 
434
             ]
 
435
        self.assertEqual(expected_scenarios, scenarios)
 
436
 
 
437
 
 
438
class TestInterTreeScenarios(tests.TestCase):
 
439
    """A group of tests that test the InterTreeTestAdapter."""
 
440
 
 
441
    def test_scenarios(self):
 
442
        # check that constructor parameters are passed through to the adapted
 
443
        # test.
 
444
        # for InterTree tests we want the machinery to bring up two trees in
 
445
        # each instance: the base one, and the one we are interacting with.
 
446
        # because each optimiser can be direction specific, we need to test
 
447
        # each optimiser in its chosen direction.
 
448
        # unlike the TestProviderAdapter we dont want to automatically add a
 
449
        # parameterized one for WorkingTree - the optimisers will tell us what
 
450
        # ones to add.
 
451
        from bzrlib.tests.per_tree import (
 
452
            return_parameter,
 
453
            revision_tree_from_workingtree
 
454
            )
 
455
        from bzrlib.tests.per_intertree import (
 
456
            make_scenarios,
 
457
            )
 
458
        from bzrlib.workingtree import WorkingTreeFormat2, WorkingTreeFormat3
 
459
        input_test = TestInterTreeScenarios(
 
460
            "test_scenarios")
 
461
        server1 = "a"
 
462
        server2 = "b"
 
463
        format1 = WorkingTreeFormat2()
 
464
        format2 = WorkingTreeFormat3()
 
465
        formats = [("1", str, format1, format2, "converter1"),
 
466
            ("2", int, format2, format1, "converter2")]
 
467
        scenarios = make_scenarios(server1, server2, formats)
 
468
        self.assertEqual(2, len(scenarios))
 
469
        expected_scenarios = [
 
470
            ("1", {
 
471
                "bzrdir_format": format1._matchingbzrdir,
 
472
                "intertree_class": formats[0][1],
 
473
                "workingtree_format": formats[0][2],
 
474
                "workingtree_format_to": formats[0][3],
 
475
                "mutable_trees_to_test_trees": formats[0][4],
 
476
                "_workingtree_to_test_tree": return_parameter,
 
477
                "transport_server": server1,
 
478
                "transport_readonly_server": server2,
 
479
                }),
 
480
            ("2", {
 
481
                "bzrdir_format": format2._matchingbzrdir,
 
482
                "intertree_class": formats[1][1],
 
483
                "workingtree_format": formats[1][2],
 
484
                "workingtree_format_to": formats[1][3],
 
485
                "mutable_trees_to_test_trees": formats[1][4],
 
486
                "_workingtree_to_test_tree": return_parameter,
 
487
                "transport_server": server1,
 
488
                "transport_readonly_server": server2,
 
489
                }),
 
490
            ]
 
491
        self.assertEqual(scenarios, expected_scenarios)
 
492
 
 
493
 
 
494
class TestTestCaseInTempDir(tests.TestCaseInTempDir):
 
495
 
 
496
    def test_home_is_not_working(self):
 
497
        self.assertNotEqual(self.test_dir, self.test_home_dir)
 
498
        cwd = osutils.getcwd()
 
499
        self.assertIsSameRealPath(self.test_dir, cwd)
 
500
        self.assertIsSameRealPath(self.test_home_dir, os.environ['HOME'])
 
501
 
 
502
    def test_assertEqualStat_equal(self):
 
503
        from bzrlib.tests.test_dirstate import _FakeStat
 
504
        self.build_tree(["foo"])
 
505
        real = os.lstat("foo")
 
506
        fake = _FakeStat(real.st_size, real.st_mtime, real.st_ctime,
 
507
            real.st_dev, real.st_ino, real.st_mode)
 
508
        self.assertEqualStat(real, fake)
 
509
 
 
510
    def test_assertEqualStat_notequal(self):
 
511
        self.build_tree(["foo", "longname"])
 
512
        self.assertRaises(AssertionError, self.assertEqualStat,
 
513
            os.lstat("foo"), os.lstat("longname"))
 
514
 
 
515
 
 
516
class TestTestCaseWithMemoryTransport(tests.TestCaseWithMemoryTransport):
 
517
 
 
518
    def test_home_is_non_existant_dir_under_root(self):
 
519
        """The test_home_dir for TestCaseWithMemoryTransport is missing.
 
520
 
 
521
        This is because TestCaseWithMemoryTransport is for tests that do not
 
522
        need any disk resources: they should be hooked into bzrlib in such a
 
523
        way that no global settings are being changed by the test (only a
 
524
        few tests should need to do that), and having a missing dir as home is
 
525
        an effective way to ensure that this is the case.
 
526
        """
 
527
        self.assertIsSameRealPath(
 
528
            self.TEST_ROOT + "/MemoryTransportMissingHomeDir",
 
529
            self.test_home_dir)
 
530
        self.assertIsSameRealPath(self.test_home_dir, os.environ['HOME'])
 
531
 
 
532
    def test_cwd_is_TEST_ROOT(self):
 
533
        self.assertIsSameRealPath(self.test_dir, self.TEST_ROOT)
 
534
        cwd = osutils.getcwd()
 
535
        self.assertIsSameRealPath(self.test_dir, cwd)
 
536
 
 
537
    def test_BZR_HOME_and_HOME_are_bytestrings(self):
 
538
        """The $BZR_HOME and $HOME environment variables should not be unicode.
 
539
 
 
540
        See https://bugs.launchpad.net/bzr/+bug/464174
 
541
        """
 
542
        self.assertIsInstance(os.environ['BZR_HOME'], str)
 
543
        self.assertIsInstance(os.environ['HOME'], str)
 
544
 
 
545
    def test_make_branch_and_memory_tree(self):
 
546
        """In TestCaseWithMemoryTransport we should not make the branch on disk.
 
547
 
 
548
        This is hard to comprehensively robustly test, so we settle for making
 
549
        a branch and checking no directory was created at its relpath.
 
550
        """
 
551
        tree = self.make_branch_and_memory_tree('dir')
 
552
        # Guard against regression into MemoryTransport leaking
 
553
        # files to disk instead of keeping them in memory.
 
554
        self.failIf(osutils.lexists('dir'))
 
555
        self.assertIsInstance(tree, memorytree.MemoryTree)
 
556
 
 
557
    def test_make_branch_and_memory_tree_with_format(self):
 
558
        """make_branch_and_memory_tree should accept a format option."""
 
559
        format = bzrdir.BzrDirMetaFormat1()
 
560
        format.repository_format = weaverepo.RepositoryFormat7()
 
561
        tree = self.make_branch_and_memory_tree('dir', format=format)
 
562
        # Guard against regression into MemoryTransport leaking
 
563
        # files to disk instead of keeping them in memory.
 
564
        self.failIf(osutils.lexists('dir'))
 
565
        self.assertIsInstance(tree, memorytree.MemoryTree)
 
566
        self.assertEqual(format.repository_format.__class__,
 
567
            tree.branch.repository._format.__class__)
 
568
 
 
569
    def test_make_branch_builder(self):
 
570
        builder = self.make_branch_builder('dir')
 
571
        self.assertIsInstance(builder, branchbuilder.BranchBuilder)
 
572
        # Guard against regression into MemoryTransport leaking
 
573
        # files to disk instead of keeping them in memory.
 
574
        self.failIf(osutils.lexists('dir'))
 
575
 
 
576
    def test_make_branch_builder_with_format(self):
 
577
        # Use a repo layout that doesn't conform to a 'named' layout, to ensure
 
578
        # that the format objects are used.
 
579
        format = bzrdir.BzrDirMetaFormat1()
 
580
        repo_format = weaverepo.RepositoryFormat7()
 
581
        format.repository_format = repo_format
 
582
        builder = self.make_branch_builder('dir', format=format)
 
583
        the_branch = builder.get_branch()
 
584
        # Guard against regression into MemoryTransport leaking
 
585
        # files to disk instead of keeping them in memory.
 
586
        self.failIf(osutils.lexists('dir'))
 
587
        self.assertEqual(format.repository_format.__class__,
 
588
                         the_branch.repository._format.__class__)
 
589
        self.assertEqual(repo_format.get_format_string(),
 
590
                         self.get_transport().get_bytes(
 
591
                            'dir/.bzr/repository/format'))
 
592
 
 
593
    def test_make_branch_builder_with_format_name(self):
 
594
        builder = self.make_branch_builder('dir', format='knit')
 
595
        the_branch = builder.get_branch()
 
596
        # Guard against regression into MemoryTransport leaking
 
597
        # files to disk instead of keeping them in memory.
 
598
        self.failIf(osutils.lexists('dir'))
 
599
        dir_format = bzrdir.format_registry.make_bzrdir('knit')
 
600
        self.assertEqual(dir_format.repository_format.__class__,
 
601
                         the_branch.repository._format.__class__)
 
602
        self.assertEqual('Bazaar-NG Knit Repository Format 1',
 
603
                         self.get_transport().get_bytes(
 
604
                            'dir/.bzr/repository/format'))
 
605
 
 
606
    def test_dangling_locks_cause_failures(self):
 
607
        class TestDanglingLock(tests.TestCaseWithMemoryTransport):
 
608
            def test_function(self):
 
609
                t = self.get_transport('.')
 
610
                l = lockdir.LockDir(t, 'lock')
 
611
                l.create()
 
612
                l.attempt_lock()
 
613
        test = TestDanglingLock('test_function')
 
614
        result = test.run()
 
615
        total_failures = result.errors + result.failures
 
616
        if self._lock_check_thorough:
 
617
            self.assertEqual(1, len(total_failures))
 
618
        else:
 
619
            # When _lock_check_thorough is disabled, then we don't trigger a
 
620
            # failure
 
621
            self.assertEqual(0, len(total_failures))
 
622
 
 
623
 
 
624
class TestTestCaseWithTransport(tests.TestCaseWithTransport):
 
625
    """Tests for the convenience functions TestCaseWithTransport introduces."""
 
626
 
 
627
    def test_get_readonly_url_none(self):
 
628
        from bzrlib.transport.readonly import ReadonlyTransportDecorator
 
629
        self.vfs_transport_factory = memory.MemoryServer
 
630
        self.transport_readonly_server = None
 
631
        # calling get_readonly_transport() constructs a decorator on the url
 
632
        # for the server
 
633
        url = self.get_readonly_url()
 
634
        url2 = self.get_readonly_url('foo/bar')
 
635
        t = transport.get_transport(url)
 
636
        t2 = transport.get_transport(url2)
 
637
        self.failUnless(isinstance(t, ReadonlyTransportDecorator))
 
638
        self.failUnless(isinstance(t2, ReadonlyTransportDecorator))
 
639
        self.assertEqual(t2.base[:-1], t.abspath('foo/bar'))
 
640
 
 
641
    def test_get_readonly_url_http(self):
 
642
        from bzrlib.tests.http_server import HttpServer
 
643
        from bzrlib.transport.http import HttpTransportBase
 
644
        self.transport_server = test_server.LocalURLServer
 
645
        self.transport_readonly_server = HttpServer
 
646
        # calling get_readonly_transport() gives us a HTTP server instance.
 
647
        url = self.get_readonly_url()
 
648
        url2 = self.get_readonly_url('foo/bar')
 
649
        # the transport returned may be any HttpTransportBase subclass
 
650
        t = transport.get_transport(url)
 
651
        t2 = transport.get_transport(url2)
 
652
        self.failUnless(isinstance(t, HttpTransportBase))
 
653
        self.failUnless(isinstance(t2, HttpTransportBase))
 
654
        self.assertEqual(t2.base[:-1], t.abspath('foo/bar'))
 
655
 
 
656
    def test_is_directory(self):
 
657
        """Test assertIsDirectory assertion"""
 
658
        t = self.get_transport()
 
659
        self.build_tree(['a_dir/', 'a_file'], transport=t)
 
660
        self.assertIsDirectory('a_dir', t)
 
661
        self.assertRaises(AssertionError, self.assertIsDirectory, 'a_file', t)
 
662
        self.assertRaises(AssertionError, self.assertIsDirectory, 'not_here', t)
 
663
 
 
664
    def test_make_branch_builder(self):
 
665
        builder = self.make_branch_builder('dir')
 
666
        rev_id = builder.build_commit()
 
667
        self.failUnlessExists('dir')
 
668
        a_dir = bzrdir.BzrDir.open('dir')
 
669
        self.assertRaises(errors.NoWorkingTree, a_dir.open_workingtree)
 
670
        a_branch = a_dir.open_branch()
 
671
        builder_branch = builder.get_branch()
 
672
        self.assertEqual(a_branch.base, builder_branch.base)
 
673
        self.assertEqual((1, rev_id), builder_branch.last_revision_info())
 
674
        self.assertEqual((1, rev_id), a_branch.last_revision_info())
 
675
 
 
676
 
 
677
class TestTestCaseTransports(tests.TestCaseWithTransport):
 
678
 
 
679
    def setUp(self):
 
680
        super(TestTestCaseTransports, self).setUp()
 
681
        self.vfs_transport_factory = memory.MemoryServer
 
682
 
 
683
    def test_make_bzrdir_preserves_transport(self):
 
684
        t = self.get_transport()
 
685
        result_bzrdir = self.make_bzrdir('subdir')
 
686
        self.assertIsInstance(result_bzrdir.transport,
 
687
                              memory.MemoryTransport)
 
688
        # should not be on disk, should only be in memory
 
689
        self.failIfExists('subdir')
 
690
 
 
691
 
 
692
class TestChrootedTest(tests.ChrootedTestCase):
 
693
 
 
694
    def test_root_is_root(self):
 
695
        t = transport.get_transport(self.get_readonly_url())
 
696
        url = t.base
 
697
        self.assertEqual(url, t.clone('..').base)
 
698
 
 
699
 
 
700
class TestProfileResult(tests.TestCase):
 
701
 
 
702
    def test_profiles_tests(self):
 
703
        self.requireFeature(test_lsprof.LSProfFeature)
 
704
        terminal = testtools.tests.helpers.ExtendedTestResult()
 
705
        result = tests.ProfileResult(terminal)
 
706
        class Sample(tests.TestCase):
 
707
            def a(self):
 
708
                self.sample_function()
 
709
            def sample_function(self):
 
710
                pass
 
711
        test = Sample("a")
 
712
        test.run(result)
 
713
        case = terminal._events[0][1]
 
714
        self.assertLength(1, case._benchcalls)
 
715
        # We must be able to unpack it as the test reporting code wants
 
716
        (_, _, _), stats = case._benchcalls[0]
 
717
        self.assertTrue(callable(stats.pprint))
 
718
 
 
719
 
 
720
class TestTestResult(tests.TestCase):
 
721
 
 
722
    def check_timing(self, test_case, expected_re):
 
723
        result = bzrlib.tests.TextTestResult(self._log_file,
 
724
                descriptions=0,
 
725
                verbosity=1,
 
726
                )
 
727
        capture = testtools.tests.helpers.ExtendedTestResult()
 
728
        test_case.run(MultiTestResult(result, capture))
 
729
        run_case = capture._events[0][1]
 
730
        timed_string = result._testTimeString(run_case)
 
731
        self.assertContainsRe(timed_string, expected_re)
 
732
 
 
733
    def test_test_reporting(self):
 
734
        class ShortDelayTestCase(tests.TestCase):
 
735
            def test_short_delay(self):
 
736
                time.sleep(0.003)
 
737
            def test_short_benchmark(self):
 
738
                self.time(time.sleep, 0.003)
 
739
        self.check_timing(ShortDelayTestCase('test_short_delay'),
 
740
                          r"^ +[0-9]+ms$")
 
741
        # if a benchmark time is given, we now show just that time followed by
 
742
        # a star
 
743
        self.check_timing(ShortDelayTestCase('test_short_benchmark'),
 
744
                          r"^ +[0-9]+ms\*$")
 
745
 
 
746
    def test_unittest_reporting_unittest_class(self):
 
747
        # getting the time from a non-bzrlib test works ok
 
748
        class ShortDelayTestCase(unittest.TestCase):
 
749
            def test_short_delay(self):
 
750
                time.sleep(0.003)
 
751
        self.check_timing(ShortDelayTestCase('test_short_delay'),
 
752
                          r"^ +[0-9]+ms$")
 
753
 
 
754
    def _patch_get_bzr_source_tree(self):
 
755
        # Reading from the actual source tree breaks isolation, but we don't
 
756
        # want to assume that thats *all* that would happen.
 
757
        self.overrideAttr(bzrlib.version, '_get_bzr_source_tree', lambda: None)
 
758
 
 
759
    def test_assigned_benchmark_file_stores_date(self):
 
760
        self._patch_get_bzr_source_tree()
 
761
        output = StringIO()
 
762
        result = bzrlib.tests.TextTestResult(self._log_file,
 
763
                                        descriptions=0,
 
764
                                        verbosity=1,
 
765
                                        bench_history=output
 
766
                                        )
 
767
        output_string = output.getvalue()
 
768
        # if you are wondering about the regexp please read the comment in
 
769
        # test_bench_history (bzrlib.tests.test_selftest.TestRunner)
 
770
        # XXX: what comment?  -- Andrew Bennetts
 
771
        self.assertContainsRe(output_string, "--date [0-9.]+")
 
772
 
 
773
    def test_benchhistory_records_test_times(self):
 
774
        self._patch_get_bzr_source_tree()
 
775
        result_stream = StringIO()
 
776
        result = bzrlib.tests.TextTestResult(
 
777
            self._log_file,
 
778
            descriptions=0,
 
779
            verbosity=1,
 
780
            bench_history=result_stream
 
781
            )
 
782
 
 
783
        # we want profile a call and check that its test duration is recorded
 
784
        # make a new test instance that when run will generate a benchmark
 
785
        example_test_case = TestTestResult("_time_hello_world_encoding")
 
786
        # execute the test, which should succeed and record times
 
787
        example_test_case.run(result)
 
788
        lines = result_stream.getvalue().splitlines()
 
789
        self.assertEqual(2, len(lines))
 
790
        self.assertContainsRe(lines[1],
 
791
            " *[0-9]+ms bzrlib.tests.test_selftest.TestTestResult"
 
792
            "._time_hello_world_encoding")
 
793
 
 
794
    def _time_hello_world_encoding(self):
 
795
        """Profile two sleep calls
 
796
 
 
797
        This is used to exercise the test framework.
 
798
        """
 
799
        self.time(unicode, 'hello', errors='replace')
 
800
        self.time(unicode, 'world', errors='replace')
 
801
 
 
802
    def test_lsprofiling(self):
 
803
        """Verbose test result prints lsprof statistics from test cases."""
 
804
        self.requireFeature(test_lsprof.LSProfFeature)
 
805
        result_stream = StringIO()
 
806
        result = bzrlib.tests.VerboseTestResult(
 
807
            result_stream,
 
808
            descriptions=0,
 
809
            verbosity=2,
 
810
            )
 
811
        # we want profile a call of some sort and check it is output by
 
812
        # addSuccess. We dont care about addError or addFailure as they
 
813
        # are not that interesting for performance tuning.
 
814
        # make a new test instance that when run will generate a profile
 
815
        example_test_case = TestTestResult("_time_hello_world_encoding")
 
816
        example_test_case._gather_lsprof_in_benchmarks = True
 
817
        # execute the test, which should succeed and record profiles
 
818
        example_test_case.run(result)
 
819
        # lsprofile_something()
 
820
        # if this worked we want
 
821
        # LSProf output for <built in function unicode> (['hello'], {'errors': 'replace'})
 
822
        #    CallCount    Recursive    Total(ms)   Inline(ms) module:lineno(function)
 
823
        # (the lsprof header)
 
824
        # ... an arbitrary number of lines
 
825
        # and the function call which is time.sleep.
 
826
        #           1        0            ???         ???       ???(sleep)
 
827
        # and then repeated but with 'world', rather than 'hello'.
 
828
        # this should appear in the output stream of our test result.
 
829
        output = result_stream.getvalue()
 
830
        self.assertContainsRe(output,
 
831
            r"LSProf output for <type 'unicode'>\(\('hello',\), {'errors': 'replace'}\)")
 
832
        self.assertContainsRe(output,
 
833
            r" *CallCount *Recursive *Total\(ms\) *Inline\(ms\) *module:lineno\(function\)\n")
 
834
        self.assertContainsRe(output,
 
835
            r"( +1 +0 +0\.\d+ +0\.\d+ +<method 'disable' of '_lsprof\.Profiler' objects>\n)?")
 
836
        self.assertContainsRe(output,
 
837
            r"LSProf output for <type 'unicode'>\(\('world',\), {'errors': 'replace'}\)\n")
 
838
 
 
839
    def test_uses_time_from_testtools(self):
 
840
        """Test case timings in verbose results should use testtools times"""
 
841
        import datetime
 
842
        class TimeAddedVerboseTestResult(tests.VerboseTestResult):
 
843
            def startTest(self, test):
 
844
                self.time(datetime.datetime.utcfromtimestamp(1.145))
 
845
                super(TimeAddedVerboseTestResult, self).startTest(test)
 
846
            def addSuccess(self, test):
 
847
                self.time(datetime.datetime.utcfromtimestamp(51.147))
 
848
                super(TimeAddedVerboseTestResult, self).addSuccess(test)
 
849
            def report_tests_starting(self): pass
 
850
        sio = StringIO()
 
851
        self.get_passing_test().run(TimeAddedVerboseTestResult(sio, 0, 2))
 
852
        self.assertEndsWith(sio.getvalue(), "OK    50002ms\n")
 
853
 
 
854
    def test_known_failure(self):
 
855
        """A KnownFailure being raised should trigger several result actions."""
 
856
        class InstrumentedTestResult(tests.ExtendedTestResult):
 
857
            def stopTestRun(self): pass
 
858
            def report_tests_starting(self): pass
 
859
            def report_known_failure(self, test, err=None, details=None):
 
860
                self._call = test, 'known failure'
 
861
        result = InstrumentedTestResult(None, None, None, None)
 
862
        class Test(tests.TestCase):
 
863
            def test_function(self):
 
864
                raise tests.KnownFailure('failed!')
 
865
        test = Test("test_function")
 
866
        test.run(result)
 
867
        # it should invoke 'report_known_failure'.
 
868
        self.assertEqual(2, len(result._call))
 
869
        self.assertEqual(test.id(), result._call[0].id())
 
870
        self.assertEqual('known failure', result._call[1])
 
871
        # we dont introspec the traceback, if the rest is ok, it would be
 
872
        # exceptional for it not to be.
 
873
        # it should update the known_failure_count on the object.
 
874
        self.assertEqual(1, result.known_failure_count)
 
875
        # the result should be successful.
 
876
        self.assertTrue(result.wasSuccessful())
 
877
 
 
878
    def test_verbose_report_known_failure(self):
 
879
        # verbose test output formatting
 
880
        result_stream = StringIO()
 
881
        result = bzrlib.tests.VerboseTestResult(
 
882
            result_stream,
 
883
            descriptions=0,
 
884
            verbosity=2,
 
885
            )
 
886
        test = self.get_passing_test()
 
887
        result.startTest(test)
 
888
        prefix = len(result_stream.getvalue())
 
889
        # the err parameter has the shape:
 
890
        # (class, exception object, traceback)
 
891
        # KnownFailures dont get their tracebacks shown though, so we
 
892
        # can skip that.
 
893
        err = (tests.KnownFailure, tests.KnownFailure('foo'), None)
 
894
        result.report_known_failure(test, err)
 
895
        output = result_stream.getvalue()[prefix:]
 
896
        lines = output.splitlines()
 
897
        self.assertContainsRe(lines[0], r'XFAIL *\d+ms$')
 
898
        if sys.version_info > (2, 7):
 
899
            self.expectFailure("_ExpectedFailure on 2.7 loses the message",
 
900
                self.assertNotEqual, lines[1], '    ')
 
901
        self.assertEqual(lines[1], '    foo')
 
902
        self.assertEqual(2, len(lines))
 
903
 
 
904
    def get_passing_test(self):
 
905
        """Return a test object that can't be run usefully."""
 
906
        def passing_test():
 
907
            pass
 
908
        return unittest.FunctionTestCase(passing_test)
 
909
 
 
910
    def test_add_not_supported(self):
 
911
        """Test the behaviour of invoking addNotSupported."""
 
912
        class InstrumentedTestResult(tests.ExtendedTestResult):
 
913
            def stopTestRun(self): pass
 
914
            def report_tests_starting(self): pass
 
915
            def report_unsupported(self, test, feature):
 
916
                self._call = test, feature
 
917
        result = InstrumentedTestResult(None, None, None, None)
 
918
        test = SampleTestCase('_test_pass')
 
919
        feature = tests.Feature()
 
920
        result.startTest(test)
 
921
        result.addNotSupported(test, feature)
 
922
        # it should invoke 'report_unsupported'.
 
923
        self.assertEqual(2, len(result._call))
 
924
        self.assertEqual(test, result._call[0])
 
925
        self.assertEqual(feature, result._call[1])
 
926
        # the result should be successful.
 
927
        self.assertTrue(result.wasSuccessful())
 
928
        # it should record the test against a count of tests not run due to
 
929
        # this feature.
 
930
        self.assertEqual(1, result.unsupported['Feature'])
 
931
        # and invoking it again should increment that counter
 
932
        result.addNotSupported(test, feature)
 
933
        self.assertEqual(2, result.unsupported['Feature'])
 
934
 
 
935
    def test_verbose_report_unsupported(self):
 
936
        # verbose test output formatting
 
937
        result_stream = StringIO()
 
938
        result = bzrlib.tests.VerboseTestResult(
 
939
            result_stream,
 
940
            descriptions=0,
 
941
            verbosity=2,
 
942
            )
 
943
        test = self.get_passing_test()
 
944
        feature = tests.Feature()
 
945
        result.startTest(test)
 
946
        prefix = len(result_stream.getvalue())
 
947
        result.report_unsupported(test, feature)
 
948
        output = result_stream.getvalue()[prefix:]
 
949
        lines = output.splitlines()
 
950
        # We don't check for the final '0ms' since it may fail on slow hosts
 
951
        self.assertStartsWith(lines[0], 'NODEP')
 
952
        self.assertEqual(lines[1],
 
953
                         "    The feature 'Feature' is not available.")
 
954
 
 
955
    def test_unavailable_exception(self):
 
956
        """An UnavailableFeature being raised should invoke addNotSupported."""
 
957
        class InstrumentedTestResult(tests.ExtendedTestResult):
 
958
            def stopTestRun(self): pass
 
959
            def report_tests_starting(self): pass
 
960
            def addNotSupported(self, test, feature):
 
961
                self._call = test, feature
 
962
        result = InstrumentedTestResult(None, None, None, None)
 
963
        feature = tests.Feature()
 
964
        class Test(tests.TestCase):
 
965
            def test_function(self):
 
966
                raise tests.UnavailableFeature(feature)
 
967
        test = Test("test_function")
 
968
        test.run(result)
 
969
        # it should invoke 'addNotSupported'.
 
970
        self.assertEqual(2, len(result._call))
 
971
        self.assertEqual(test.id(), result._call[0].id())
 
972
        self.assertEqual(feature, result._call[1])
 
973
        # and not count as an error
 
974
        self.assertEqual(0, result.error_count)
 
975
 
 
976
    def test_strict_with_unsupported_feature(self):
 
977
        result = bzrlib.tests.TextTestResult(self._log_file, descriptions=0,
 
978
                                             verbosity=1)
 
979
        test = self.get_passing_test()
 
980
        feature = "Unsupported Feature"
 
981
        result.addNotSupported(test, feature)
 
982
        self.assertFalse(result.wasStrictlySuccessful())
 
983
        self.assertEqual(None, result._extractBenchmarkTime(test))
 
984
 
 
985
    def test_strict_with_known_failure(self):
 
986
        result = bzrlib.tests.TextTestResult(self._log_file, descriptions=0,
 
987
                                             verbosity=1)
 
988
        test = self.get_passing_test()
 
989
        err = (tests.KnownFailure, tests.KnownFailure('foo'), None)
 
990
        result.addExpectedFailure(test, err)
 
991
        self.assertFalse(result.wasStrictlySuccessful())
 
992
        self.assertEqual(None, result._extractBenchmarkTime(test))
 
993
 
 
994
    def test_strict_with_success(self):
 
995
        result = bzrlib.tests.TextTestResult(self._log_file, descriptions=0,
 
996
                                             verbosity=1)
 
997
        test = self.get_passing_test()
 
998
        result.addSuccess(test)
 
999
        self.assertTrue(result.wasStrictlySuccessful())
 
1000
        self.assertEqual(None, result._extractBenchmarkTime(test))
 
1001
 
 
1002
    def test_startTests(self):
 
1003
        """Starting the first test should trigger startTests."""
 
1004
        class InstrumentedTestResult(tests.ExtendedTestResult):
 
1005
            calls = 0
 
1006
            def startTests(self): self.calls += 1
 
1007
        result = InstrumentedTestResult(None, None, None, None)
 
1008
        def test_function():
 
1009
            pass
 
1010
        test = unittest.FunctionTestCase(test_function)
 
1011
        test.run(result)
 
1012
        self.assertEquals(1, result.calls)
 
1013
 
 
1014
    def test_startTests_only_once(self):
 
1015
        """With multiple tests startTests should still only be called once"""
 
1016
        class InstrumentedTestResult(tests.ExtendedTestResult):
 
1017
            calls = 0
 
1018
            def startTests(self): self.calls += 1
 
1019
        result = InstrumentedTestResult(None, None, None, None)
 
1020
        suite = unittest.TestSuite([
 
1021
            unittest.FunctionTestCase(lambda: None),
 
1022
            unittest.FunctionTestCase(lambda: None)])
 
1023
        suite.run(result)
 
1024
        self.assertEquals(1, result.calls)
 
1025
        self.assertEquals(2, result.count)
 
1026
 
 
1027
 
 
1028
class TestUnicodeFilenameFeature(tests.TestCase):
 
1029
 
 
1030
    def test_probe_passes(self):
 
1031
        """UnicodeFilenameFeature._probe passes."""
 
1032
        # We can't test much more than that because the behaviour depends
 
1033
        # on the platform.
 
1034
        tests.UnicodeFilenameFeature._probe()
 
1035
 
 
1036
 
 
1037
class TestRunner(tests.TestCase):
 
1038
 
 
1039
    def dummy_test(self):
 
1040
        pass
 
1041
 
 
1042
    def run_test_runner(self, testrunner, test):
 
1043
        """Run suite in testrunner, saving global state and restoring it.
 
1044
 
 
1045
        This current saves and restores:
 
1046
        TestCaseInTempDir.TEST_ROOT
 
1047
 
 
1048
        There should be no tests in this file that use
 
1049
        bzrlib.tests.TextTestRunner without using this convenience method,
 
1050
        because of our use of global state.
 
1051
        """
 
1052
        old_root = tests.TestCaseInTempDir.TEST_ROOT
 
1053
        try:
 
1054
            tests.TestCaseInTempDir.TEST_ROOT = None
 
1055
            return testrunner.run(test)
 
1056
        finally:
 
1057
            tests.TestCaseInTempDir.TEST_ROOT = old_root
 
1058
 
 
1059
    def test_known_failure_failed_run(self):
 
1060
        # run a test that generates a known failure which should be printed in
 
1061
        # the final output when real failures occur.
 
1062
        class Test(tests.TestCase):
 
1063
            def known_failure_test(self):
 
1064
                self.expectFailure('failed', self.assertTrue, False)
 
1065
        test = unittest.TestSuite()
 
1066
        test.addTest(Test("known_failure_test"))
 
1067
        def failing_test():
 
1068
            self.fail('foo')
 
1069
        test.addTest(unittest.FunctionTestCase(failing_test))
 
1070
        stream = StringIO()
 
1071
        runner = tests.TextTestRunner(stream=stream)
 
1072
        result = self.run_test_runner(runner, test)
 
1073
        lines = stream.getvalue().splitlines()
 
1074
        self.assertContainsRe(stream.getvalue(),
 
1075
            '(?sm)^bzr selftest.*$'
 
1076
            '.*'
 
1077
            '^======================================================================\n'
 
1078
            '^FAIL: failing_test\n'
 
1079
            '^----------------------------------------------------------------------\n'
 
1080
            'Traceback \\(most recent call last\\):\n'
 
1081
            '  .*' # File .*, line .*, in failing_test' - but maybe not from .pyc
 
1082
            '    self.fail\\(\'foo\'\\)\n'
 
1083
            '.*'
 
1084
            '^----------------------------------------------------------------------\n'
 
1085
            '.*'
 
1086
            'FAILED \\(failures=1, known_failure_count=1\\)'
 
1087
            )
 
1088
 
 
1089
    def test_known_failure_ok_run(self):
 
1090
        # run a test that generates a known failure which should be printed in
 
1091
        # the final output.
 
1092
        class Test(tests.TestCase):
 
1093
            def known_failure_test(self):
 
1094
                self.expectFailure('failed', self.assertTrue, False)
 
1095
        test = Test("known_failure_test")
 
1096
        stream = StringIO()
 
1097
        runner = tests.TextTestRunner(stream=stream)
 
1098
        result = self.run_test_runner(runner, test)
 
1099
        self.assertContainsRe(stream.getvalue(),
 
1100
            '\n'
 
1101
            '-*\n'
 
1102
            'Ran 1 test in .*\n'
 
1103
            '\n'
 
1104
            'OK \\(known_failures=1\\)\n')
 
1105
 
 
1106
    def test_result_decorator(self):
 
1107
        # decorate results
 
1108
        calls = []
 
1109
        class LoggingDecorator(ExtendedToOriginalDecorator):
 
1110
            def startTest(self, test):
 
1111
                ExtendedToOriginalDecorator.startTest(self, test)
 
1112
                calls.append('start')
 
1113
        test = unittest.FunctionTestCase(lambda:None)
 
1114
        stream = StringIO()
 
1115
        runner = tests.TextTestRunner(stream=stream,
 
1116
            result_decorators=[LoggingDecorator])
 
1117
        result = self.run_test_runner(runner, test)
 
1118
        self.assertLength(1, calls)
 
1119
 
 
1120
    def test_skipped_test(self):
 
1121
        # run a test that is skipped, and check the suite as a whole still
 
1122
        # succeeds.
 
1123
        # skipping_test must be hidden in here so it's not run as a real test
 
1124
        class SkippingTest(tests.TestCase):
 
1125
            def skipping_test(self):
 
1126
                raise tests.TestSkipped('test intentionally skipped')
 
1127
        runner = tests.TextTestRunner(stream=self._log_file)
 
1128
        test = SkippingTest("skipping_test")
 
1129
        result = self.run_test_runner(runner, test)
 
1130
        self.assertTrue(result.wasSuccessful())
 
1131
 
 
1132
    def test_skipped_from_setup(self):
 
1133
        calls = []
 
1134
        class SkippedSetupTest(tests.TestCase):
 
1135
 
 
1136
            def setUp(self):
 
1137
                calls.append('setUp')
 
1138
                self.addCleanup(self.cleanup)
 
1139
                raise tests.TestSkipped('skipped setup')
 
1140
 
 
1141
            def test_skip(self):
 
1142
                self.fail('test reached')
 
1143
 
 
1144
            def cleanup(self):
 
1145
                calls.append('cleanup')
 
1146
 
 
1147
        runner = tests.TextTestRunner(stream=self._log_file)
 
1148
        test = SkippedSetupTest('test_skip')
 
1149
        result = self.run_test_runner(runner, test)
 
1150
        self.assertTrue(result.wasSuccessful())
 
1151
        # Check if cleanup was called the right number of times.
 
1152
        self.assertEqual(['setUp', 'cleanup'], calls)
 
1153
 
 
1154
    def test_skipped_from_test(self):
 
1155
        calls = []
 
1156
        class SkippedTest(tests.TestCase):
 
1157
 
 
1158
            def setUp(self):
 
1159
                tests.TestCase.setUp(self)
 
1160
                calls.append('setUp')
 
1161
                self.addCleanup(self.cleanup)
 
1162
 
 
1163
            def test_skip(self):
 
1164
                raise tests.TestSkipped('skipped test')
 
1165
 
 
1166
            def cleanup(self):
 
1167
                calls.append('cleanup')
 
1168
 
 
1169
        runner = tests.TextTestRunner(stream=self._log_file)
 
1170
        test = SkippedTest('test_skip')
 
1171
        result = self.run_test_runner(runner, test)
 
1172
        self.assertTrue(result.wasSuccessful())
 
1173
        # Check if cleanup was called the right number of times.
 
1174
        self.assertEqual(['setUp', 'cleanup'], calls)
 
1175
 
 
1176
    def test_not_applicable(self):
 
1177
        # run a test that is skipped because it's not applicable
 
1178
        class Test(tests.TestCase):
 
1179
            def not_applicable_test(self):
 
1180
                raise tests.TestNotApplicable('this test never runs')
 
1181
        out = StringIO()
 
1182
        runner = tests.TextTestRunner(stream=out, verbosity=2)
 
1183
        test = Test("not_applicable_test")
 
1184
        result = self.run_test_runner(runner, test)
 
1185
        self._log_file.write(out.getvalue())
 
1186
        self.assertTrue(result.wasSuccessful())
 
1187
        self.assertTrue(result.wasStrictlySuccessful())
 
1188
        self.assertContainsRe(out.getvalue(),
 
1189
                r'(?m)not_applicable_test   * N/A')
 
1190
        self.assertContainsRe(out.getvalue(),
 
1191
                r'(?m)^    this test never runs')
 
1192
 
 
1193
    def test_unsupported_features_listed(self):
 
1194
        """When unsupported features are encountered they are detailed."""
 
1195
        class Feature1(tests.Feature):
 
1196
            def _probe(self): return False
 
1197
        class Feature2(tests.Feature):
 
1198
            def _probe(self): return False
 
1199
        # create sample tests
 
1200
        test1 = SampleTestCase('_test_pass')
 
1201
        test1._test_needs_features = [Feature1()]
 
1202
        test2 = SampleTestCase('_test_pass')
 
1203
        test2._test_needs_features = [Feature2()]
 
1204
        test = unittest.TestSuite()
 
1205
        test.addTest(test1)
 
1206
        test.addTest(test2)
 
1207
        stream = StringIO()
 
1208
        runner = tests.TextTestRunner(stream=stream)
 
1209
        result = self.run_test_runner(runner, test)
 
1210
        lines = stream.getvalue().splitlines()
 
1211
        self.assertEqual([
 
1212
            'OK',
 
1213
            "Missing feature 'Feature1' skipped 1 tests.",
 
1214
            "Missing feature 'Feature2' skipped 1 tests.",
 
1215
            ],
 
1216
            lines[-3:])
 
1217
 
 
1218
    def _patch_get_bzr_source_tree(self):
 
1219
        # Reading from the actual source tree breaks isolation, but we don't
 
1220
        # want to assume that thats *all* that would happen.
 
1221
        self._get_source_tree_calls = []
 
1222
        def new_get():
 
1223
            self._get_source_tree_calls.append("called")
 
1224
            return None
 
1225
        self.overrideAttr(bzrlib.version, '_get_bzr_source_tree',  new_get)
 
1226
 
 
1227
    def test_bench_history(self):
 
1228
        # tests that the running the benchmark passes bench_history into
 
1229
        # the test result object. We can tell that happens if
 
1230
        # _get_bzr_source_tree is called.
 
1231
        self._patch_get_bzr_source_tree()
 
1232
        test = TestRunner('dummy_test')
 
1233
        output = StringIO()
 
1234
        runner = tests.TextTestRunner(stream=self._log_file,
 
1235
                                      bench_history=output)
 
1236
        result = self.run_test_runner(runner, test)
 
1237
        output_string = output.getvalue()
 
1238
        self.assertContainsRe(output_string, "--date [0-9.]+")
 
1239
        self.assertLength(1, self._get_source_tree_calls)
 
1240
 
 
1241
    def test_verbose_test_count(self):
 
1242
        """A verbose test run reports the right test count at the start"""
 
1243
        suite = TestUtil.TestSuite([
 
1244
            unittest.FunctionTestCase(lambda:None),
 
1245
            unittest.FunctionTestCase(lambda:None)])
 
1246
        self.assertEqual(suite.countTestCases(), 2)
 
1247
        stream = StringIO()
 
1248
        runner = tests.TextTestRunner(stream=stream, verbosity=2)
 
1249
        # Need to use the CountingDecorator as that's what sets num_tests
 
1250
        result = self.run_test_runner(runner, tests.CountingDecorator(suite))
 
1251
        self.assertStartsWith(stream.getvalue(), "running 2 tests")
 
1252
 
 
1253
    def test_startTestRun(self):
 
1254
        """run should call result.startTestRun()"""
 
1255
        calls = []
 
1256
        class LoggingDecorator(ExtendedToOriginalDecorator):
 
1257
            def startTestRun(self):
 
1258
                ExtendedToOriginalDecorator.startTestRun(self)
 
1259
                calls.append('startTestRun')
 
1260
        test = unittest.FunctionTestCase(lambda:None)
 
1261
        stream = StringIO()
 
1262
        runner = tests.TextTestRunner(stream=stream,
 
1263
            result_decorators=[LoggingDecorator])
 
1264
        result = self.run_test_runner(runner, test)
 
1265
        self.assertLength(1, calls)
 
1266
 
 
1267
    def test_stopTestRun(self):
 
1268
        """run should call result.stopTestRun()"""
 
1269
        calls = []
 
1270
        class LoggingDecorator(ExtendedToOriginalDecorator):
 
1271
            def stopTestRun(self):
 
1272
                ExtendedToOriginalDecorator.stopTestRun(self)
 
1273
                calls.append('stopTestRun')
 
1274
        test = unittest.FunctionTestCase(lambda:None)
 
1275
        stream = StringIO()
 
1276
        runner = tests.TextTestRunner(stream=stream,
 
1277
            result_decorators=[LoggingDecorator])
 
1278
        result = self.run_test_runner(runner, test)
 
1279
        self.assertLength(1, calls)
 
1280
 
 
1281
    def test_unicode_test_output_on_ascii_stream(self):
 
1282
        """Showing results should always succeed even on an ascii console"""
 
1283
        class FailureWithUnicode(tests.TestCase):
 
1284
            def test_log_unicode(self):
 
1285
                self.log(u"\u2606")
 
1286
                self.fail("Now print that log!")
 
1287
        out = StringIO()
 
1288
        self.overrideAttr(osutils, "get_terminal_encoding",
 
1289
            lambda trace=False: "ascii")
 
1290
        result = self.run_test_runner(tests.TextTestRunner(stream=out),
 
1291
            FailureWithUnicode("test_log_unicode"))
 
1292
        self.assertContainsRe(out.getvalue(),
 
1293
            "Text attachment: log\n"
 
1294
            "-+\n"
 
1295
            "\d+\.\d+  \\\\u2606\n"
 
1296
            "-+\n")
 
1297
 
 
1298
 
 
1299
class SampleTestCase(tests.TestCase):
 
1300
 
 
1301
    def _test_pass(self):
 
1302
        pass
 
1303
 
 
1304
class _TestException(Exception):
 
1305
    pass
 
1306
 
 
1307
 
 
1308
class TestTestCase(tests.TestCase):
 
1309
    """Tests that test the core bzrlib TestCase."""
 
1310
 
 
1311
    def test_assertLength_matches_empty(self):
 
1312
        a_list = []
 
1313
        self.assertLength(0, a_list)
 
1314
 
 
1315
    def test_assertLength_matches_nonempty(self):
 
1316
        a_list = [1, 2, 3]
 
1317
        self.assertLength(3, a_list)
 
1318
 
 
1319
    def test_assertLength_fails_different(self):
 
1320
        a_list = []
 
1321
        self.assertRaises(AssertionError, self.assertLength, 1, a_list)
 
1322
 
 
1323
    def test_assertLength_shows_sequence_in_failure(self):
 
1324
        a_list = [1, 2, 3]
 
1325
        exception = self.assertRaises(AssertionError, self.assertLength, 2,
 
1326
            a_list)
 
1327
        self.assertEqual('Incorrect length: wanted 2, got 3 for [1, 2, 3]',
 
1328
            exception.args[0])
 
1329
 
 
1330
    def test_base_setUp_not_called_causes_failure(self):
 
1331
        class TestCaseWithBrokenSetUp(tests.TestCase):
 
1332
            def setUp(self):
 
1333
                pass # does not call TestCase.setUp
 
1334
            def test_foo(self):
 
1335
                pass
 
1336
        test = TestCaseWithBrokenSetUp('test_foo')
 
1337
        result = unittest.TestResult()
 
1338
        test.run(result)
 
1339
        self.assertFalse(result.wasSuccessful())
 
1340
        self.assertEqual(1, result.testsRun)
 
1341
 
 
1342
    def test_base_tearDown_not_called_causes_failure(self):
 
1343
        class TestCaseWithBrokenTearDown(tests.TestCase):
 
1344
            def tearDown(self):
 
1345
                pass # does not call TestCase.tearDown
 
1346
            def test_foo(self):
 
1347
                pass
 
1348
        test = TestCaseWithBrokenTearDown('test_foo')
 
1349
        result = unittest.TestResult()
 
1350
        test.run(result)
 
1351
        self.assertFalse(result.wasSuccessful())
 
1352
        self.assertEqual(1, result.testsRun)
 
1353
 
 
1354
    def test_debug_flags_sanitised(self):
 
1355
        """The bzrlib debug flags should be sanitised by setUp."""
 
1356
        if 'allow_debug' in tests.selftest_debug_flags:
 
1357
            raise tests.TestNotApplicable(
 
1358
                '-Eallow_debug option prevents debug flag sanitisation')
 
1359
        # we could set something and run a test that will check
 
1360
        # it gets santised, but this is probably sufficient for now:
 
1361
        # if someone runs the test with -Dsomething it will error.
 
1362
        flags = set()
 
1363
        if self._lock_check_thorough:
 
1364
            flags.add('strict_locks')
 
1365
        self.assertEqual(flags, bzrlib.debug.debug_flags)
 
1366
 
 
1367
    def change_selftest_debug_flags(self, new_flags):
 
1368
        self.overrideAttr(tests, 'selftest_debug_flags', set(new_flags))
 
1369
 
 
1370
    def test_allow_debug_flag(self):
 
1371
        """The -Eallow_debug flag prevents bzrlib.debug.debug_flags from being
 
1372
        sanitised (i.e. cleared) before running a test.
 
1373
        """
 
1374
        self.change_selftest_debug_flags(set(['allow_debug']))
 
1375
        bzrlib.debug.debug_flags = set(['a-flag'])
 
1376
        class TestThatRecordsFlags(tests.TestCase):
 
1377
            def test_foo(nested_self):
 
1378
                self.flags = set(bzrlib.debug.debug_flags)
 
1379
        test = TestThatRecordsFlags('test_foo')
 
1380
        test.run(self.make_test_result())
 
1381
        flags = set(['a-flag'])
 
1382
        if 'disable_lock_checks' not in tests.selftest_debug_flags:
 
1383
            flags.add('strict_locks')
 
1384
        self.assertEqual(flags, self.flags)
 
1385
 
 
1386
    def test_disable_lock_checks(self):
 
1387
        """The -Edisable_lock_checks flag disables thorough checks."""
 
1388
        class TestThatRecordsFlags(tests.TestCase):
 
1389
            def test_foo(nested_self):
 
1390
                self.flags = set(bzrlib.debug.debug_flags)
 
1391
                self.test_lock_check_thorough = nested_self._lock_check_thorough
 
1392
        self.change_selftest_debug_flags(set())
 
1393
        test = TestThatRecordsFlags('test_foo')
 
1394
        test.run(self.make_test_result())
 
1395
        # By default we do strict lock checking and thorough lock/unlock
 
1396
        # tracking.
 
1397
        self.assertTrue(self.test_lock_check_thorough)
 
1398
        self.assertEqual(set(['strict_locks']), self.flags)
 
1399
        # Now set the disable_lock_checks flag, and show that this changed.
 
1400
        self.change_selftest_debug_flags(set(['disable_lock_checks']))
 
1401
        test = TestThatRecordsFlags('test_foo')
 
1402
        test.run(self.make_test_result())
 
1403
        self.assertFalse(self.test_lock_check_thorough)
 
1404
        self.assertEqual(set(), self.flags)
 
1405
 
 
1406
    def test_this_fails_strict_lock_check(self):
 
1407
        class TestThatRecordsFlags(tests.TestCase):
 
1408
            def test_foo(nested_self):
 
1409
                self.flags1 = set(bzrlib.debug.debug_flags)
 
1410
                self.thisFailsStrictLockCheck()
 
1411
                self.flags2 = set(bzrlib.debug.debug_flags)
 
1412
        # Make sure lock checking is active
 
1413
        self.change_selftest_debug_flags(set())
 
1414
        test = TestThatRecordsFlags('test_foo')
 
1415
        test.run(self.make_test_result())
 
1416
        self.assertEqual(set(['strict_locks']), self.flags1)
 
1417
        self.assertEqual(set(), self.flags2)
 
1418
 
 
1419
    def test_debug_flags_restored(self):
 
1420
        """The bzrlib debug flags should be restored to their original state
 
1421
        after the test was run, even if allow_debug is set.
 
1422
        """
 
1423
        self.change_selftest_debug_flags(set(['allow_debug']))
 
1424
        # Now run a test that modifies debug.debug_flags.
 
1425
        bzrlib.debug.debug_flags = set(['original-state'])
 
1426
        class TestThatModifiesFlags(tests.TestCase):
 
1427
            def test_foo(self):
 
1428
                bzrlib.debug.debug_flags = set(['modified'])
 
1429
        test = TestThatModifiesFlags('test_foo')
 
1430
        test.run(self.make_test_result())
 
1431
        self.assertEqual(set(['original-state']), bzrlib.debug.debug_flags)
 
1432
 
 
1433
    def make_test_result(self):
 
1434
        """Get a test result that writes to the test log file."""
 
1435
        return tests.TextTestResult(self._log_file, descriptions=0, verbosity=1)
 
1436
 
 
1437
    def inner_test(self):
 
1438
        # the inner child test
 
1439
        note("inner_test")
 
1440
 
 
1441
    def outer_child(self):
 
1442
        # the outer child test
 
1443
        note("outer_start")
 
1444
        self.inner_test = TestTestCase("inner_child")
 
1445
        result = self.make_test_result()
 
1446
        self.inner_test.run(result)
 
1447
        note("outer finish")
 
1448
        self.addCleanup(osutils.delete_any, self._log_file_name)
 
1449
 
 
1450
    def test_trace_nesting(self):
 
1451
        # this tests that each test case nests its trace facility correctly.
 
1452
        # we do this by running a test case manually. That test case (A)
 
1453
        # should setup a new log, log content to it, setup a child case (B),
 
1454
        # which should log independently, then case (A) should log a trailer
 
1455
        # and return.
 
1456
        # we do two nested children so that we can verify the state of the
 
1457
        # logs after the outer child finishes is correct, which a bad clean
 
1458
        # up routine in tearDown might trigger a fault in our test with only
 
1459
        # one child, we should instead see the bad result inside our test with
 
1460
        # the two children.
 
1461
        # the outer child test
 
1462
        original_trace = bzrlib.trace._trace_file
 
1463
        outer_test = TestTestCase("outer_child")
 
1464
        result = self.make_test_result()
 
1465
        outer_test.run(result)
 
1466
        self.assertEqual(original_trace, bzrlib.trace._trace_file)
 
1467
 
 
1468
    def method_that_times_a_bit_twice(self):
 
1469
        # call self.time twice to ensure it aggregates
 
1470
        self.time(time.sleep, 0.007)
 
1471
        self.time(time.sleep, 0.007)
 
1472
 
 
1473
    def test_time_creates_benchmark_in_result(self):
 
1474
        """Test that the TestCase.time() method accumulates a benchmark time."""
 
1475
        sample_test = TestTestCase("method_that_times_a_bit_twice")
 
1476
        output_stream = StringIO()
 
1477
        result = bzrlib.tests.VerboseTestResult(
 
1478
            output_stream,
 
1479
            descriptions=0,
 
1480
            verbosity=2)
 
1481
        sample_test.run(result)
 
1482
        self.assertContainsRe(
 
1483
            output_stream.getvalue(),
 
1484
            r"\d+ms\*\n$")
 
1485
 
 
1486
    def test_hooks_sanitised(self):
 
1487
        """The bzrlib hooks should be sanitised by setUp."""
 
1488
        # Note this test won't fail with hooks that the core library doesn't
 
1489
        # use - but it trigger with a plugin that adds hooks, so its still a
 
1490
        # useful warning in that case.
 
1491
        self.assertEqual(bzrlib.branch.BranchHooks(),
 
1492
            bzrlib.branch.Branch.hooks)
 
1493
        self.assertEqual(bzrlib.smart.server.SmartServerHooks(),
 
1494
            bzrlib.smart.server.SmartTCPServer.hooks)
 
1495
        self.assertEqual(bzrlib.commands.CommandHooks(),
 
1496
            bzrlib.commands.Command.hooks)
 
1497
 
 
1498
    def test__gather_lsprof_in_benchmarks(self):
 
1499
        """When _gather_lsprof_in_benchmarks is on, accumulate profile data.
 
1500
 
 
1501
        Each self.time() call is individually and separately profiled.
 
1502
        """
 
1503
        self.requireFeature(test_lsprof.LSProfFeature)
 
1504
        # overrides the class member with an instance member so no cleanup
 
1505
        # needed.
 
1506
        self._gather_lsprof_in_benchmarks = True
 
1507
        self.time(time.sleep, 0.000)
 
1508
        self.time(time.sleep, 0.003)
 
1509
        self.assertEqual(2, len(self._benchcalls))
 
1510
        self.assertEqual((time.sleep, (0.000,), {}), self._benchcalls[0][0])
 
1511
        self.assertEqual((time.sleep, (0.003,), {}), self._benchcalls[1][0])
 
1512
        self.assertIsInstance(self._benchcalls[0][1], bzrlib.lsprof.Stats)
 
1513
        self.assertIsInstance(self._benchcalls[1][1], bzrlib.lsprof.Stats)
 
1514
        del self._benchcalls[:]
 
1515
 
 
1516
    def test_knownFailure(self):
 
1517
        """Self.knownFailure() should raise a KnownFailure exception."""
 
1518
        self.assertRaises(tests.KnownFailure, self.knownFailure, "A Failure")
 
1519
 
 
1520
    def test_open_bzrdir_safe_roots(self):
 
1521
        # even a memory transport should fail to open when its url isn't 
 
1522
        # permitted.
 
1523
        # Manually set one up (TestCase doesn't and shouldn't provide magic
 
1524
        # machinery)
 
1525
        transport_server = memory.MemoryServer()
 
1526
        transport_server.start_server()
 
1527
        self.addCleanup(transport_server.stop_server)
 
1528
        t = transport.get_transport(transport_server.get_url())
 
1529
        bzrdir.BzrDir.create(t.base)
 
1530
        self.assertRaises(errors.BzrError,
 
1531
            bzrdir.BzrDir.open_from_transport, t)
 
1532
        # But if we declare this as safe, we can open the bzrdir.
 
1533
        self.permit_url(t.base)
 
1534
        self._bzr_selftest_roots.append(t.base)
 
1535
        bzrdir.BzrDir.open_from_transport(t)
 
1536
 
 
1537
    def test_requireFeature_available(self):
 
1538
        """self.requireFeature(available) is a no-op."""
 
1539
        class Available(tests.Feature):
 
1540
            def _probe(self):return True
 
1541
        feature = Available()
 
1542
        self.requireFeature(feature)
 
1543
 
 
1544
    def test_requireFeature_unavailable(self):
 
1545
        """self.requireFeature(unavailable) raises UnavailableFeature."""
 
1546
        class Unavailable(tests.Feature):
 
1547
            def _probe(self):return False
 
1548
        feature = Unavailable()
 
1549
        self.assertRaises(tests.UnavailableFeature,
 
1550
                          self.requireFeature, feature)
 
1551
 
 
1552
    def test_run_no_parameters(self):
 
1553
        test = SampleTestCase('_test_pass')
 
1554
        test.run()
 
1555
 
 
1556
    def test_run_enabled_unittest_result(self):
 
1557
        """Test we revert to regular behaviour when the test is enabled."""
 
1558
        test = SampleTestCase('_test_pass')
 
1559
        class EnabledFeature(object):
 
1560
            def available(self):
 
1561
                return True
 
1562
        test._test_needs_features = [EnabledFeature()]
 
1563
        result = unittest.TestResult()
 
1564
        test.run(result)
 
1565
        self.assertEqual(1, result.testsRun)
 
1566
        self.assertEqual([], result.errors)
 
1567
        self.assertEqual([], result.failures)
 
1568
 
 
1569
    def test_run_disabled_unittest_result(self):
 
1570
        """Test our compatability for disabled tests with unittest results."""
 
1571
        test = SampleTestCase('_test_pass')
 
1572
        class DisabledFeature(object):
 
1573
            def available(self):
 
1574
                return False
 
1575
        test._test_needs_features = [DisabledFeature()]
 
1576
        result = unittest.TestResult()
 
1577
        test.run(result)
 
1578
        self.assertEqual(1, result.testsRun)
 
1579
        self.assertEqual([], result.errors)
 
1580
        self.assertEqual([], result.failures)
 
1581
 
 
1582
    def test_run_disabled_supporting_result(self):
 
1583
        """Test disabled tests behaviour with support aware results."""
 
1584
        test = SampleTestCase('_test_pass')
 
1585
        class DisabledFeature(object):
 
1586
            def __eq__(self, other):
 
1587
                return isinstance(other, DisabledFeature)
 
1588
            def available(self):
 
1589
                return False
 
1590
        the_feature = DisabledFeature()
 
1591
        test._test_needs_features = [the_feature]
 
1592
        class InstrumentedTestResult(unittest.TestResult):
 
1593
            def __init__(self):
 
1594
                unittest.TestResult.__init__(self)
 
1595
                self.calls = []
 
1596
            def startTest(self, test):
 
1597
                self.calls.append(('startTest', test))
 
1598
            def stopTest(self, test):
 
1599
                self.calls.append(('stopTest', test))
 
1600
            def addNotSupported(self, test, feature):
 
1601
                self.calls.append(('addNotSupported', test, feature))
 
1602
        result = InstrumentedTestResult()
 
1603
        test.run(result)
 
1604
        case = result.calls[0][1]
 
1605
        self.assertEqual([
 
1606
            ('startTest', case),
 
1607
            ('addNotSupported', case, the_feature),
 
1608
            ('stopTest', case),
 
1609
            ],
 
1610
            result.calls)
 
1611
 
 
1612
    def test_start_server_registers_url(self):
 
1613
        transport_server = memory.MemoryServer()
 
1614
        # A little strict, but unlikely to be changed soon.
 
1615
        self.assertEqual([], self._bzr_selftest_roots)
 
1616
        self.start_server(transport_server)
 
1617
        self.assertSubset([transport_server.get_url()],
 
1618
            self._bzr_selftest_roots)
 
1619
 
 
1620
    def test_assert_list_raises_on_generator(self):
 
1621
        def generator_which_will_raise():
 
1622
            # This will not raise until after the first yield
 
1623
            yield 1
 
1624
            raise _TestException()
 
1625
 
 
1626
        e = self.assertListRaises(_TestException, generator_which_will_raise)
 
1627
        self.assertIsInstance(e, _TestException)
 
1628
 
 
1629
        e = self.assertListRaises(Exception, generator_which_will_raise)
 
1630
        self.assertIsInstance(e, _TestException)
 
1631
 
 
1632
    def test_assert_list_raises_on_plain(self):
 
1633
        def plain_exception():
 
1634
            raise _TestException()
 
1635
            return []
 
1636
 
 
1637
        e = self.assertListRaises(_TestException, plain_exception)
 
1638
        self.assertIsInstance(e, _TestException)
 
1639
 
 
1640
        e = self.assertListRaises(Exception, plain_exception)
 
1641
        self.assertIsInstance(e, _TestException)
 
1642
 
 
1643
    def test_assert_list_raises_assert_wrong_exception(self):
 
1644
        class _NotTestException(Exception):
 
1645
            pass
 
1646
 
 
1647
        def wrong_exception():
 
1648
            raise _NotTestException()
 
1649
 
 
1650
        def wrong_exception_generator():
 
1651
            yield 1
 
1652
            yield 2
 
1653
            raise _NotTestException()
 
1654
 
 
1655
        # Wrong exceptions are not intercepted
 
1656
        self.assertRaises(_NotTestException,
 
1657
            self.assertListRaises, _TestException, wrong_exception)
 
1658
        self.assertRaises(_NotTestException,
 
1659
            self.assertListRaises, _TestException, wrong_exception_generator)
 
1660
 
 
1661
    def test_assert_list_raises_no_exception(self):
 
1662
        def success():
 
1663
            return []
 
1664
 
 
1665
        def success_generator():
 
1666
            yield 1
 
1667
            yield 2
 
1668
 
 
1669
        self.assertRaises(AssertionError,
 
1670
            self.assertListRaises, _TestException, success)
 
1671
 
 
1672
        self.assertRaises(AssertionError,
 
1673
            self.assertListRaises, _TestException, success_generator)
 
1674
 
 
1675
    def test_overrideAttr_without_value(self):
 
1676
        self.test_attr = 'original' # Define a test attribute
 
1677
        obj = self # Make 'obj' visible to the embedded test
 
1678
        class Test(tests.TestCase):
 
1679
 
 
1680
            def setUp(self):
 
1681
                tests.TestCase.setUp(self)
 
1682
                self.orig = self.overrideAttr(obj, 'test_attr')
 
1683
 
 
1684
            def test_value(self):
 
1685
                self.assertEqual('original', self.orig)
 
1686
                self.assertEqual('original', obj.test_attr)
 
1687
                obj.test_attr = 'modified'
 
1688
                self.assertEqual('modified', obj.test_attr)
 
1689
 
 
1690
        test = Test('test_value')
 
1691
        test.run(unittest.TestResult())
 
1692
        self.assertEqual('original', obj.test_attr)
 
1693
 
 
1694
    def test_overrideAttr_with_value(self):
 
1695
        self.test_attr = 'original' # Define a test attribute
 
1696
        obj = self # Make 'obj' visible to the embedded test
 
1697
        class Test(tests.TestCase):
 
1698
 
 
1699
            def setUp(self):
 
1700
                tests.TestCase.setUp(self)
 
1701
                self.orig = self.overrideAttr(obj, 'test_attr', new='modified')
 
1702
 
 
1703
            def test_value(self):
 
1704
                self.assertEqual('original', self.orig)
 
1705
                self.assertEqual('modified', obj.test_attr)
 
1706
 
 
1707
        test = Test('test_value')
 
1708
        test.run(unittest.TestResult())
 
1709
        self.assertEqual('original', obj.test_attr)
 
1710
 
 
1711
 
 
1712
class _MissingFeature(tests.Feature):
 
1713
    def _probe(self):
 
1714
        return False
 
1715
missing_feature = _MissingFeature()
 
1716
 
 
1717
 
 
1718
def _get_test(name):
 
1719
    """Get an instance of a specific example test.
 
1720
 
 
1721
    We protect this in a function so that they don't auto-run in the test
 
1722
    suite.
 
1723
    """
 
1724
 
 
1725
    class ExampleTests(tests.TestCase):
 
1726
 
 
1727
        def test_fail(self):
 
1728
            mutter('this was a failing test')
 
1729
            self.fail('this test will fail')
 
1730
 
 
1731
        def test_error(self):
 
1732
            mutter('this test errored')
 
1733
            raise RuntimeError('gotcha')
 
1734
 
 
1735
        def test_missing_feature(self):
 
1736
            mutter('missing the feature')
 
1737
            self.requireFeature(missing_feature)
 
1738
 
 
1739
        def test_skip(self):
 
1740
            mutter('this test will be skipped')
 
1741
            raise tests.TestSkipped('reason')
 
1742
 
 
1743
        def test_success(self):
 
1744
            mutter('this test succeeds')
 
1745
 
 
1746
        def test_xfail(self):
 
1747
            mutter('test with expected failure')
 
1748
            self.knownFailure('this_fails')
 
1749
 
 
1750
        def test_unexpected_success(self):
 
1751
            mutter('test with unexpected success')
 
1752
            self.expectFailure('should_fail', lambda: None)
 
1753
 
 
1754
    return ExampleTests(name)
 
1755
 
 
1756
 
 
1757
class TestTestCaseLogDetails(tests.TestCase):
 
1758
 
 
1759
    def _run_test(self, test_name):
 
1760
        test = _get_test(test_name)
 
1761
        result = testtools.TestResult()
 
1762
        test.run(result)
 
1763
        return result
 
1764
 
 
1765
    def test_fail_has_log(self):
 
1766
        result = self._run_test('test_fail')
 
1767
        self.assertEqual(1, len(result.failures))
 
1768
        result_content = result.failures[0][1]
 
1769
        self.assertContainsRe(result_content, 'Text attachment: log')
 
1770
        self.assertContainsRe(result_content, 'this was a failing test')
 
1771
 
 
1772
    def test_error_has_log(self):
 
1773
        result = self._run_test('test_error')
 
1774
        self.assertEqual(1, len(result.errors))
 
1775
        result_content = result.errors[0][1]
 
1776
        self.assertContainsRe(result_content, 'Text attachment: log')
 
1777
        self.assertContainsRe(result_content, 'this test errored')
 
1778
 
 
1779
    def test_skip_has_no_log(self):
 
1780
        result = self._run_test('test_skip')
 
1781
        self.assertEqual(['reason'], result.skip_reasons.keys())
 
1782
        skips = result.skip_reasons['reason']
 
1783
        self.assertEqual(1, len(skips))
 
1784
        test = skips[0]
 
1785
        self.assertFalse('log' in test.getDetails())
 
1786
 
 
1787
    def test_missing_feature_has_no_log(self):
 
1788
        # testtools doesn't know about addNotSupported, so it just gets
 
1789
        # considered as a skip
 
1790
        result = self._run_test('test_missing_feature')
 
1791
        self.assertEqual([missing_feature], result.skip_reasons.keys())
 
1792
        skips = result.skip_reasons[missing_feature]
 
1793
        self.assertEqual(1, len(skips))
 
1794
        test = skips[0]
 
1795
        self.assertFalse('log' in test.getDetails())
 
1796
 
 
1797
    def test_xfail_has_no_log(self):
 
1798
        result = self._run_test('test_xfail')
 
1799
        self.assertEqual(1, len(result.expectedFailures))
 
1800
        result_content = result.expectedFailures[0][1]
 
1801
        self.assertNotContainsRe(result_content, 'Text attachment: log')
 
1802
        self.assertNotContainsRe(result_content, 'test with expected failure')
 
1803
 
 
1804
    def test_unexpected_success_has_log(self):
 
1805
        result = self._run_test('test_unexpected_success')
 
1806
        self.assertEqual(1, len(result.unexpectedSuccesses))
 
1807
        # Inconsistency, unexpectedSuccesses is a list of tests,
 
1808
        # expectedFailures is a list of reasons?
 
1809
        test = result.unexpectedSuccesses[0]
 
1810
        details = test.getDetails()
 
1811
        self.assertTrue('log' in details)
 
1812
 
 
1813
 
 
1814
class TestTestCloning(tests.TestCase):
 
1815
    """Tests that test cloning of TestCases (as used by multiply_tests)."""
 
1816
 
 
1817
    def test_cloned_testcase_does_not_share_details(self):
 
1818
        """A TestCase cloned with clone_test does not share mutable attributes
 
1819
        such as details or cleanups.
 
1820
        """
 
1821
        class Test(tests.TestCase):
 
1822
            def test_foo(self):
 
1823
                self.addDetail('foo', Content('text/plain', lambda: 'foo'))
 
1824
        orig_test = Test('test_foo')
 
1825
        cloned_test = tests.clone_test(orig_test, orig_test.id() + '(cloned)')
 
1826
        orig_test.run(unittest.TestResult())
 
1827
        self.assertEqual('foo', orig_test.getDetails()['foo'].iter_bytes())
 
1828
        self.assertEqual(None, cloned_test.getDetails().get('foo'))
 
1829
 
 
1830
    def test_double_apply_scenario_preserves_first_scenario(self):
 
1831
        """Applying two levels of scenarios to a test preserves the attributes
 
1832
        added by both scenarios.
 
1833
        """
 
1834
        class Test(tests.TestCase):
 
1835
            def test_foo(self):
 
1836
                pass
 
1837
        test = Test('test_foo')
 
1838
        scenarios_x = [('x=1', {'x': 1}), ('x=2', {'x': 2})]
 
1839
        scenarios_y = [('y=1', {'y': 1}), ('y=2', {'y': 2})]
 
1840
        suite = tests.multiply_tests(test, scenarios_x, unittest.TestSuite())
 
1841
        suite = tests.multiply_tests(suite, scenarios_y, unittest.TestSuite())
 
1842
        all_tests = list(tests.iter_suite_tests(suite))
 
1843
        self.assertLength(4, all_tests)
 
1844
        all_xys = sorted((t.x, t.y) for t in all_tests)
 
1845
        self.assertEqual([(1, 1), (1, 2), (2, 1), (2, 2)], all_xys)
 
1846
 
 
1847
 
 
1848
# NB: Don't delete this; it's not actually from 0.11!
 
1849
@deprecated_function(deprecated_in((0, 11, 0)))
 
1850
def sample_deprecated_function():
 
1851
    """A deprecated function to test applyDeprecated with."""
 
1852
    return 2
 
1853
 
 
1854
 
 
1855
def sample_undeprecated_function(a_param):
 
1856
    """A undeprecated function to test applyDeprecated with."""
 
1857
 
 
1858
 
 
1859
class ApplyDeprecatedHelper(object):
 
1860
    """A helper class for ApplyDeprecated tests."""
 
1861
 
 
1862
    @deprecated_method(deprecated_in((0, 11, 0)))
 
1863
    def sample_deprecated_method(self, param_one):
 
1864
        """A deprecated method for testing with."""
 
1865
        return param_one
 
1866
 
 
1867
    def sample_normal_method(self):
 
1868
        """A undeprecated method."""
 
1869
 
 
1870
    @deprecated_method(deprecated_in((0, 10, 0)))
 
1871
    def sample_nested_deprecation(self):
 
1872
        return sample_deprecated_function()
 
1873
 
 
1874
 
 
1875
class TestExtraAssertions(tests.TestCase):
 
1876
    """Tests for new test assertions in bzrlib test suite"""
 
1877
 
 
1878
    def test_assert_isinstance(self):
 
1879
        self.assertIsInstance(2, int)
 
1880
        self.assertIsInstance(u'', basestring)
 
1881
        e = self.assertRaises(AssertionError, self.assertIsInstance, None, int)
 
1882
        self.assertEquals(str(e),
 
1883
            "None is an instance of <type 'NoneType'> rather than <type 'int'>")
 
1884
        self.assertRaises(AssertionError, self.assertIsInstance, 23.3, int)
 
1885
        e = self.assertRaises(AssertionError,
 
1886
            self.assertIsInstance, None, int, "it's just not")
 
1887
        self.assertEquals(str(e),
 
1888
            "None is an instance of <type 'NoneType'> rather than <type 'int'>"
 
1889
            ": it's just not")
 
1890
 
 
1891
    def test_assertEndsWith(self):
 
1892
        self.assertEndsWith('foo', 'oo')
 
1893
        self.assertRaises(AssertionError, self.assertEndsWith, 'o', 'oo')
 
1894
 
 
1895
    def test_assertEqualDiff(self):
 
1896
        e = self.assertRaises(AssertionError,
 
1897
                              self.assertEqualDiff, '', '\n')
 
1898
        self.assertEquals(str(e),
 
1899
                          # Don't blink ! The '+' applies to the second string
 
1900
                          'first string is missing a final newline.\n+ \n')
 
1901
        e = self.assertRaises(AssertionError,
 
1902
                              self.assertEqualDiff, '\n', '')
 
1903
        self.assertEquals(str(e),
 
1904
                          # Don't blink ! The '-' applies to the second string
 
1905
                          'second string is missing a final newline.\n- \n')
 
1906
 
 
1907
 
 
1908
class TestDeprecations(tests.TestCase):
 
1909
 
 
1910
    def test_applyDeprecated_not_deprecated(self):
 
1911
        sample_object = ApplyDeprecatedHelper()
 
1912
        # calling an undeprecated callable raises an assertion
 
1913
        self.assertRaises(AssertionError, self.applyDeprecated,
 
1914
            deprecated_in((0, 11, 0)),
 
1915
            sample_object.sample_normal_method)
 
1916
        self.assertRaises(AssertionError, self.applyDeprecated,
 
1917
            deprecated_in((0, 11, 0)),
 
1918
            sample_undeprecated_function, "a param value")
 
1919
        # calling a deprecated callable (function or method) with the wrong
 
1920
        # expected deprecation fails.
 
1921
        self.assertRaises(AssertionError, self.applyDeprecated,
 
1922
            deprecated_in((0, 10, 0)),
 
1923
            sample_object.sample_deprecated_method, "a param value")
 
1924
        self.assertRaises(AssertionError, self.applyDeprecated,
 
1925
            deprecated_in((0, 10, 0)),
 
1926
            sample_deprecated_function)
 
1927
        # calling a deprecated callable (function or method) with the right
 
1928
        # expected deprecation returns the functions result.
 
1929
        self.assertEqual("a param value",
 
1930
            self.applyDeprecated(deprecated_in((0, 11, 0)),
 
1931
            sample_object.sample_deprecated_method, "a param value"))
 
1932
        self.assertEqual(2, self.applyDeprecated(deprecated_in((0, 11, 0)),
 
1933
            sample_deprecated_function))
 
1934
        # calling a nested deprecation with the wrong deprecation version
 
1935
        # fails even if a deeper nested function was deprecated with the
 
1936
        # supplied version.
 
1937
        self.assertRaises(AssertionError, self.applyDeprecated,
 
1938
            deprecated_in((0, 11, 0)), sample_object.sample_nested_deprecation)
 
1939
        # calling a nested deprecation with the right deprecation value
 
1940
        # returns the calls result.
 
1941
        self.assertEqual(2, self.applyDeprecated(deprecated_in((0, 10, 0)),
 
1942
            sample_object.sample_nested_deprecation))
 
1943
 
 
1944
    def test_callDeprecated(self):
 
1945
        def testfunc(be_deprecated, result=None):
 
1946
            if be_deprecated is True:
 
1947
                symbol_versioning.warn('i am deprecated', DeprecationWarning,
 
1948
                                       stacklevel=1)
 
1949
            return result
 
1950
        result = self.callDeprecated(['i am deprecated'], testfunc, True)
 
1951
        self.assertIs(None, result)
 
1952
        result = self.callDeprecated([], testfunc, False, 'result')
 
1953
        self.assertEqual('result', result)
 
1954
        self.callDeprecated(['i am deprecated'], testfunc, be_deprecated=True)
 
1955
        self.callDeprecated([], testfunc, be_deprecated=False)
 
1956
 
 
1957
 
 
1958
class TestWarningTests(tests.TestCase):
 
1959
    """Tests for calling methods that raise warnings."""
 
1960
 
 
1961
    def test_callCatchWarnings(self):
 
1962
        def meth(a, b):
 
1963
            warnings.warn("this is your last warning")
 
1964
            return a + b
 
1965
        wlist, result = self.callCatchWarnings(meth, 1, 2)
 
1966
        self.assertEquals(3, result)
 
1967
        # would like just to compare them, but UserWarning doesn't implement
 
1968
        # eq well
 
1969
        w0, = wlist
 
1970
        self.assertIsInstance(w0, UserWarning)
 
1971
        self.assertEquals("this is your last warning", str(w0))
 
1972
 
 
1973
 
 
1974
class TestConvenienceMakers(tests.TestCaseWithTransport):
 
1975
    """Test for the make_* convenience functions."""
 
1976
 
 
1977
    def test_make_branch_and_tree_with_format(self):
 
1978
        # we should be able to supply a format to make_branch_and_tree
 
1979
        self.make_branch_and_tree('a', format=bzrlib.bzrdir.BzrDirMetaFormat1())
 
1980
        self.make_branch_and_tree('b', format=bzrlib.bzrdir.BzrDirFormat6())
 
1981
        self.assertIsInstance(bzrlib.bzrdir.BzrDir.open('a')._format,
 
1982
                              bzrlib.bzrdir.BzrDirMetaFormat1)
 
1983
        self.assertIsInstance(bzrlib.bzrdir.BzrDir.open('b')._format,
 
1984
                              bzrlib.bzrdir.BzrDirFormat6)
 
1985
 
 
1986
    def test_make_branch_and_memory_tree(self):
 
1987
        # we should be able to get a new branch and a mutable tree from
 
1988
        # TestCaseWithTransport
 
1989
        tree = self.make_branch_and_memory_tree('a')
 
1990
        self.assertIsInstance(tree, bzrlib.memorytree.MemoryTree)
 
1991
 
 
1992
    def test_make_tree_for_local_vfs_backed_transport(self):
 
1993
        # make_branch_and_tree has to use local branch and repositories
 
1994
        # when the vfs transport and local disk are colocated, even if
 
1995
        # a different transport is in use for url generation.
 
1996
        self.transport_server = test_server.FakeVFATServer
 
1997
        self.assertFalse(self.get_url('t1').startswith('file://'))
 
1998
        tree = self.make_branch_and_tree('t1')
 
1999
        base = tree.bzrdir.root_transport.base
 
2000
        self.assertStartsWith(base, 'file://')
 
2001
        self.assertEquals(tree.bzrdir.root_transport,
 
2002
                tree.branch.bzrdir.root_transport)
 
2003
        self.assertEquals(tree.bzrdir.root_transport,
 
2004
                tree.branch.repository.bzrdir.root_transport)
 
2005
 
 
2006
 
 
2007
class SelfTestHelper(object):
 
2008
 
 
2009
    def run_selftest(self, **kwargs):
 
2010
        """Run selftest returning its output."""
 
2011
        output = StringIO()
 
2012
        old_transport = bzrlib.tests.default_transport
 
2013
        old_root = tests.TestCaseWithMemoryTransport.TEST_ROOT
 
2014
        tests.TestCaseWithMemoryTransport.TEST_ROOT = None
 
2015
        try:
 
2016
            self.assertEqual(True, tests.selftest(stream=output, **kwargs))
 
2017
        finally:
 
2018
            bzrlib.tests.default_transport = old_transport
 
2019
            tests.TestCaseWithMemoryTransport.TEST_ROOT = old_root
 
2020
        output.seek(0)
 
2021
        return output
 
2022
 
 
2023
 
 
2024
class TestSelftest(tests.TestCase, SelfTestHelper):
 
2025
    """Tests of bzrlib.tests.selftest."""
 
2026
 
 
2027
    def test_selftest_benchmark_parameter_invokes_test_suite__benchmark__(self):
 
2028
        factory_called = []
 
2029
        def factory():
 
2030
            factory_called.append(True)
 
2031
            return TestUtil.TestSuite()
 
2032
        out = StringIO()
 
2033
        err = StringIO()
 
2034
        self.apply_redirected(out, err, None, bzrlib.tests.selftest,
 
2035
            test_suite_factory=factory)
 
2036
        self.assertEqual([True], factory_called)
 
2037
 
 
2038
    def factory(self):
 
2039
        """A test suite factory."""
 
2040
        class Test(tests.TestCase):
 
2041
            def a(self):
 
2042
                pass
 
2043
            def b(self):
 
2044
                pass
 
2045
            def c(self):
 
2046
                pass
 
2047
        return TestUtil.TestSuite([Test("a"), Test("b"), Test("c")])
 
2048
 
 
2049
    def test_list_only(self):
 
2050
        output = self.run_selftest(test_suite_factory=self.factory,
 
2051
            list_only=True)
 
2052
        self.assertEqual(3, len(output.readlines()))
 
2053
 
 
2054
    def test_list_only_filtered(self):
 
2055
        output = self.run_selftest(test_suite_factory=self.factory,
 
2056
            list_only=True, pattern="Test.b")
 
2057
        self.assertEndsWith(output.getvalue(), "Test.b\n")
 
2058
        self.assertLength(1, output.readlines())
 
2059
 
 
2060
    def test_list_only_excludes(self):
 
2061
        output = self.run_selftest(test_suite_factory=self.factory,
 
2062
            list_only=True, exclude_pattern="Test.b")
 
2063
        self.assertNotContainsRe("Test.b", output.getvalue())
 
2064
        self.assertLength(2, output.readlines())
 
2065
 
 
2066
    def test_lsprof_tests(self):
 
2067
        self.requireFeature(test_lsprof.LSProfFeature)
 
2068
        calls = []
 
2069
        class Test(object):
 
2070
            def __call__(test, result):
 
2071
                test.run(result)
 
2072
            def run(test, result):
 
2073
                self.assertIsInstance(result, ExtendedToOriginalDecorator)
 
2074
                calls.append("called")
 
2075
            def countTestCases(self):
 
2076
                return 1
 
2077
        self.run_selftest(test_suite_factory=Test, lsprof_tests=True)
 
2078
        self.assertLength(1, calls)
 
2079
 
 
2080
    def test_random(self):
 
2081
        # test randomising by listing a number of tests.
 
2082
        output_123 = self.run_selftest(test_suite_factory=self.factory,
 
2083
            list_only=True, random_seed="123")
 
2084
        output_234 = self.run_selftest(test_suite_factory=self.factory,
 
2085
            list_only=True, random_seed="234")
 
2086
        self.assertNotEqual(output_123, output_234)
 
2087
        # "Randominzing test order..\n\n
 
2088
        self.assertLength(5, output_123.readlines())
 
2089
        self.assertLength(5, output_234.readlines())
 
2090
 
 
2091
    def test_random_reuse_is_same_order(self):
 
2092
        # test randomising by listing a number of tests.
 
2093
        expected = self.run_selftest(test_suite_factory=self.factory,
 
2094
            list_only=True, random_seed="123")
 
2095
        repeated = self.run_selftest(test_suite_factory=self.factory,
 
2096
            list_only=True, random_seed="123")
 
2097
        self.assertEqual(expected.getvalue(), repeated.getvalue())
 
2098
 
 
2099
    def test_runner_class(self):
 
2100
        self.requireFeature(features.subunit)
 
2101
        from subunit import ProtocolTestCase
 
2102
        stream = self.run_selftest(runner_class=tests.SubUnitBzrRunner,
 
2103
            test_suite_factory=self.factory)
 
2104
        test = ProtocolTestCase(stream)
 
2105
        result = unittest.TestResult()
 
2106
        test.run(result)
 
2107
        self.assertEqual(3, result.testsRun)
 
2108
 
 
2109
    def test_starting_with_single_argument(self):
 
2110
        output = self.run_selftest(test_suite_factory=self.factory,
 
2111
            starting_with=['bzrlib.tests.test_selftest.Test.a'],
 
2112
            list_only=True)
 
2113
        self.assertEqual('bzrlib.tests.test_selftest.Test.a\n',
 
2114
            output.getvalue())
 
2115
 
 
2116
    def test_starting_with_multiple_argument(self):
 
2117
        output = self.run_selftest(test_suite_factory=self.factory,
 
2118
            starting_with=['bzrlib.tests.test_selftest.Test.a',
 
2119
                'bzrlib.tests.test_selftest.Test.b'],
 
2120
            list_only=True)
 
2121
        self.assertEqual('bzrlib.tests.test_selftest.Test.a\n'
 
2122
            'bzrlib.tests.test_selftest.Test.b\n',
 
2123
            output.getvalue())
 
2124
 
 
2125
    def check_transport_set(self, transport_server):
 
2126
        captured_transport = []
 
2127
        def seen_transport(a_transport):
 
2128
            captured_transport.append(a_transport)
 
2129
        class Capture(tests.TestCase):
 
2130
            def a(self):
 
2131
                seen_transport(bzrlib.tests.default_transport)
 
2132
        def factory():
 
2133
            return TestUtil.TestSuite([Capture("a")])
 
2134
        self.run_selftest(transport=transport_server, test_suite_factory=factory)
 
2135
        self.assertEqual(transport_server, captured_transport[0])
 
2136
 
 
2137
    def test_transport_sftp(self):
 
2138
        self.requireFeature(features.paramiko)
 
2139
        from bzrlib.tests import stub_sftp
 
2140
        self.check_transport_set(stub_sftp.SFTPAbsoluteServer)
 
2141
 
 
2142
    def test_transport_memory(self):
 
2143
        self.check_transport_set(memory.MemoryServer)
 
2144
 
 
2145
 
 
2146
class TestSelftestWithIdList(tests.TestCaseInTempDir, SelfTestHelper):
 
2147
    # Does IO: reads test.list
 
2148
 
 
2149
    def test_load_list(self):
 
2150
        # Provide a list with one test - this test.
 
2151
        test_id_line = '%s\n' % self.id()
 
2152
        self.build_tree_contents([('test.list', test_id_line)])
 
2153
        # And generate a list of the tests in  the suite.
 
2154
        stream = self.run_selftest(load_list='test.list', list_only=True)
 
2155
        self.assertEqual(test_id_line, stream.getvalue())
 
2156
 
 
2157
    def test_load_unknown(self):
 
2158
        # Provide a list with one test - this test.
 
2159
        # And generate a list of the tests in  the suite.
 
2160
        err = self.assertRaises(errors.NoSuchFile, self.run_selftest,
 
2161
            load_list='missing file name', list_only=True)
 
2162
 
 
2163
 
 
2164
class TestSubunitLogDetails(tests.TestCase, SelfTestHelper):
 
2165
 
 
2166
    _test_needs_features = [features.subunit]
 
2167
 
 
2168
    def run_subunit_stream(self, test_name):
 
2169
        from subunit import ProtocolTestCase
 
2170
        def factory():
 
2171
            return TestUtil.TestSuite([_get_test(test_name)])
 
2172
        stream = self.run_selftest(runner_class=tests.SubUnitBzrRunner,
 
2173
            test_suite_factory=factory)
 
2174
        test = ProtocolTestCase(stream)
 
2175
        result = testtools.TestResult()
 
2176
        test.run(result)
 
2177
        content = stream.getvalue()
 
2178
        return content, result
 
2179
 
 
2180
    def test_fail_has_log(self):
 
2181
        content, result = self.run_subunit_stream('test_fail')
 
2182
        self.assertEqual(1, len(result.failures))
 
2183
        self.assertContainsRe(content, '(?m)^log$')
 
2184
        self.assertContainsRe(content, 'this test will fail')
 
2185
 
 
2186
    def test_error_has_log(self):
 
2187
        content, result = self.run_subunit_stream('test_error')
 
2188
        self.assertContainsRe(content, '(?m)^log$')
 
2189
        self.assertContainsRe(content, 'this test errored')
 
2190
 
 
2191
    def test_skip_has_no_log(self):
 
2192
        content, result = self.run_subunit_stream('test_skip')
 
2193
        self.assertNotContainsRe(content, '(?m)^log$')
 
2194
        self.assertNotContainsRe(content, 'this test will be skipped')
 
2195
        self.assertEqual(['reason'], result.skip_reasons.keys())
 
2196
        skips = result.skip_reasons['reason']
 
2197
        self.assertEqual(1, len(skips))
 
2198
        test = skips[0]
 
2199
        # RemotedTestCase doesn't preserve the "details"
 
2200
        ## self.assertFalse('log' in test.getDetails())
 
2201
 
 
2202
    def test_missing_feature_has_no_log(self):
 
2203
        content, result = self.run_subunit_stream('test_missing_feature')
 
2204
        self.assertNotContainsRe(content, '(?m)^log$')
 
2205
        self.assertNotContainsRe(content, 'missing the feature')
 
2206
        self.assertEqual(['_MissingFeature\n'], result.skip_reasons.keys())
 
2207
        skips = result.skip_reasons['_MissingFeature\n']
 
2208
        self.assertEqual(1, len(skips))
 
2209
        test = skips[0]
 
2210
        # RemotedTestCase doesn't preserve the "details"
 
2211
        ## self.assertFalse('log' in test.getDetails())
 
2212
 
 
2213
    def test_xfail_has_no_log(self):
 
2214
        content, result = self.run_subunit_stream('test_xfail')
 
2215
        self.assertNotContainsRe(content, '(?m)^log$')
 
2216
        self.assertNotContainsRe(content, 'test with expected failure')
 
2217
        self.assertEqual(1, len(result.expectedFailures))
 
2218
        result_content = result.expectedFailures[0][1]
 
2219
        self.assertNotContainsRe(result_content, 'Text attachment: log')
 
2220
        self.assertNotContainsRe(result_content, 'test with expected failure')
 
2221
 
 
2222
    def test_unexpected_success_has_log(self):
 
2223
        content, result = self.run_subunit_stream('test_unexpected_success')
 
2224
        self.assertContainsRe(content, '(?m)^log$')
 
2225
        self.assertContainsRe(content, 'test with unexpected success')
 
2226
        self.expectFailure('subunit treats "unexpectedSuccess"'
 
2227
                           ' as a plain success',
 
2228
            self.assertEqual, 1, len(result.unexpectedSuccesses))
 
2229
        self.assertEqual(1, len(result.unexpectedSuccesses))
 
2230
        test = result.unexpectedSuccesses[0]
 
2231
        # RemotedTestCase doesn't preserve the "details"
 
2232
        ## self.assertTrue('log' in test.getDetails())
 
2233
 
 
2234
    def test_success_has_no_log(self):
 
2235
        content, result = self.run_subunit_stream('test_success')
 
2236
        self.assertEqual(1, result.testsRun)
 
2237
        self.assertNotContainsRe(content, '(?m)^log$')
 
2238
        self.assertNotContainsRe(content, 'this test succeeds')
 
2239
 
 
2240
 
 
2241
class TestRunBzr(tests.TestCase):
 
2242
 
 
2243
    out = ''
 
2244
    err = ''
 
2245
 
 
2246
    def _run_bzr_core(self, argv, retcode=0, encoding=None, stdin=None,
 
2247
                         working_dir=None):
 
2248
        """Override _run_bzr_core to test how it is invoked by run_bzr.
 
2249
 
 
2250
        Attempts to run bzr from inside this class don't actually run it.
 
2251
 
 
2252
        We test how run_bzr actually invokes bzr in another location.  Here we
 
2253
        only need to test that it passes the right parameters to run_bzr.
 
2254
        """
 
2255
        self.argv = list(argv)
 
2256
        self.retcode = retcode
 
2257
        self.encoding = encoding
 
2258
        self.stdin = stdin
 
2259
        self.working_dir = working_dir
 
2260
        return self.retcode, self.out, self.err
 
2261
 
 
2262
    def test_run_bzr_error(self):
 
2263
        self.out = "It sure does!\n"
 
2264
        out, err = self.run_bzr_error(['^$'], ['rocks'], retcode=34)
 
2265
        self.assertEqual(['rocks'], self.argv)
 
2266
        self.assertEqual(34, self.retcode)
 
2267
        self.assertEqual('It sure does!\n', out)
 
2268
        self.assertEquals(out, self.out)
 
2269
        self.assertEqual('', err)
 
2270
        self.assertEquals(err, self.err)
 
2271
 
 
2272
    def test_run_bzr_error_regexes(self):
 
2273
        self.out = ''
 
2274
        self.err = "bzr: ERROR: foobarbaz is not versioned"
 
2275
        out, err = self.run_bzr_error(
 
2276
            ["bzr: ERROR: foobarbaz is not versioned"],
 
2277
            ['file-id', 'foobarbaz'])
 
2278
 
 
2279
    def test_encoding(self):
 
2280
        """Test that run_bzr passes encoding to _run_bzr_core"""
 
2281
        self.run_bzr('foo bar')
 
2282
        self.assertEqual(None, self.encoding)
 
2283
        self.assertEqual(['foo', 'bar'], self.argv)
 
2284
 
 
2285
        self.run_bzr('foo bar', encoding='baz')
 
2286
        self.assertEqual('baz', self.encoding)
 
2287
        self.assertEqual(['foo', 'bar'], self.argv)
 
2288
 
 
2289
    def test_retcode(self):
 
2290
        """Test that run_bzr passes retcode to _run_bzr_core"""
 
2291
        # Default is retcode == 0
 
2292
        self.run_bzr('foo bar')
 
2293
        self.assertEqual(0, self.retcode)
 
2294
        self.assertEqual(['foo', 'bar'], self.argv)
 
2295
 
 
2296
        self.run_bzr('foo bar', retcode=1)
 
2297
        self.assertEqual(1, self.retcode)
 
2298
        self.assertEqual(['foo', 'bar'], self.argv)
 
2299
 
 
2300
        self.run_bzr('foo bar', retcode=None)
 
2301
        self.assertEqual(None, self.retcode)
 
2302
        self.assertEqual(['foo', 'bar'], self.argv)
 
2303
 
 
2304
        self.run_bzr(['foo', 'bar'], retcode=3)
 
2305
        self.assertEqual(3, self.retcode)
 
2306
        self.assertEqual(['foo', 'bar'], self.argv)
 
2307
 
 
2308
    def test_stdin(self):
 
2309
        # test that the stdin keyword to run_bzr is passed through to
 
2310
        # _run_bzr_core as-is. We do this by overriding
 
2311
        # _run_bzr_core in this class, and then calling run_bzr,
 
2312
        # which is a convenience function for _run_bzr_core, so
 
2313
        # should invoke it.
 
2314
        self.run_bzr('foo bar', stdin='gam')
 
2315
        self.assertEqual('gam', self.stdin)
 
2316
        self.assertEqual(['foo', 'bar'], self.argv)
 
2317
 
 
2318
        self.run_bzr('foo bar', stdin='zippy')
 
2319
        self.assertEqual('zippy', self.stdin)
 
2320
        self.assertEqual(['foo', 'bar'], self.argv)
 
2321
 
 
2322
    def test_working_dir(self):
 
2323
        """Test that run_bzr passes working_dir to _run_bzr_core"""
 
2324
        self.run_bzr('foo bar')
 
2325
        self.assertEqual(None, self.working_dir)
 
2326
        self.assertEqual(['foo', 'bar'], self.argv)
 
2327
 
 
2328
        self.run_bzr('foo bar', working_dir='baz')
 
2329
        self.assertEqual('baz', self.working_dir)
 
2330
        self.assertEqual(['foo', 'bar'], self.argv)
 
2331
 
 
2332
    def test_reject_extra_keyword_arguments(self):
 
2333
        self.assertRaises(TypeError, self.run_bzr, "foo bar",
 
2334
                          error_regex=['error message'])
 
2335
 
 
2336
 
 
2337
class TestRunBzrCaptured(tests.TestCaseWithTransport):
 
2338
    # Does IO when testing the working_dir parameter.
 
2339
 
 
2340
    def apply_redirected(self, stdin=None, stdout=None, stderr=None,
 
2341
                         a_callable=None, *args, **kwargs):
 
2342
        self.stdin = stdin
 
2343
        self.factory_stdin = getattr(bzrlib.ui.ui_factory, "stdin", None)
 
2344
        self.factory = bzrlib.ui.ui_factory
 
2345
        self.working_dir = osutils.getcwd()
 
2346
        stdout.write('foo\n')
 
2347
        stderr.write('bar\n')
 
2348
        return 0
 
2349
 
 
2350
    def test_stdin(self):
 
2351
        # test that the stdin keyword to _run_bzr_core is passed through to
 
2352
        # apply_redirected as a StringIO. We do this by overriding
 
2353
        # apply_redirected in this class, and then calling _run_bzr_core,
 
2354
        # which calls apply_redirected.
 
2355
        self.run_bzr(['foo', 'bar'], stdin='gam')
 
2356
        self.assertEqual('gam', self.stdin.read())
 
2357
        self.assertTrue(self.stdin is self.factory_stdin)
 
2358
        self.run_bzr(['foo', 'bar'], stdin='zippy')
 
2359
        self.assertEqual('zippy', self.stdin.read())
 
2360
        self.assertTrue(self.stdin is self.factory_stdin)
 
2361
 
 
2362
    def test_ui_factory(self):
 
2363
        # each invocation of self.run_bzr should get its
 
2364
        # own UI factory, which is an instance of TestUIFactory,
 
2365
        # with stdin, stdout and stderr attached to the stdin,
 
2366
        # stdout and stderr of the invoked run_bzr
 
2367
        current_factory = bzrlib.ui.ui_factory
 
2368
        self.run_bzr(['foo'])
 
2369
        self.failIf(current_factory is self.factory)
 
2370
        self.assertNotEqual(sys.stdout, self.factory.stdout)
 
2371
        self.assertNotEqual(sys.stderr, self.factory.stderr)
 
2372
        self.assertEqual('foo\n', self.factory.stdout.getvalue())
 
2373
        self.assertEqual('bar\n', self.factory.stderr.getvalue())
 
2374
        self.assertIsInstance(self.factory, tests.TestUIFactory)
 
2375
 
 
2376
    def test_working_dir(self):
 
2377
        self.build_tree(['one/', 'two/'])
 
2378
        cwd = osutils.getcwd()
 
2379
 
 
2380
        # Default is to work in the current directory
 
2381
        self.run_bzr(['foo', 'bar'])
 
2382
        self.assertEqual(cwd, self.working_dir)
 
2383
 
 
2384
        self.run_bzr(['foo', 'bar'], working_dir=None)
 
2385
        self.assertEqual(cwd, self.working_dir)
 
2386
 
 
2387
        # The function should be run in the alternative directory
 
2388
        # but afterwards the current working dir shouldn't be changed
 
2389
        self.run_bzr(['foo', 'bar'], working_dir='one')
 
2390
        self.assertNotEqual(cwd, self.working_dir)
 
2391
        self.assertEndsWith(self.working_dir, 'one')
 
2392
        self.assertEqual(cwd, osutils.getcwd())
 
2393
 
 
2394
        self.run_bzr(['foo', 'bar'], working_dir='two')
 
2395
        self.assertNotEqual(cwd, self.working_dir)
 
2396
        self.assertEndsWith(self.working_dir, 'two')
 
2397
        self.assertEqual(cwd, osutils.getcwd())
 
2398
 
 
2399
 
 
2400
class StubProcess(object):
 
2401
    """A stub process for testing run_bzr_subprocess."""
 
2402
    
 
2403
    def __init__(self, out="", err="", retcode=0):
 
2404
        self.out = out
 
2405
        self.err = err
 
2406
        self.returncode = retcode
 
2407
 
 
2408
    def communicate(self):
 
2409
        return self.out, self.err
 
2410
 
 
2411
 
 
2412
class TestWithFakedStartBzrSubprocess(tests.TestCaseWithTransport):
 
2413
    """Base class for tests testing how we might run bzr."""
 
2414
 
 
2415
    def setUp(self):
 
2416
        tests.TestCaseWithTransport.setUp(self)
 
2417
        self.subprocess_calls = []
 
2418
 
 
2419
    def start_bzr_subprocess(self, process_args, env_changes=None,
 
2420
                             skip_if_plan_to_signal=False,
 
2421
                             working_dir=None,
 
2422
                             allow_plugins=False):
 
2423
        """capture what run_bzr_subprocess tries to do."""
 
2424
        self.subprocess_calls.append({'process_args':process_args,
 
2425
            'env_changes':env_changes,
 
2426
            'skip_if_plan_to_signal':skip_if_plan_to_signal,
 
2427
            'working_dir':working_dir, 'allow_plugins':allow_plugins})
 
2428
        return self.next_subprocess
 
2429
 
 
2430
 
 
2431
class TestRunBzrSubprocess(TestWithFakedStartBzrSubprocess):
 
2432
 
 
2433
    def assertRunBzrSubprocess(self, expected_args, process, *args, **kwargs):
 
2434
        """Run run_bzr_subprocess with args and kwargs using a stubbed process.
 
2435
 
 
2436
        Inside TestRunBzrSubprocessCommands we use a stub start_bzr_subprocess
 
2437
        that will return static results. This assertion method populates those
 
2438
        results and also checks the arguments run_bzr_subprocess generates.
 
2439
        """
 
2440
        self.next_subprocess = process
 
2441
        try:
 
2442
            result = self.run_bzr_subprocess(*args, **kwargs)
 
2443
        except:
 
2444
            self.next_subprocess = None
 
2445
            for key, expected in expected_args.iteritems():
 
2446
                self.assertEqual(expected, self.subprocess_calls[-1][key])
 
2447
            raise
 
2448
        else:
 
2449
            self.next_subprocess = None
 
2450
            for key, expected in expected_args.iteritems():
 
2451
                self.assertEqual(expected, self.subprocess_calls[-1][key])
 
2452
            return result
 
2453
 
 
2454
    def test_run_bzr_subprocess(self):
 
2455
        """The run_bzr_helper_external command behaves nicely."""
 
2456
        self.assertRunBzrSubprocess({'process_args':['--version']},
 
2457
            StubProcess(), '--version')
 
2458
        self.assertRunBzrSubprocess({'process_args':['--version']},
 
2459
            StubProcess(), ['--version'])
 
2460
        # retcode=None disables retcode checking
 
2461
        result = self.assertRunBzrSubprocess({},
 
2462
            StubProcess(retcode=3), '--version', retcode=None)
 
2463
        result = self.assertRunBzrSubprocess({},
 
2464
            StubProcess(out="is free software"), '--version')
 
2465
        self.assertContainsRe(result[0], 'is free software')
 
2466
        # Running a subcommand that is missing errors
 
2467
        self.assertRaises(AssertionError, self.assertRunBzrSubprocess,
 
2468
            {'process_args':['--versionn']}, StubProcess(retcode=3),
 
2469
            '--versionn')
 
2470
        # Unless it is told to expect the error from the subprocess
 
2471
        result = self.assertRunBzrSubprocess({},
 
2472
            StubProcess(retcode=3), '--versionn', retcode=3)
 
2473
        # Or to ignore retcode checking
 
2474
        result = self.assertRunBzrSubprocess({},
 
2475
            StubProcess(err="unknown command", retcode=3), '--versionn',
 
2476
            retcode=None)
 
2477
        self.assertContainsRe(result[1], 'unknown command')
 
2478
 
 
2479
    def test_env_change_passes_through(self):
 
2480
        self.assertRunBzrSubprocess(
 
2481
            {'env_changes':{'new':'value', 'changed':'newvalue', 'deleted':None}},
 
2482
            StubProcess(), '',
 
2483
            env_changes={'new':'value', 'changed':'newvalue', 'deleted':None})
 
2484
 
 
2485
    def test_no_working_dir_passed_as_None(self):
 
2486
        self.assertRunBzrSubprocess({'working_dir': None}, StubProcess(), '')
 
2487
 
 
2488
    def test_no_working_dir_passed_through(self):
 
2489
        self.assertRunBzrSubprocess({'working_dir': 'dir'}, StubProcess(), '',
 
2490
            working_dir='dir')
 
2491
 
 
2492
    def test_run_bzr_subprocess_no_plugins(self):
 
2493
        self.assertRunBzrSubprocess({'allow_plugins': False},
 
2494
            StubProcess(), '')
 
2495
 
 
2496
    def test_allow_plugins(self):
 
2497
        self.assertRunBzrSubprocess({'allow_plugins': True},
 
2498
            StubProcess(), '', allow_plugins=True)
 
2499
 
 
2500
 
 
2501
class TestFinishBzrSubprocess(TestWithFakedStartBzrSubprocess):
 
2502
 
 
2503
    def test_finish_bzr_subprocess_with_error(self):
 
2504
        """finish_bzr_subprocess allows specification of the desired exit code.
 
2505
        """
 
2506
        process = StubProcess(err="unknown command", retcode=3)
 
2507
        result = self.finish_bzr_subprocess(process, retcode=3)
 
2508
        self.assertEqual('', result[0])
 
2509
        self.assertContainsRe(result[1], 'unknown command')
 
2510
 
 
2511
    def test_finish_bzr_subprocess_ignoring_retcode(self):
 
2512
        """finish_bzr_subprocess allows the exit code to be ignored."""
 
2513
        process = StubProcess(err="unknown command", retcode=3)
 
2514
        result = self.finish_bzr_subprocess(process, retcode=None)
 
2515
        self.assertEqual('', result[0])
 
2516
        self.assertContainsRe(result[1], 'unknown command')
 
2517
 
 
2518
    def test_finish_subprocess_with_unexpected_retcode(self):
 
2519
        """finish_bzr_subprocess raises self.failureException if the retcode is
 
2520
        not the expected one.
 
2521
        """
 
2522
        process = StubProcess(err="unknown command", retcode=3)
 
2523
        self.assertRaises(self.failureException, self.finish_bzr_subprocess,
 
2524
                          process)
 
2525
 
 
2526
 
 
2527
class _DontSpawnProcess(Exception):
 
2528
    """A simple exception which just allows us to skip unnecessary steps"""
 
2529
 
 
2530
 
 
2531
class TestStartBzrSubProcess(tests.TestCase):
 
2532
 
 
2533
    def check_popen_state(self):
 
2534
        """Replace to make assertions when popen is called."""
 
2535
 
 
2536
    def _popen(self, *args, **kwargs):
 
2537
        """Record the command that is run, so that we can ensure it is correct"""
 
2538
        self.check_popen_state()
 
2539
        self._popen_args = args
 
2540
        self._popen_kwargs = kwargs
 
2541
        raise _DontSpawnProcess()
 
2542
 
 
2543
    def test_run_bzr_subprocess_no_plugins(self):
 
2544
        self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [])
 
2545
        command = self._popen_args[0]
 
2546
        self.assertEqual(sys.executable, command[0])
 
2547
        self.assertEqual(self.get_bzr_path(), command[1])
 
2548
        self.assertEqual(['--no-plugins'], command[2:])
 
2549
 
 
2550
    def test_allow_plugins(self):
 
2551
        self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [],
 
2552
            allow_plugins=True)
 
2553
        command = self._popen_args[0]
 
2554
        self.assertEqual([], command[2:])
 
2555
 
 
2556
    def test_set_env(self):
 
2557
        self.failIf('EXISTANT_ENV_VAR' in os.environ)
 
2558
        # set in the child
 
2559
        def check_environment():
 
2560
            self.assertEqual('set variable', os.environ['EXISTANT_ENV_VAR'])
 
2561
        self.check_popen_state = check_environment
 
2562
        self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [],
 
2563
            env_changes={'EXISTANT_ENV_VAR':'set variable'})
 
2564
        # not set in theparent
 
2565
        self.assertFalse('EXISTANT_ENV_VAR' in os.environ)
 
2566
 
 
2567
    def test_run_bzr_subprocess_env_del(self):
 
2568
        """run_bzr_subprocess can remove environment variables too."""
 
2569
        self.failIf('EXISTANT_ENV_VAR' in os.environ)
 
2570
        def check_environment():
 
2571
            self.assertFalse('EXISTANT_ENV_VAR' in os.environ)
 
2572
        os.environ['EXISTANT_ENV_VAR'] = 'set variable'
 
2573
        self.check_popen_state = check_environment
 
2574
        self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [],
 
2575
            env_changes={'EXISTANT_ENV_VAR':None})
 
2576
        # Still set in parent
 
2577
        self.assertEqual('set variable', os.environ['EXISTANT_ENV_VAR'])
 
2578
        del os.environ['EXISTANT_ENV_VAR']
 
2579
 
 
2580
    def test_env_del_missing(self):
 
2581
        self.failIf('NON_EXISTANT_ENV_VAR' in os.environ)
 
2582
        def check_environment():
 
2583
            self.assertFalse('NON_EXISTANT_ENV_VAR' in os.environ)
 
2584
        self.check_popen_state = check_environment
 
2585
        self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [],
 
2586
            env_changes={'NON_EXISTANT_ENV_VAR':None})
 
2587
 
 
2588
    def test_working_dir(self):
 
2589
        """Test that we can specify the working dir for the child"""
 
2590
        orig_getcwd = osutils.getcwd
 
2591
        orig_chdir = os.chdir
 
2592
        chdirs = []
 
2593
        def chdir(path):
 
2594
            chdirs.append(path)
 
2595
        os.chdir = chdir
 
2596
        try:
 
2597
            def getcwd():
 
2598
                return 'current'
 
2599
            osutils.getcwd = getcwd
 
2600
            try:
 
2601
                self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [],
 
2602
                    working_dir='foo')
 
2603
            finally:
 
2604
                osutils.getcwd = orig_getcwd
 
2605
        finally:
 
2606
            os.chdir = orig_chdir
 
2607
        self.assertEqual(['foo', 'current'], chdirs)
 
2608
 
 
2609
    def test_get_bzr_path_with_cwd_bzrlib(self):
 
2610
        self.get_source_path = lambda: ""
 
2611
        self.overrideAttr(os.path, "isfile", lambda path: True)
 
2612
        self.assertEqual(self.get_bzr_path(), "bzr")
 
2613
 
 
2614
 
 
2615
class TestActuallyStartBzrSubprocess(tests.TestCaseWithTransport):
 
2616
    """Tests that really need to do things with an external bzr."""
 
2617
 
 
2618
    def test_start_and_stop_bzr_subprocess_send_signal(self):
 
2619
        """finish_bzr_subprocess raises self.failureException if the retcode is
 
2620
        not the expected one.
 
2621
        """
 
2622
        self.disable_missing_extensions_warning()
 
2623
        process = self.start_bzr_subprocess(['wait-until-signalled'],
 
2624
                                            skip_if_plan_to_signal=True)
 
2625
        self.assertEqual('running\n', process.stdout.readline())
 
2626
        result = self.finish_bzr_subprocess(process, send_signal=signal.SIGINT,
 
2627
                                            retcode=3)
 
2628
        self.assertEqual('', result[0])
 
2629
        self.assertEqual('bzr: interrupted\n', result[1])
 
2630
 
 
2631
 
 
2632
class TestFeature(tests.TestCase):
 
2633
 
 
2634
    def test_caching(self):
 
2635
        """Feature._probe is called by the feature at most once."""
 
2636
        class InstrumentedFeature(tests.Feature):
 
2637
            def __init__(self):
 
2638
                super(InstrumentedFeature, self).__init__()
 
2639
                self.calls = []
 
2640
            def _probe(self):
 
2641
                self.calls.append('_probe')
 
2642
                return False
 
2643
        feature = InstrumentedFeature()
 
2644
        feature.available()
 
2645
        self.assertEqual(['_probe'], feature.calls)
 
2646
        feature.available()
 
2647
        self.assertEqual(['_probe'], feature.calls)
 
2648
 
 
2649
    def test_named_str(self):
 
2650
        """Feature.__str__ should thunk to feature_name()."""
 
2651
        class NamedFeature(tests.Feature):
 
2652
            def feature_name(self):
 
2653
                return 'symlinks'
 
2654
        feature = NamedFeature()
 
2655
        self.assertEqual('symlinks', str(feature))
 
2656
 
 
2657
    def test_default_str(self):
 
2658
        """Feature.__str__ should default to __class__.__name__."""
 
2659
        class NamedFeature(tests.Feature):
 
2660
            pass
 
2661
        feature = NamedFeature()
 
2662
        self.assertEqual('NamedFeature', str(feature))
 
2663
 
 
2664
 
 
2665
class TestUnavailableFeature(tests.TestCase):
 
2666
 
 
2667
    def test_access_feature(self):
 
2668
        feature = tests.Feature()
 
2669
        exception = tests.UnavailableFeature(feature)
 
2670
        self.assertIs(feature, exception.args[0])
 
2671
 
 
2672
 
 
2673
simple_thunk_feature = tests._CompatabilityThunkFeature(
 
2674
    deprecated_in((2, 1, 0)),
 
2675
    'bzrlib.tests.test_selftest',
 
2676
    'simple_thunk_feature','UnicodeFilename',
 
2677
    replacement_module='bzrlib.tests'
 
2678
    )
 
2679
 
 
2680
class Test_CompatibilityFeature(tests.TestCase):
 
2681
 
 
2682
    def test_does_thunk(self):
 
2683
        res = self.callDeprecated(
 
2684
            ['bzrlib.tests.test_selftest.simple_thunk_feature was deprecated'
 
2685
             ' in version 2.1.0. Use bzrlib.tests.UnicodeFilename instead.'],
 
2686
            simple_thunk_feature.available)
 
2687
        self.assertEqual(tests.UnicodeFilename.available(), res)
 
2688
 
 
2689
 
 
2690
class TestModuleAvailableFeature(tests.TestCase):
 
2691
 
 
2692
    def test_available_module(self):
 
2693
        feature = tests.ModuleAvailableFeature('bzrlib.tests')
 
2694
        self.assertEqual('bzrlib.tests', feature.module_name)
 
2695
        self.assertEqual('bzrlib.tests', str(feature))
 
2696
        self.assertTrue(feature.available())
 
2697
        self.assertIs(tests, feature.module)
 
2698
 
 
2699
    def test_unavailable_module(self):
 
2700
        feature = tests.ModuleAvailableFeature('bzrlib.no_such_module_exists')
 
2701
        self.assertEqual('bzrlib.no_such_module_exists', str(feature))
 
2702
        self.assertFalse(feature.available())
 
2703
        self.assertIs(None, feature.module)
 
2704
 
 
2705
 
 
2706
class TestSelftestFiltering(tests.TestCase):
 
2707
 
 
2708
    def setUp(self):
 
2709
        tests.TestCase.setUp(self)
 
2710
        self.suite = TestUtil.TestSuite()
 
2711
        self.loader = TestUtil.TestLoader()
 
2712
        self.suite.addTest(self.loader.loadTestsFromModule(
 
2713
            sys.modules['bzrlib.tests.test_selftest']))
 
2714
        self.all_names = _test_ids(self.suite)
 
2715
 
 
2716
    def test_condition_id_re(self):
 
2717
        test_name = ('bzrlib.tests.test_selftest.TestSelftestFiltering.'
 
2718
            'test_condition_id_re')
 
2719
        filtered_suite = tests.filter_suite_by_condition(
 
2720
            self.suite, tests.condition_id_re('test_condition_id_re'))
 
2721
        self.assertEqual([test_name], _test_ids(filtered_suite))
 
2722
 
 
2723
    def test_condition_id_in_list(self):
 
2724
        test_names = ['bzrlib.tests.test_selftest.TestSelftestFiltering.'
 
2725
                      'test_condition_id_in_list']
 
2726
        id_list = tests.TestIdList(test_names)
 
2727
        filtered_suite = tests.filter_suite_by_condition(
 
2728
            self.suite, tests.condition_id_in_list(id_list))
 
2729
        my_pattern = 'TestSelftestFiltering.*test_condition_id_in_list'
 
2730
        re_filtered = tests.filter_suite_by_re(self.suite, my_pattern)
 
2731
        self.assertEqual(_test_ids(re_filtered), _test_ids(filtered_suite))
 
2732
 
 
2733
    def test_condition_id_startswith(self):
 
2734
        klass = 'bzrlib.tests.test_selftest.TestSelftestFiltering.'
 
2735
        start1 = klass + 'test_condition_id_starts'
 
2736
        start2 = klass + 'test_condition_id_in'
 
2737
        test_names = [ klass + 'test_condition_id_in_list',
 
2738
                      klass + 'test_condition_id_startswith',
 
2739
                     ]
 
2740
        filtered_suite = tests.filter_suite_by_condition(
 
2741
            self.suite, tests.condition_id_startswith([start1, start2]))
 
2742
        self.assertEqual(test_names, _test_ids(filtered_suite))
 
2743
 
 
2744
    def test_condition_isinstance(self):
 
2745
        filtered_suite = tests.filter_suite_by_condition(
 
2746
            self.suite, tests.condition_isinstance(self.__class__))
 
2747
        class_pattern = 'bzrlib.tests.test_selftest.TestSelftestFiltering.'
 
2748
        re_filtered = tests.filter_suite_by_re(self.suite, class_pattern)
 
2749
        self.assertEqual(_test_ids(re_filtered), _test_ids(filtered_suite))
 
2750
 
 
2751
    def test_exclude_tests_by_condition(self):
 
2752
        excluded_name = ('bzrlib.tests.test_selftest.TestSelftestFiltering.'
 
2753
            'test_exclude_tests_by_condition')
 
2754
        filtered_suite = tests.exclude_tests_by_condition(self.suite,
 
2755
            lambda x:x.id() == excluded_name)
 
2756
        self.assertEqual(len(self.all_names) - 1,
 
2757
            filtered_suite.countTestCases())
 
2758
        self.assertFalse(excluded_name in _test_ids(filtered_suite))
 
2759
        remaining_names = list(self.all_names)
 
2760
        remaining_names.remove(excluded_name)
 
2761
        self.assertEqual(remaining_names, _test_ids(filtered_suite))
 
2762
 
 
2763
    def test_exclude_tests_by_re(self):
 
2764
        self.all_names = _test_ids(self.suite)
 
2765
        filtered_suite = tests.exclude_tests_by_re(self.suite,
 
2766
                                                   'exclude_tests_by_re')
 
2767
        excluded_name = ('bzrlib.tests.test_selftest.TestSelftestFiltering.'
 
2768
            'test_exclude_tests_by_re')
 
2769
        self.assertEqual(len(self.all_names) - 1,
 
2770
            filtered_suite.countTestCases())
 
2771
        self.assertFalse(excluded_name in _test_ids(filtered_suite))
 
2772
        remaining_names = list(self.all_names)
 
2773
        remaining_names.remove(excluded_name)
 
2774
        self.assertEqual(remaining_names, _test_ids(filtered_suite))
 
2775
 
 
2776
    def test_filter_suite_by_condition(self):
 
2777
        test_name = ('bzrlib.tests.test_selftest.TestSelftestFiltering.'
 
2778
            'test_filter_suite_by_condition')
 
2779
        filtered_suite = tests.filter_suite_by_condition(self.suite,
 
2780
            lambda x:x.id() == test_name)
 
2781
        self.assertEqual([test_name], _test_ids(filtered_suite))
 
2782
 
 
2783
    def test_filter_suite_by_re(self):
 
2784
        filtered_suite = tests.filter_suite_by_re(self.suite,
 
2785
                                                  'test_filter_suite_by_r')
 
2786
        filtered_names = _test_ids(filtered_suite)
 
2787
        self.assertEqual(filtered_names, ['bzrlib.tests.test_selftest.'
 
2788
            'TestSelftestFiltering.test_filter_suite_by_re'])
 
2789
 
 
2790
    def test_filter_suite_by_id_list(self):
 
2791
        test_list = ['bzrlib.tests.test_selftest.'
 
2792
                     'TestSelftestFiltering.test_filter_suite_by_id_list']
 
2793
        filtered_suite = tests.filter_suite_by_id_list(
 
2794
            self.suite, tests.TestIdList(test_list))
 
2795
        filtered_names = _test_ids(filtered_suite)
 
2796
        self.assertEqual(
 
2797
            filtered_names,
 
2798
            ['bzrlib.tests.test_selftest.'
 
2799
             'TestSelftestFiltering.test_filter_suite_by_id_list'])
 
2800
 
 
2801
    def test_filter_suite_by_id_startswith(self):
 
2802
        # By design this test may fail if another test is added whose name also
 
2803
        # begins with one of the start value used.
 
2804
        klass = 'bzrlib.tests.test_selftest.TestSelftestFiltering.'
 
2805
        start1 = klass + 'test_filter_suite_by_id_starts'
 
2806
        start2 = klass + 'test_filter_suite_by_id_li'
 
2807
        test_list = [klass + 'test_filter_suite_by_id_list',
 
2808
                     klass + 'test_filter_suite_by_id_startswith',
 
2809
                     ]
 
2810
        filtered_suite = tests.filter_suite_by_id_startswith(
 
2811
            self.suite, [start1, start2])
 
2812
        self.assertEqual(
 
2813
            test_list,
 
2814
            _test_ids(filtered_suite),
 
2815
            )
 
2816
 
 
2817
    def test_preserve_input(self):
 
2818
        # NB: Surely this is something in the stdlib to do this?
 
2819
        self.assertTrue(self.suite is tests.preserve_input(self.suite))
 
2820
        self.assertTrue("@#$" is tests.preserve_input("@#$"))
 
2821
 
 
2822
    def test_randomize_suite(self):
 
2823
        randomized_suite = tests.randomize_suite(self.suite)
 
2824
        # randomizing should not add or remove test names.
 
2825
        self.assertEqual(set(_test_ids(self.suite)),
 
2826
                         set(_test_ids(randomized_suite)))
 
2827
        # Technically, this *can* fail, because random.shuffle(list) can be
 
2828
        # equal to list. Trying multiple times just pushes the frequency back.
 
2829
        # As its len(self.all_names)!:1, the failure frequency should be low
 
2830
        # enough to ignore. RBC 20071021.
 
2831
        # It should change the order.
 
2832
        self.assertNotEqual(self.all_names, _test_ids(randomized_suite))
 
2833
        # But not the length. (Possibly redundant with the set test, but not
 
2834
        # necessarily.)
 
2835
        self.assertEqual(len(self.all_names), len(_test_ids(randomized_suite)))
 
2836
 
 
2837
    def test_split_suit_by_condition(self):
 
2838
        self.all_names = _test_ids(self.suite)
 
2839
        condition = tests.condition_id_re('test_filter_suite_by_r')
 
2840
        split_suite = tests.split_suite_by_condition(self.suite, condition)
 
2841
        filtered_name = ('bzrlib.tests.test_selftest.TestSelftestFiltering.'
 
2842
            'test_filter_suite_by_re')
 
2843
        self.assertEqual([filtered_name], _test_ids(split_suite[0]))
 
2844
        self.assertFalse(filtered_name in _test_ids(split_suite[1]))
 
2845
        remaining_names = list(self.all_names)
 
2846
        remaining_names.remove(filtered_name)
 
2847
        self.assertEqual(remaining_names, _test_ids(split_suite[1]))
 
2848
 
 
2849
    def test_split_suit_by_re(self):
 
2850
        self.all_names = _test_ids(self.suite)
 
2851
        split_suite = tests.split_suite_by_re(self.suite,
 
2852
                                              'test_filter_suite_by_r')
 
2853
        filtered_name = ('bzrlib.tests.test_selftest.TestSelftestFiltering.'
 
2854
            'test_filter_suite_by_re')
 
2855
        self.assertEqual([filtered_name], _test_ids(split_suite[0]))
 
2856
        self.assertFalse(filtered_name in _test_ids(split_suite[1]))
 
2857
        remaining_names = list(self.all_names)
 
2858
        remaining_names.remove(filtered_name)
 
2859
        self.assertEqual(remaining_names, _test_ids(split_suite[1]))
 
2860
 
 
2861
 
 
2862
class TestCheckInventoryShape(tests.TestCaseWithTransport):
 
2863
 
 
2864
    def test_check_inventory_shape(self):
 
2865
        files = ['a', 'b/', 'b/c']
 
2866
        tree = self.make_branch_and_tree('.')
 
2867
        self.build_tree(files)
 
2868
        tree.add(files)
 
2869
        tree.lock_read()
 
2870
        try:
 
2871
            self.check_inventory_shape(tree.inventory, files)
 
2872
        finally:
 
2873
            tree.unlock()
 
2874
 
 
2875
 
 
2876
class TestBlackboxSupport(tests.TestCase):
 
2877
    """Tests for testsuite blackbox features."""
 
2878
 
 
2879
    def test_run_bzr_failure_not_caught(self):
 
2880
        # When we run bzr in blackbox mode, we want any unexpected errors to
 
2881
        # propagate up to the test suite so that it can show the error in the
 
2882
        # usual way, and we won't get a double traceback.
 
2883
        e = self.assertRaises(
 
2884
            AssertionError,
 
2885
            self.run_bzr, ['assert-fail'])
 
2886
        # make sure we got the real thing, not an error from somewhere else in
 
2887
        # the test framework
 
2888
        self.assertEquals('always fails', str(e))
 
2889
        # check that there's no traceback in the test log
 
2890
        self.assertNotContainsRe(self.get_log(), r'Traceback')
 
2891
 
 
2892
    def test_run_bzr_user_error_caught(self):
 
2893
        # Running bzr in blackbox mode, normal/expected/user errors should be
 
2894
        # caught in the regular way and turned into an error message plus exit
 
2895
        # code.
 
2896
        transport_server = memory.MemoryServer()
 
2897
        transport_server.start_server()
 
2898
        self.addCleanup(transport_server.stop_server)
 
2899
        url = transport_server.get_url()
 
2900
        self.permit_url(url)
 
2901
        out, err = self.run_bzr(["log", "%s/nonexistantpath" % url], retcode=3)
 
2902
        self.assertEqual(out, '')
 
2903
        self.assertContainsRe(err,
 
2904
            'bzr: ERROR: Not a branch: ".*nonexistantpath/".\n')
 
2905
 
 
2906
 
 
2907
class TestTestLoader(tests.TestCase):
 
2908
    """Tests for the test loader."""
 
2909
 
 
2910
    def _get_loader_and_module(self):
 
2911
        """Gets a TestLoader and a module with one test in it."""
 
2912
        loader = TestUtil.TestLoader()
 
2913
        module = {}
 
2914
        class Stub(tests.TestCase):
 
2915
            def test_foo(self):
 
2916
                pass
 
2917
        class MyModule(object):
 
2918
            pass
 
2919
        MyModule.a_class = Stub
 
2920
        module = MyModule()
 
2921
        return loader, module
 
2922
 
 
2923
    def test_module_no_load_tests_attribute_loads_classes(self):
 
2924
        loader, module = self._get_loader_and_module()
 
2925
        self.assertEqual(1, loader.loadTestsFromModule(module).countTestCases())
 
2926
 
 
2927
    def test_module_load_tests_attribute_gets_called(self):
 
2928
        loader, module = self._get_loader_and_module()
 
2929
        # 'self' is here because we're faking the module with a class. Regular
 
2930
        # load_tests do not need that :)
 
2931
        def load_tests(self, standard_tests, module, loader):
 
2932
            result = loader.suiteClass()
 
2933
            for test in tests.iter_suite_tests(standard_tests):
 
2934
                result.addTests([test, test])
 
2935
            return result
 
2936
        # add a load_tests() method which multiplies the tests from the module.
 
2937
        module.__class__.load_tests = load_tests
 
2938
        self.assertEqual(2, loader.loadTestsFromModule(module).countTestCases())
 
2939
 
 
2940
    def test_load_tests_from_module_name_smoke_test(self):
 
2941
        loader = TestUtil.TestLoader()
 
2942
        suite = loader.loadTestsFromModuleName('bzrlib.tests.test_sampler')
 
2943
        self.assertEquals(['bzrlib.tests.test_sampler.DemoTest.test_nothing'],
 
2944
                          _test_ids(suite))
 
2945
 
 
2946
    def test_load_tests_from_module_name_with_bogus_module_name(self):
 
2947
        loader = TestUtil.TestLoader()
 
2948
        self.assertRaises(ImportError, loader.loadTestsFromModuleName, 'bogus')
 
2949
 
 
2950
 
 
2951
class TestTestIdList(tests.TestCase):
 
2952
 
 
2953
    def _create_id_list(self, test_list):
 
2954
        return tests.TestIdList(test_list)
 
2955
 
 
2956
    def _create_suite(self, test_id_list):
 
2957
 
 
2958
        class Stub(tests.TestCase):
 
2959
            def test_foo(self):
 
2960
                pass
 
2961
 
 
2962
        def _create_test_id(id):
 
2963
            return lambda: id
 
2964
 
 
2965
        suite = TestUtil.TestSuite()
 
2966
        for id in test_id_list:
 
2967
            t  = Stub('test_foo')
 
2968
            t.id = _create_test_id(id)
 
2969
            suite.addTest(t)
 
2970
        return suite
 
2971
 
 
2972
    def _test_ids(self, test_suite):
 
2973
        """Get the ids for the tests in a test suite."""
 
2974
        return [t.id() for t in tests.iter_suite_tests(test_suite)]
 
2975
 
 
2976
    def test_empty_list(self):
 
2977
        id_list = self._create_id_list([])
 
2978
        self.assertEquals({}, id_list.tests)
 
2979
        self.assertEquals({}, id_list.modules)
 
2980
 
 
2981
    def test_valid_list(self):
 
2982
        id_list = self._create_id_list(
 
2983
            ['mod1.cl1.meth1', 'mod1.cl1.meth2',
 
2984
             'mod1.func1', 'mod1.cl2.meth2',
 
2985
             'mod1.submod1',
 
2986
             'mod1.submod2.cl1.meth1', 'mod1.submod2.cl2.meth2',
 
2987
             ])
 
2988
        self.assertTrue(id_list.refers_to('mod1'))
 
2989
        self.assertTrue(id_list.refers_to('mod1.submod1'))
 
2990
        self.assertTrue(id_list.refers_to('mod1.submod2'))
 
2991
        self.assertTrue(id_list.includes('mod1.cl1.meth1'))
 
2992
        self.assertTrue(id_list.includes('mod1.submod1'))
 
2993
        self.assertTrue(id_list.includes('mod1.func1'))
 
2994
 
 
2995
    def test_bad_chars_in_params(self):
 
2996
        id_list = self._create_id_list(['mod1.cl1.meth1(xx.yy)'])
 
2997
        self.assertTrue(id_list.refers_to('mod1'))
 
2998
        self.assertTrue(id_list.includes('mod1.cl1.meth1(xx.yy)'))
 
2999
 
 
3000
    def test_module_used(self):
 
3001
        id_list = self._create_id_list(['mod.class.meth'])
 
3002
        self.assertTrue(id_list.refers_to('mod'))
 
3003
        self.assertTrue(id_list.refers_to('mod.class'))
 
3004
        self.assertTrue(id_list.refers_to('mod.class.meth'))
 
3005
 
 
3006
    def test_test_suite_matches_id_list_with_unknown(self):
 
3007
        loader = TestUtil.TestLoader()
 
3008
        suite = loader.loadTestsFromModuleName('bzrlib.tests.test_sampler')
 
3009
        test_list = ['bzrlib.tests.test_sampler.DemoTest.test_nothing',
 
3010
                     'bogus']
 
3011
        not_found, duplicates = tests.suite_matches_id_list(suite, test_list)
 
3012
        self.assertEquals(['bogus'], not_found)
 
3013
        self.assertEquals([], duplicates)
 
3014
 
 
3015
    def test_suite_matches_id_list_with_duplicates(self):
 
3016
        loader = TestUtil.TestLoader()
 
3017
        suite = loader.loadTestsFromModuleName('bzrlib.tests.test_sampler')
 
3018
        dupes = loader.suiteClass()
 
3019
        for test in tests.iter_suite_tests(suite):
 
3020
            dupes.addTest(test)
 
3021
            dupes.addTest(test) # Add it again
 
3022
 
 
3023
        test_list = ['bzrlib.tests.test_sampler.DemoTest.test_nothing',]
 
3024
        not_found, duplicates = tests.suite_matches_id_list(
 
3025
            dupes, test_list)
 
3026
        self.assertEquals([], not_found)
 
3027
        self.assertEquals(['bzrlib.tests.test_sampler.DemoTest.test_nothing'],
 
3028
                          duplicates)
 
3029
 
 
3030
 
 
3031
class TestTestSuite(tests.TestCase):
 
3032
 
 
3033
    def test__test_suite_testmod_names(self):
 
3034
        # Test that a plausible list of test module names are returned
 
3035
        # by _test_suite_testmod_names.
 
3036
        test_list = tests._test_suite_testmod_names()
 
3037
        self.assertSubset([
 
3038
            'bzrlib.tests.blackbox',
 
3039
            'bzrlib.tests.per_transport',
 
3040
            'bzrlib.tests.test_selftest',
 
3041
            ],
 
3042
            test_list)
 
3043
 
 
3044
    def test__test_suite_modules_to_doctest(self):
 
3045
        # Test that a plausible list of modules to doctest is returned
 
3046
        # by _test_suite_modules_to_doctest.
 
3047
        test_list = tests._test_suite_modules_to_doctest()
 
3048
        if __doc__ is None:
 
3049
            # When docstrings are stripped, there are no modules to doctest
 
3050
            self.assertEqual([], test_list)
 
3051
            return
 
3052
        self.assertSubset([
 
3053
            'bzrlib.timestamp',
 
3054
            ],
 
3055
            test_list)
 
3056
 
 
3057
    def test_test_suite(self):
 
3058
        # test_suite() loads the entire test suite to operate. To avoid this
 
3059
        # overhead, and yet still be confident that things are happening,
 
3060
        # we temporarily replace two functions used by test_suite with 
 
3061
        # test doubles that supply a few sample tests to load, and check they
 
3062
        # are loaded.
 
3063
        calls = []
 
3064
        def testmod_names():
 
3065
            calls.append("testmod_names")
 
3066
            return [
 
3067
                'bzrlib.tests.blackbox.test_branch',
 
3068
                'bzrlib.tests.per_transport',
 
3069
                'bzrlib.tests.test_selftest',
 
3070
                ]
 
3071
        self.overrideAttr(tests, '_test_suite_testmod_names', testmod_names)
 
3072
        def doctests():
 
3073
            calls.append("modules_to_doctest")
 
3074
            if __doc__ is None:
 
3075
                return []
 
3076
            return ['bzrlib.timestamp']
 
3077
        self.overrideAttr(tests, '_test_suite_modules_to_doctest', doctests)
 
3078
        expected_test_list = [
 
3079
            # testmod_names
 
3080
            'bzrlib.tests.blackbox.test_branch.TestBranch.test_branch',
 
3081
            ('bzrlib.tests.per_transport.TransportTests'
 
3082
             '.test_abspath(LocalTransport,LocalURLServer)'),
 
3083
            'bzrlib.tests.test_selftest.TestTestSuite.test_test_suite',
 
3084
            # plugins can't be tested that way since selftest may be run with
 
3085
            # --no-plugins
 
3086
            ]
 
3087
        if __doc__ is not None:
 
3088
            expected_test_list.extend([
 
3089
                # modules_to_doctest
 
3090
                'bzrlib.timestamp.format_highres_date',
 
3091
                ])
 
3092
        suite = tests.test_suite()
 
3093
        self.assertEqual(set(["testmod_names", "modules_to_doctest"]),
 
3094
            set(calls))
 
3095
        self.assertSubset(expected_test_list, _test_ids(suite))
 
3096
 
 
3097
    def test_test_suite_list_and_start(self):
 
3098
        # We cannot test this at the same time as the main load, because we want
 
3099
        # to know that starting_with == None works. So a second load is
 
3100
        # incurred - note that the starting_with parameter causes a partial load
 
3101
        # rather than a full load so this test should be pretty quick.
 
3102
        test_list = ['bzrlib.tests.test_selftest.TestTestSuite.test_test_suite']
 
3103
        suite = tests.test_suite(test_list,
 
3104
                                 ['bzrlib.tests.test_selftest.TestTestSuite'])
 
3105
        # test_test_suite_list_and_start is not included 
 
3106
        self.assertEquals(test_list, _test_ids(suite))
 
3107
 
 
3108
 
 
3109
class TestLoadTestIdList(tests.TestCaseInTempDir):
 
3110
 
 
3111
    def _create_test_list_file(self, file_name, content):
 
3112
        fl = open(file_name, 'wt')
 
3113
        fl.write(content)
 
3114
        fl.close()
 
3115
 
 
3116
    def test_load_unknown(self):
 
3117
        self.assertRaises(errors.NoSuchFile,
 
3118
                          tests.load_test_id_list, 'i_do_not_exist')
 
3119
 
 
3120
    def test_load_test_list(self):
 
3121
        test_list_fname = 'test.list'
 
3122
        self._create_test_list_file(test_list_fname,
 
3123
                                    'mod1.cl1.meth1\nmod2.cl2.meth2\n')
 
3124
        tlist = tests.load_test_id_list(test_list_fname)
 
3125
        self.assertEquals(2, len(tlist))
 
3126
        self.assertEquals('mod1.cl1.meth1', tlist[0])
 
3127
        self.assertEquals('mod2.cl2.meth2', tlist[1])
 
3128
 
 
3129
    def test_load_dirty_file(self):
 
3130
        test_list_fname = 'test.list'
 
3131
        self._create_test_list_file(test_list_fname,
 
3132
                                    '  mod1.cl1.meth1\n\nmod2.cl2.meth2  \n'
 
3133
                                    'bar baz\n')
 
3134
        tlist = tests.load_test_id_list(test_list_fname)
 
3135
        self.assertEquals(4, len(tlist))
 
3136
        self.assertEquals('mod1.cl1.meth1', tlist[0])
 
3137
        self.assertEquals('', tlist[1])
 
3138
        self.assertEquals('mod2.cl2.meth2', tlist[2])
 
3139
        self.assertEquals('bar baz', tlist[3])
 
3140
 
 
3141
 
 
3142
class TestFilteredByModuleTestLoader(tests.TestCase):
 
3143
 
 
3144
    def _create_loader(self, test_list):
 
3145
        id_filter = tests.TestIdList(test_list)
 
3146
        loader = TestUtil.FilteredByModuleTestLoader(id_filter.refers_to)
 
3147
        return loader
 
3148
 
 
3149
    def test_load_tests(self):
 
3150
        test_list = ['bzrlib.tests.test_sampler.DemoTest.test_nothing']
 
3151
        loader = self._create_loader(test_list)
 
3152
        suite = loader.loadTestsFromModuleName('bzrlib.tests.test_sampler')
 
3153
        self.assertEquals(test_list, _test_ids(suite))
 
3154
 
 
3155
    def test_exclude_tests(self):
 
3156
        test_list = ['bogus']
 
3157
        loader = self._create_loader(test_list)
 
3158
        suite = loader.loadTestsFromModuleName('bzrlib.tests.test_sampler')
 
3159
        self.assertEquals([], _test_ids(suite))
 
3160
 
 
3161
 
 
3162
class TestFilteredByNameStartTestLoader(tests.TestCase):
 
3163
 
 
3164
    def _create_loader(self, name_start):
 
3165
        def needs_module(name):
 
3166
            return name.startswith(name_start) or name_start.startswith(name)
 
3167
        loader = TestUtil.FilteredByModuleTestLoader(needs_module)
 
3168
        return loader
 
3169
 
 
3170
    def test_load_tests(self):
 
3171
        test_list = ['bzrlib.tests.test_sampler.DemoTest.test_nothing']
 
3172
        loader = self._create_loader('bzrlib.tests.test_samp')
 
3173
 
 
3174
        suite = loader.loadTestsFromModuleName('bzrlib.tests.test_sampler')
 
3175
        self.assertEquals(test_list, _test_ids(suite))
 
3176
 
 
3177
    def test_load_tests_inside_module(self):
 
3178
        test_list = ['bzrlib.tests.test_sampler.DemoTest.test_nothing']
 
3179
        loader = self._create_loader('bzrlib.tests.test_sampler.Demo')
 
3180
 
 
3181
        suite = loader.loadTestsFromModuleName('bzrlib.tests.test_sampler')
 
3182
        self.assertEquals(test_list, _test_ids(suite))
 
3183
 
 
3184
    def test_exclude_tests(self):
 
3185
        test_list = ['bogus']
 
3186
        loader = self._create_loader('bogus')
 
3187
 
 
3188
        suite = loader.loadTestsFromModuleName('bzrlib.tests.test_sampler')
 
3189
        self.assertEquals([], _test_ids(suite))
 
3190
 
 
3191
 
 
3192
class TestTestPrefixRegistry(tests.TestCase):
 
3193
 
 
3194
    def _get_registry(self):
 
3195
        tp_registry = tests.TestPrefixAliasRegistry()
 
3196
        return tp_registry
 
3197
 
 
3198
    def test_register_new_prefix(self):
 
3199
        tpr = self._get_registry()
 
3200
        tpr.register('foo', 'fff.ooo.ooo')
 
3201
        self.assertEquals('fff.ooo.ooo', tpr.get('foo'))
 
3202
 
 
3203
    def test_register_existing_prefix(self):
 
3204
        tpr = self._get_registry()
 
3205
        tpr.register('bar', 'bbb.aaa.rrr')
 
3206
        tpr.register('bar', 'bBB.aAA.rRR')
 
3207
        self.assertEquals('bbb.aaa.rrr', tpr.get('bar'))
 
3208
        self.assertThat(self.get_log(),
 
3209
            DocTestMatches("...bar...bbb.aaa.rrr...BB.aAA.rRR",
 
3210
                           doctest.ELLIPSIS))
 
3211
 
 
3212
    def test_get_unknown_prefix(self):
 
3213
        tpr = self._get_registry()
 
3214
        self.assertRaises(KeyError, tpr.get, 'I am not a prefix')
 
3215
 
 
3216
    def test_resolve_prefix(self):
 
3217
        tpr = self._get_registry()
 
3218
        tpr.register('bar', 'bb.aa.rr')
 
3219
        self.assertEquals('bb.aa.rr', tpr.resolve_alias('bar'))
 
3220
 
 
3221
    def test_resolve_unknown_alias(self):
 
3222
        tpr = self._get_registry()
 
3223
        self.assertRaises(errors.BzrCommandError,
 
3224
                          tpr.resolve_alias, 'I am not a prefix')
 
3225
 
 
3226
    def test_predefined_prefixes(self):
 
3227
        tpr = tests.test_prefix_alias_registry
 
3228
        self.assertEquals('bzrlib', tpr.resolve_alias('bzrlib'))
 
3229
        self.assertEquals('bzrlib.doc', tpr.resolve_alias('bd'))
 
3230
        self.assertEquals('bzrlib.utils', tpr.resolve_alias('bu'))
 
3231
        self.assertEquals('bzrlib.tests', tpr.resolve_alias('bt'))
 
3232
        self.assertEquals('bzrlib.tests.blackbox', tpr.resolve_alias('bb'))
 
3233
        self.assertEquals('bzrlib.plugins', tpr.resolve_alias('bp'))
 
3234
 
 
3235
 
 
3236
class TestThreadLeakDetection(tests.TestCase):
 
3237
    """Ensure when tests leak threads we detect and report it"""
 
3238
 
 
3239
    class LeakRecordingResult(tests.ExtendedTestResult):
 
3240
        def __init__(self):
 
3241
            tests.ExtendedTestResult.__init__(self, StringIO(), 0, 1)
 
3242
            self.leaks = []
 
3243
        def _report_thread_leak(self, test, leaks, alive):
 
3244
            self.leaks.append((test, leaks))
 
3245
 
 
3246
    def test_testcase_without_addCleanups(self):
 
3247
        """Check old TestCase instances don't break with leak detection"""
 
3248
        class Test(unittest.TestCase):
 
3249
            def runTest(self):
 
3250
                pass
 
3251
        result = self.LeakRecordingResult()
 
3252
        test = Test()
 
3253
        result.startTestRun()
 
3254
        test.run(result)
 
3255
        result.stopTestRun()
 
3256
        self.assertEqual(result._tests_leaking_threads_count, 0)
 
3257
        self.assertEqual(result.leaks, [])
 
3258
        
 
3259
    def test_thread_leak(self):
 
3260
        """Ensure a thread that outlives the running of a test is reported
 
3261
 
 
3262
        Uses a thread that blocks on an event, and is started by the inner
 
3263
        test case. As the thread outlives the inner case's run, it should be
 
3264
        detected as a leak, but the event is then set so that the thread can
 
3265
        be safely joined in cleanup so it's not leaked for real.
 
3266
        """
 
3267
        event = threading.Event()
 
3268
        thread = threading.Thread(name="Leaker", target=event.wait)
 
3269
        class Test(tests.TestCase):
 
3270
            def test_leak(self):
 
3271
                thread.start()
 
3272
        result = self.LeakRecordingResult()
 
3273
        test = Test("test_leak")
 
3274
        self.addCleanup(thread.join)
 
3275
        self.addCleanup(event.set)
 
3276
        result.startTestRun()
 
3277
        test.run(result)
 
3278
        result.stopTestRun()
 
3279
        self.assertEqual(result._tests_leaking_threads_count, 1)
 
3280
        self.assertEqual(result._first_thread_leaker_id, test.id())
 
3281
        self.assertEqual(result.leaks, [(test, set([thread]))])
 
3282
        self.assertContainsString(result.stream.getvalue(), "leaking threads")
 
3283
 
 
3284
    def test_multiple_leaks(self):
 
3285
        """Check multiple leaks are blamed on the test cases at fault
 
3286
 
 
3287
        Same concept as the previous test, but has one inner test method that
 
3288
        leaks two threads, and one that doesn't leak at all.
 
3289
        """
 
3290
        event = threading.Event()
 
3291
        thread_a = threading.Thread(name="LeakerA", target=event.wait)
 
3292
        thread_b = threading.Thread(name="LeakerB", target=event.wait)
 
3293
        thread_c = threading.Thread(name="LeakerC", target=event.wait)
 
3294
        class Test(tests.TestCase):
 
3295
            def test_first_leak(self):
 
3296
                thread_b.start()
 
3297
            def test_second_no_leak(self):
 
3298
                pass
 
3299
            def test_third_leak(self):
 
3300
                thread_c.start()
 
3301
                thread_a.start()
 
3302
        result = self.LeakRecordingResult()
 
3303
        first_test = Test("test_first_leak")
 
3304
        third_test = Test("test_third_leak")
 
3305
        self.addCleanup(thread_a.join)
 
3306
        self.addCleanup(thread_b.join)
 
3307
        self.addCleanup(thread_c.join)
 
3308
        self.addCleanup(event.set)
 
3309
        result.startTestRun()
 
3310
        unittest.TestSuite(
 
3311
            [first_test, Test("test_second_no_leak"), third_test]
 
3312
            ).run(result)
 
3313
        result.stopTestRun()
 
3314
        self.assertEqual(result._tests_leaking_threads_count, 2)
 
3315
        self.assertEqual(result._first_thread_leaker_id, first_test.id())
 
3316
        self.assertEqual(result.leaks, [
 
3317
            (first_test, set([thread_b])),
 
3318
            (third_test, set([thread_a, thread_c]))])
 
3319
        self.assertContainsString(result.stream.getvalue(), "leaking threads")
 
3320
 
 
3321
 
 
3322
class TestPostMortemDebugging(tests.TestCase):
 
3323
    """Check post mortem debugging works when tests fail or error"""
 
3324
 
 
3325
    class TracebackRecordingResult(tests.ExtendedTestResult):
 
3326
        def __init__(self):
 
3327
            tests.ExtendedTestResult.__init__(self, StringIO(), 0, 1)
 
3328
            self.postcode = None
 
3329
        def _post_mortem(self, tb=None):
 
3330
            """Record the code object at the end of the current traceback"""
 
3331
            tb = tb or sys.exc_info()[2]
 
3332
            if tb is not None:
 
3333
                next = tb.tb_next
 
3334
                while next is not None:
 
3335
                    tb = next
 
3336
                    next = next.tb_next
 
3337
                self.postcode = tb.tb_frame.f_code
 
3338
        def report_error(self, test, err):
 
3339
            pass
 
3340
        def report_failure(self, test, err):
 
3341
            pass
 
3342
 
 
3343
    def test_location_unittest_error(self):
 
3344
        """Needs right post mortem traceback with erroring unittest case"""
 
3345
        class Test(unittest.TestCase):
 
3346
            def runTest(self):
 
3347
                raise RuntimeError
 
3348
        result = self.TracebackRecordingResult()
 
3349
        Test().run(result)
 
3350
        self.assertEqual(result.postcode, Test.runTest.func_code)
 
3351
 
 
3352
    def test_location_unittest_failure(self):
 
3353
        """Needs right post mortem traceback with failing unittest case"""
 
3354
        class Test(unittest.TestCase):
 
3355
            def runTest(self):
 
3356
                raise self.failureException
 
3357
        result = self.TracebackRecordingResult()
 
3358
        Test().run(result)
 
3359
        self.assertEqual(result.postcode, Test.runTest.func_code)
 
3360
 
 
3361
    def test_location_bt_error(self):
 
3362
        """Needs right post mortem traceback with erroring bzrlib.tests case"""
 
3363
        class Test(tests.TestCase):
 
3364
            def test_error(self):
 
3365
                raise RuntimeError
 
3366
        result = self.TracebackRecordingResult()
 
3367
        Test("test_error").run(result)
 
3368
        self.assertEqual(result.postcode, Test.test_error.func_code)
 
3369
 
 
3370
    def test_location_bt_failure(self):
 
3371
        """Needs right post mortem traceback with failing bzrlib.tests case"""
 
3372
        class Test(tests.TestCase):
 
3373
            def test_failure(self):
 
3374
                raise self.failureException
 
3375
        result = self.TracebackRecordingResult()
 
3376
        Test("test_failure").run(result)
 
3377
        self.assertEqual(result.postcode, Test.test_failure.func_code)
 
3378
 
 
3379
    def test_env_var_triggers_post_mortem(self):
 
3380
        """Check pdb.post_mortem is called iff BZR_TEST_PDB is set"""
 
3381
        import pdb
 
3382
        result = tests.ExtendedTestResult(StringIO(), 0, 1)
 
3383
        post_mortem_calls = []
 
3384
        self.overrideAttr(pdb, "post_mortem", post_mortem_calls.append)
 
3385
        self.overrideEnv('BZR_TEST_PDB', None)
 
3386
        result._post_mortem(1)
 
3387
        self.overrideEnv('BZR_TEST_PDB', 'on')
 
3388
        result._post_mortem(2)
 
3389
        self.assertEqual([2], post_mortem_calls)
 
3390
 
 
3391
 
 
3392
class TestRunSuite(tests.TestCase):
 
3393
 
 
3394
    def test_runner_class(self):
 
3395
        """run_suite accepts and uses a runner_class keyword argument."""
 
3396
        class Stub(tests.TestCase):
 
3397
            def test_foo(self):
 
3398
                pass
 
3399
        suite = Stub("test_foo")
 
3400
        calls = []
 
3401
        class MyRunner(tests.TextTestRunner):
 
3402
            def run(self, test):
 
3403
                calls.append(test)
 
3404
                return tests.ExtendedTestResult(self.stream, self.descriptions,
 
3405
                                                self.verbosity)
 
3406
        tests.run_suite(suite, runner_class=MyRunner, stream=StringIO())
 
3407
        self.assertLength(1, calls)
 
3408
 
 
3409
 
 
3410
class TestEnvironHandling(tests.TestCase):
 
3411
 
 
3412
    def test_overrideEnv_None_called_twice_doesnt_leak(self):
 
3413
        self.failIf('MYVAR' in os.environ)
 
3414
        self.overrideEnv('MYVAR', '42')
 
3415
        # We use an embedded test to make sure we fix the _captureVar bug
 
3416
        class Test(tests.TestCase):
 
3417
            def test_me(self):
 
3418
                # The first call save the 42 value
 
3419
                self.overrideEnv('MYVAR', None)
 
3420
                self.assertEquals(None, os.environ.get('MYVAR'))
 
3421
                # Make sure we can call it twice
 
3422
                self.overrideEnv('MYVAR', None)
 
3423
                self.assertEquals(None, os.environ.get('MYVAR'))
 
3424
        output = StringIO()
 
3425
        result = tests.TextTestResult(output, 0, 1)
 
3426
        Test('test_me').run(result)
 
3427
        if not result.wasStrictlySuccessful():
 
3428
            self.fail(output.getvalue())
 
3429
        # We get our value back
 
3430
        self.assertEquals('42', os.environ.get('MYVAR'))
 
3431
 
 
3432
 
 
3433
class TestIsolatedEnv(tests.TestCase):
 
3434
    """Test isolating tests from os.environ.
 
3435
 
 
3436
    Since we use tests that are already isolated from os.environ a bit of care
 
3437
    should be taken when designing the tests to avoid bootstrap side-effects.
 
3438
    The tests start an already clean os.environ which allow doing valid
 
3439
    assertions about which variables are present or not and design tests around
 
3440
    these assertions.
 
3441
    """
 
3442
 
 
3443
    class ScratchMonkey(tests.TestCase):
 
3444
 
 
3445
        def test_me(self):
 
3446
            pass
 
3447
 
 
3448
    def test_basics(self):
 
3449
        # Make sure we know the definition of BZR_HOME: not part of os.environ
 
3450
        # for tests.TestCase.
 
3451
        self.assertTrue('BZR_HOME' in tests.isolated_environ)
 
3452
        self.assertEquals(None, tests.isolated_environ['BZR_HOME'])
 
3453
        # Being part of isolated_environ, BZR_HOME should not appear here
 
3454
        self.assertFalse('BZR_HOME' in os.environ)
 
3455
        # Make sure we know the definition of LINES: part of os.environ for
 
3456
        # tests.TestCase
 
3457
        self.assertTrue('LINES' in tests.isolated_environ)
 
3458
        self.assertEquals('25', tests.isolated_environ['LINES'])
 
3459
        self.assertEquals('25', os.environ['LINES'])
 
3460
 
 
3461
    def test_injecting_unknown_variable(self):
 
3462
        # BZR_HOME is known to be absent from os.environ
 
3463
        test = self.ScratchMonkey('test_me')
 
3464
        tests.override_os_environ(test, {'BZR_HOME': 'foo'})
 
3465
        self.assertEquals('foo', os.environ['BZR_HOME'])
 
3466
        tests.restore_os_environ(test)
 
3467
        self.assertFalse('BZR_HOME' in os.environ)
 
3468
 
 
3469
    def test_injecting_known_variable(self):
 
3470
        test = self.ScratchMonkey('test_me')
 
3471
        # LINES is known to be present in os.environ
 
3472
        tests.override_os_environ(test, {'LINES': '42'})
 
3473
        self.assertEquals('42', os.environ['LINES'])
 
3474
        tests.restore_os_environ(test)
 
3475
        self.assertEquals('25', os.environ['LINES'])
 
3476
 
 
3477
    def test_deleting_variable(self):
 
3478
        test = self.ScratchMonkey('test_me')
 
3479
        # LINES is known to be present in os.environ
 
3480
        tests.override_os_environ(test, {'LINES': None})
 
3481
        self.assertTrue('LINES' not in os.environ)
 
3482
        tests.restore_os_environ(test)
 
3483
        self.assertEquals('25', os.environ['LINES'])
 
3484
 
 
3485
 
 
3486
class TestDocTestSuiteIsolation(tests.TestCase):
 
3487
    """Test that `tests.DocTestSuite` isolates doc tests from os.environ.
 
3488
 
 
3489
    Since tests.TestCase alreay provides an isolation from os.environ, we use
 
3490
    the clean environment as a base for testing. To precisely capture the
 
3491
    isolation provided by tests.DocTestSuite, we use doctest.DocTestSuite to
 
3492
    compare against.
 
3493
 
 
3494
    We want to make sure `tests.DocTestSuite` respect `tests.isolated_environ`,
 
3495
    not `os.environ` so each test overrides it to suit its needs.
 
3496
 
 
3497
    """
 
3498
 
 
3499
    def get_doctest_suite_for_string(self, klass, string):
 
3500
        class Finder(doctest.DocTestFinder):
 
3501
 
 
3502
            def find(*args, **kwargs):
 
3503
                test = doctest.DocTestParser().get_doctest(
 
3504
                    string, {}, 'foo', 'foo.py', 0)
 
3505
                return [test]
 
3506
 
 
3507
        suite = klass(test_finder=Finder())
 
3508
        return suite
 
3509
 
 
3510
    def run_doctest_suite_for_string(self, klass, string):
 
3511
        suite = self.get_doctest_suite_for_string(klass, string)
 
3512
        output = StringIO()
 
3513
        result = tests.TextTestResult(output, 0, 1)
 
3514
        suite.run(result)
 
3515
        return result, output
 
3516
 
 
3517
    def assertDocTestStringSucceds(self, klass, string):
 
3518
        result, output = self.run_doctest_suite_for_string(klass, string)
 
3519
        if not result.wasStrictlySuccessful():
 
3520
            self.fail(output.getvalue())
 
3521
 
 
3522
    def assertDocTestStringFails(self, klass, string):
 
3523
        result, output = self.run_doctest_suite_for_string(klass, string)
 
3524
        if result.wasStrictlySuccessful():
 
3525
            self.fail(output.getvalue())
 
3526
 
 
3527
    def test_injected_variable(self):
 
3528
        self.overrideAttr(tests, 'isolated_environ', {'LINES': '42'})
 
3529
        test = """
 
3530
            >>> import os
 
3531
            >>> os.environ['LINES']
 
3532
            '42'
 
3533
            """
 
3534
        # doctest.DocTestSuite fails as it sees '25'
 
3535
        self.assertDocTestStringFails(doctest.DocTestSuite, test)
 
3536
        # tests.DocTestSuite sees '42'
 
3537
        self.assertDocTestStringSucceds(tests.IsolatedDocTestSuite, test)
 
3538
 
 
3539
    def test_deleted_variable(self):
 
3540
        self.overrideAttr(tests, 'isolated_environ', {'LINES': None})
 
3541
        test = """
 
3542
            >>> import os
 
3543
            >>> os.environ.get('LINES')
 
3544
            """
 
3545
        # doctest.DocTestSuite fails as it sees '25'
 
3546
        self.assertDocTestStringFails(doctest.DocTestSuite, test)
 
3547
        # tests.DocTestSuite sees None
 
3548
        self.assertDocTestStringSucceds(tests.IsolatedDocTestSuite, test)