1
# Copyright (C) 2005-2011 Canonical Ltd
3
# This program is free software; you can redistribute it and/or modify
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.
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
# GNU General Public License for more details.
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
"""Tests for the test framework."""
19
from cStringIO import StringIO
29
from testtools import (
30
ExtendedToOriginalDecorator,
33
from testtools.content import Content
34
from testtools.content_type import ContentType
35
from testtools.matchers import (
39
import testtools.testresult.doubles
59
from bzrlib.repofmt import (
62
from bzrlib.symbol_versioning import (
67
from bzrlib.tests import (
73
from bzrlib.trace import note, mutter
74
from bzrlib.transport import memory
77
def _test_ids(test_suite):
78
"""Get the ids for the tests in a test suite."""
79
return [t.id() for t in tests.iter_suite_tests(test_suite)]
82
class MetaTestLog(tests.TestCase):
84
def test_logging(self):
85
"""Test logs are captured when a test fails."""
86
self.log('a test message')
87
details = self.getDetails()
89
self.assertThat(log.content_type, Equals(ContentType(
90
"text", "plain", {"charset": "utf8"})))
91
self.assertThat(u"".join(log.iter_text()), Equals(self.get_log()))
92
self.assertThat(self.get_log(),
93
DocTestMatches(u"...a test message\n", doctest.ELLIPSIS))
96
class TestUnicodeFilename(tests.TestCase):
98
def test_probe_passes(self):
99
"""UnicodeFilename._probe passes."""
100
# We can't test much more than that because the behaviour depends
102
tests.UnicodeFilename._probe()
105
class TestTreeShape(tests.TestCaseInTempDir):
107
def test_unicode_paths(self):
108
self.requireFeature(tests.UnicodeFilename)
110
filename = u'hell\u00d8'
111
self.build_tree_contents([(filename, 'contents of hello')])
112
self.assertPathExists(filename)
115
class TestClassesAvailable(tests.TestCase):
116
"""As a convenience we expose Test* classes from bzrlib.tests"""
118
def test_test_case(self):
119
from bzrlib.tests import TestCase
121
def test_test_loader(self):
122
from bzrlib.tests import TestLoader
124
def test_test_suite(self):
125
from bzrlib.tests import TestSuite
128
class TestTransportScenarios(tests.TestCase):
129
"""A group of tests that test the transport implementation adaption core.
131
This is a meta test that the tests are applied to all available
134
This will be generalised in the future which is why it is in this
135
test file even though it is specific to transport tests at the moment.
138
def test_get_transport_permutations(self):
139
# this checks that get_test_permutations defined by the module is
140
# called by the get_transport_test_permutations function.
141
class MockModule(object):
142
def get_test_permutations(self):
143
return sample_permutation
144
sample_permutation = [(1,2), (3,4)]
145
from bzrlib.tests.per_transport import get_transport_test_permutations
146
self.assertEqual(sample_permutation,
147
get_transport_test_permutations(MockModule()))
149
def test_scenarios_include_all_modules(self):
150
# this checks that the scenario generator returns as many permutations
151
# as there are in all the registered transport modules - we assume if
152
# this matches its probably doing the right thing especially in
153
# combination with the tests for setting the right classes below.
154
from bzrlib.tests.per_transport import transport_test_permutations
155
from bzrlib.transport import _get_transport_modules
156
modules = _get_transport_modules()
157
permutation_count = 0
158
for module in modules:
160
permutation_count += len(reduce(getattr,
161
(module + ".get_test_permutations").split('.')[1:],
162
__import__(module))())
163
except errors.DependencyNotPresent:
165
scenarios = transport_test_permutations()
166
self.assertEqual(permutation_count, len(scenarios))
168
def test_scenarios_include_transport_class(self):
169
# This test used to know about all the possible transports and the
170
# order they were returned but that seems overly brittle (mbp
172
from bzrlib.tests.per_transport import transport_test_permutations
173
scenarios = transport_test_permutations()
174
# there are at least that many builtin transports
175
self.assertTrue(len(scenarios) > 6)
176
one_scenario = scenarios[0]
177
self.assertIsInstance(one_scenario[0], str)
178
self.assertTrue(issubclass(one_scenario[1]["transport_class"],
179
bzrlib.transport.Transport))
180
self.assertTrue(issubclass(one_scenario[1]["transport_server"],
181
bzrlib.transport.Server))
184
class TestBranchScenarios(tests.TestCase):
186
def test_scenarios(self):
187
# check that constructor parameters are passed through to the adapted
189
from bzrlib.tests.per_branch import make_scenarios
192
formats = [("c", "C"), ("d", "D")]
193
scenarios = make_scenarios(server1, server2, formats)
194
self.assertEqual(2, len(scenarios))
197
{'branch_format': 'c',
198
'bzrdir_format': 'C',
199
'transport_readonly_server': 'b',
200
'transport_server': 'a'}),
202
{'branch_format': 'd',
203
'bzrdir_format': 'D',
204
'transport_readonly_server': 'b',
205
'transport_server': 'a'})],
209
class TestBzrDirScenarios(tests.TestCase):
211
def test_scenarios(self):
212
# check that constructor parameters are passed through to the adapted
214
from bzrlib.tests.per_controldir import make_scenarios
219
scenarios = make_scenarios(vfs_factory, server1, server2, formats)
222
{'bzrdir_format': 'c',
223
'transport_readonly_server': 'b',
224
'transport_server': 'a',
225
'vfs_transport_factory': 'v'}),
227
{'bzrdir_format': 'd',
228
'transport_readonly_server': 'b',
229
'transport_server': 'a',
230
'vfs_transport_factory': 'v'})],
234
class TestRepositoryScenarios(tests.TestCase):
236
def test_formats_to_scenarios(self):
237
from bzrlib.tests.per_repository import formats_to_scenarios
238
formats = [("(c)", remote.RemoteRepositoryFormat()),
239
("(d)", repository.format_registry.get(
240
'Bazaar repository format 2a (needs bzr 1.16 or later)\n'))]
241
no_vfs_scenarios = formats_to_scenarios(formats, "server", "readonly",
243
vfs_scenarios = formats_to_scenarios(formats, "server", "readonly",
244
vfs_transport_factory="vfs")
245
# no_vfs generate scenarios without vfs_transport_factory
247
('RemoteRepositoryFormat(c)',
248
{'bzrdir_format': remote.RemoteBzrDirFormat(),
249
'repository_format': remote.RemoteRepositoryFormat(),
250
'transport_readonly_server': 'readonly',
251
'transport_server': 'server'}),
252
('RepositoryFormat2a(d)',
253
{'bzrdir_format': bzrdir.BzrDirMetaFormat1(),
254
'repository_format': groupcompress_repo.RepositoryFormat2a(),
255
'transport_readonly_server': 'readonly',
256
'transport_server': 'server'})]
257
self.assertEqual(expected, no_vfs_scenarios)
259
('RemoteRepositoryFormat(c)',
260
{'bzrdir_format': remote.RemoteBzrDirFormat(),
261
'repository_format': remote.RemoteRepositoryFormat(),
262
'transport_readonly_server': 'readonly',
263
'transport_server': 'server',
264
'vfs_transport_factory': 'vfs'}),
265
('RepositoryFormat2a(d)',
266
{'bzrdir_format': bzrdir.BzrDirMetaFormat1(),
267
'repository_format': groupcompress_repo.RepositoryFormat2a(),
268
'transport_readonly_server': 'readonly',
269
'transport_server': 'server',
270
'vfs_transport_factory': 'vfs'})],
274
class TestTestScenarioApplication(tests.TestCase):
275
"""Tests for the test adaption facilities."""
277
def test_apply_scenario(self):
278
from bzrlib.tests import apply_scenario
279
input_test = TestTestScenarioApplication("test_apply_scenario")
280
# setup two adapted tests
281
adapted_test1 = apply_scenario(input_test,
283
{"bzrdir_format":"bzr_format",
284
"repository_format":"repo_fmt",
285
"transport_server":"transport_server",
286
"transport_readonly_server":"readonly-server"}))
287
adapted_test2 = apply_scenario(input_test,
288
("new id 2", {"bzrdir_format":None}))
289
# input_test should have been altered.
290
self.assertRaises(AttributeError, getattr, input_test, "bzrdir_format")
291
# the new tests are mutually incompatible, ensuring it has
292
# made new ones, and unspecified elements in the scenario
293
# should not have been altered.
294
self.assertEqual("bzr_format", adapted_test1.bzrdir_format)
295
self.assertEqual("repo_fmt", adapted_test1.repository_format)
296
self.assertEqual("transport_server", adapted_test1.transport_server)
297
self.assertEqual("readonly-server",
298
adapted_test1.transport_readonly_server)
300
"bzrlib.tests.test_selftest.TestTestScenarioApplication."
301
"test_apply_scenario(new id)",
303
self.assertEqual(None, adapted_test2.bzrdir_format)
305
"bzrlib.tests.test_selftest.TestTestScenarioApplication."
306
"test_apply_scenario(new id 2)",
310
class TestInterRepositoryScenarios(tests.TestCase):
312
def test_scenarios(self):
313
# check that constructor parameters are passed through to the adapted
315
from bzrlib.tests.per_interrepository import make_scenarios
318
formats = [("C0", "C1", "C2", "C3"), ("D0", "D1", "D2", "D3")]
319
scenarios = make_scenarios(server1, server2, formats)
322
{'repository_format': 'C1',
323
'repository_format_to': 'C2',
324
'transport_readonly_server': 'b',
325
'transport_server': 'a',
326
'extra_setup': 'C3'}),
328
{'repository_format': 'D1',
329
'repository_format_to': 'D2',
330
'transport_readonly_server': 'b',
331
'transport_server': 'a',
332
'extra_setup': 'D3'})],
336
class TestWorkingTreeScenarios(tests.TestCase):
338
def test_scenarios(self):
339
# check that constructor parameters are passed through to the adapted
341
from bzrlib.tests.per_workingtree import make_scenarios
344
formats = [workingtree_4.WorkingTreeFormat4(),
345
workingtree_3.WorkingTreeFormat3(),]
346
scenarios = make_scenarios(server1, server2, formats)
348
('WorkingTreeFormat4',
349
{'bzrdir_format': formats[0]._matchingbzrdir,
350
'transport_readonly_server': 'b',
351
'transport_server': 'a',
352
'workingtree_format': formats[0]}),
353
('WorkingTreeFormat3',
354
{'bzrdir_format': formats[1]._matchingbzrdir,
355
'transport_readonly_server': 'b',
356
'transport_server': 'a',
357
'workingtree_format': formats[1]})],
361
class TestTreeScenarios(tests.TestCase):
363
def test_scenarios(self):
364
# the tree implementation scenario generator is meant to setup one
365
# instance for each working tree format, and one additional instance
366
# that will use the default wt format, but create a revision tree for
367
# the tests. this means that the wt ones should have the
368
# workingtree_to_test_tree attribute set to 'return_parameter' and the
369
# revision one set to revision_tree_from_workingtree.
371
from bzrlib.tests.per_tree import (
372
_dirstate_tree_from_workingtree,
377
revision_tree_from_workingtree
381
formats = [workingtree_4.WorkingTreeFormat4(),
382
workingtree_3.WorkingTreeFormat3(),]
383
scenarios = make_scenarios(server1, server2, formats)
384
self.assertEqual(7, len(scenarios))
385
default_wt_format = workingtree.format_registry.get_default()
386
wt4_format = workingtree_4.WorkingTreeFormat4()
387
wt5_format = workingtree_4.WorkingTreeFormat5()
388
expected_scenarios = [
389
('WorkingTreeFormat4',
390
{'bzrdir_format': formats[0]._matchingbzrdir,
391
'transport_readonly_server': 'b',
392
'transport_server': 'a',
393
'workingtree_format': formats[0],
394
'_workingtree_to_test_tree': return_parameter,
396
('WorkingTreeFormat3',
397
{'bzrdir_format': formats[1]._matchingbzrdir,
398
'transport_readonly_server': 'b',
399
'transport_server': 'a',
400
'workingtree_format': formats[1],
401
'_workingtree_to_test_tree': return_parameter,
404
{'_workingtree_to_test_tree': revision_tree_from_workingtree,
405
'bzrdir_format': default_wt_format._matchingbzrdir,
406
'transport_readonly_server': 'b',
407
'transport_server': 'a',
408
'workingtree_format': default_wt_format,
410
('DirStateRevisionTree,WT4',
411
{'_workingtree_to_test_tree': _dirstate_tree_from_workingtree,
412
'bzrdir_format': wt4_format._matchingbzrdir,
413
'transport_readonly_server': 'b',
414
'transport_server': 'a',
415
'workingtree_format': wt4_format,
417
('DirStateRevisionTree,WT5',
418
{'_workingtree_to_test_tree': _dirstate_tree_from_workingtree,
419
'bzrdir_format': wt5_format._matchingbzrdir,
420
'transport_readonly_server': 'b',
421
'transport_server': 'a',
422
'workingtree_format': wt5_format,
425
{'_workingtree_to_test_tree': preview_tree_pre,
426
'bzrdir_format': default_wt_format._matchingbzrdir,
427
'transport_readonly_server': 'b',
428
'transport_server': 'a',
429
'workingtree_format': default_wt_format}),
431
{'_workingtree_to_test_tree': preview_tree_post,
432
'bzrdir_format': default_wt_format._matchingbzrdir,
433
'transport_readonly_server': 'b',
434
'transport_server': 'a',
435
'workingtree_format': default_wt_format}),
437
self.assertEqual(expected_scenarios, scenarios)
440
class TestInterTreeScenarios(tests.TestCase):
441
"""A group of tests that test the InterTreeTestAdapter."""
443
def test_scenarios(self):
444
# check that constructor parameters are passed through to the adapted
446
# for InterTree tests we want the machinery to bring up two trees in
447
# each instance: the base one, and the one we are interacting with.
448
# because each optimiser can be direction specific, we need to test
449
# each optimiser in its chosen direction.
450
# unlike the TestProviderAdapter we dont want to automatically add a
451
# parameterized one for WorkingTree - the optimisers will tell us what
453
from bzrlib.tests.per_tree import (
456
from bzrlib.tests.per_intertree import (
459
from bzrlib.workingtree_3 import WorkingTreeFormat3
460
from bzrlib.workingtree_4 import WorkingTreeFormat4
461
input_test = TestInterTreeScenarios(
465
format1 = WorkingTreeFormat4()
466
format2 = WorkingTreeFormat3()
467
formats = [("1", str, format1, format2, "converter1"),
468
("2", int, format2, format1, "converter2")]
469
scenarios = make_scenarios(server1, server2, formats)
470
self.assertEqual(2, len(scenarios))
471
expected_scenarios = [
473
"bzrdir_format": format1._matchingbzrdir,
474
"intertree_class": formats[0][1],
475
"workingtree_format": formats[0][2],
476
"workingtree_format_to": formats[0][3],
477
"mutable_trees_to_test_trees": formats[0][4],
478
"_workingtree_to_test_tree": return_parameter,
479
"transport_server": server1,
480
"transport_readonly_server": server2,
483
"bzrdir_format": format2._matchingbzrdir,
484
"intertree_class": formats[1][1],
485
"workingtree_format": formats[1][2],
486
"workingtree_format_to": formats[1][3],
487
"mutable_trees_to_test_trees": formats[1][4],
488
"_workingtree_to_test_tree": return_parameter,
489
"transport_server": server1,
490
"transport_readonly_server": server2,
493
self.assertEqual(scenarios, expected_scenarios)
496
class TestTestCaseInTempDir(tests.TestCaseInTempDir):
498
def test_home_is_not_working(self):
499
self.assertNotEqual(self.test_dir, self.test_home_dir)
500
cwd = osutils.getcwd()
501
self.assertIsSameRealPath(self.test_dir, cwd)
502
self.assertIsSameRealPath(self.test_home_dir, os.environ['HOME'])
504
def test_assertEqualStat_equal(self):
505
from bzrlib.tests.test_dirstate import _FakeStat
506
self.build_tree(["foo"])
507
real = os.lstat("foo")
508
fake = _FakeStat(real.st_size, real.st_mtime, real.st_ctime,
509
real.st_dev, real.st_ino, real.st_mode)
510
self.assertEqualStat(real, fake)
512
def test_assertEqualStat_notequal(self):
513
self.build_tree(["foo", "longname"])
514
self.assertRaises(AssertionError, self.assertEqualStat,
515
os.lstat("foo"), os.lstat("longname"))
517
def test_failUnlessExists(self):
518
"""Deprecated failUnlessExists and failIfExists"""
519
self.applyDeprecated(
520
deprecated_in((2, 4)),
521
self.failUnlessExists, '.')
522
self.build_tree(['foo/', 'foo/bar'])
523
self.applyDeprecated(
524
deprecated_in((2, 4)),
525
self.failUnlessExists, 'foo/bar')
526
self.applyDeprecated(
527
deprecated_in((2, 4)),
528
self.failIfExists, 'foo/foo')
530
def test_assertPathExists(self):
531
self.assertPathExists('.')
532
self.build_tree(['foo/', 'foo/bar'])
533
self.assertPathExists('foo/bar')
534
self.assertPathDoesNotExist('foo/foo')
537
class TestTestCaseWithMemoryTransport(tests.TestCaseWithMemoryTransport):
539
def test_home_is_non_existant_dir_under_root(self):
540
"""The test_home_dir for TestCaseWithMemoryTransport is missing.
542
This is because TestCaseWithMemoryTransport is for tests that do not
543
need any disk resources: they should be hooked into bzrlib in such a
544
way that no global settings are being changed by the test (only a
545
few tests should need to do that), and having a missing dir as home is
546
an effective way to ensure that this is the case.
548
self.assertIsSameRealPath(
549
self.TEST_ROOT + "/MemoryTransportMissingHomeDir",
551
self.assertIsSameRealPath(self.test_home_dir, os.environ['HOME'])
553
def test_cwd_is_TEST_ROOT(self):
554
self.assertIsSameRealPath(self.test_dir, self.TEST_ROOT)
555
cwd = osutils.getcwd()
556
self.assertIsSameRealPath(self.test_dir, cwd)
558
def test_BZR_HOME_and_HOME_are_bytestrings(self):
559
"""The $BZR_HOME and $HOME environment variables should not be unicode.
561
See https://bugs.launchpad.net/bzr/+bug/464174
563
self.assertIsInstance(os.environ['BZR_HOME'], str)
564
self.assertIsInstance(os.environ['HOME'], str)
566
def test_make_branch_and_memory_tree(self):
567
"""In TestCaseWithMemoryTransport we should not make the branch on disk.
569
This is hard to comprehensively robustly test, so we settle for making
570
a branch and checking no directory was created at its relpath.
572
tree = self.make_branch_and_memory_tree('dir')
573
# Guard against regression into MemoryTransport leaking
574
# files to disk instead of keeping them in memory.
575
self.assertFalse(osutils.lexists('dir'))
576
self.assertIsInstance(tree, memorytree.MemoryTree)
578
def test_make_branch_and_memory_tree_with_format(self):
579
"""make_branch_and_memory_tree should accept a format option."""
580
format = bzrdir.BzrDirMetaFormat1()
581
format.repository_format = repository.format_registry.get_default()
582
tree = self.make_branch_and_memory_tree('dir', format=format)
583
# Guard against regression into MemoryTransport leaking
584
# files to disk instead of keeping them in memory.
585
self.assertFalse(osutils.lexists('dir'))
586
self.assertIsInstance(tree, memorytree.MemoryTree)
587
self.assertEqual(format.repository_format.__class__,
588
tree.branch.repository._format.__class__)
590
def test_make_branch_builder(self):
591
builder = self.make_branch_builder('dir')
592
self.assertIsInstance(builder, branchbuilder.BranchBuilder)
593
# Guard against regression into MemoryTransport leaking
594
# files to disk instead of keeping them in memory.
595
self.assertFalse(osutils.lexists('dir'))
597
def test_make_branch_builder_with_format(self):
598
# Use a repo layout that doesn't conform to a 'named' layout, to ensure
599
# that the format objects are used.
600
format = bzrdir.BzrDirMetaFormat1()
601
repo_format = repository.format_registry.get_default()
602
format.repository_format = repo_format
603
builder = self.make_branch_builder('dir', format=format)
604
the_branch = builder.get_branch()
605
# Guard against regression into MemoryTransport leaking
606
# files to disk instead of keeping them in memory.
607
self.assertFalse(osutils.lexists('dir'))
608
self.assertEqual(format.repository_format.__class__,
609
the_branch.repository._format.__class__)
610
self.assertEqual(repo_format.get_format_string(),
611
self.get_transport().get_bytes(
612
'dir/.bzr/repository/format'))
614
def test_make_branch_builder_with_format_name(self):
615
builder = self.make_branch_builder('dir', format='knit')
616
the_branch = builder.get_branch()
617
# Guard against regression into MemoryTransport leaking
618
# files to disk instead of keeping them in memory.
619
self.assertFalse(osutils.lexists('dir'))
620
dir_format = bzrdir.format_registry.make_bzrdir('knit')
621
self.assertEqual(dir_format.repository_format.__class__,
622
the_branch.repository._format.__class__)
623
self.assertEqual('Bazaar-NG Knit Repository Format 1',
624
self.get_transport().get_bytes(
625
'dir/.bzr/repository/format'))
627
def test_dangling_locks_cause_failures(self):
628
class TestDanglingLock(tests.TestCaseWithMemoryTransport):
629
def test_function(self):
630
t = self.get_transport('.')
631
l = lockdir.LockDir(t, 'lock')
634
test = TestDanglingLock('test_function')
636
total_failures = result.errors + result.failures
637
if self._lock_check_thorough:
638
self.assertEqual(1, len(total_failures))
640
# When _lock_check_thorough is disabled, then we don't trigger a
642
self.assertEqual(0, len(total_failures))
645
class TestTestCaseWithTransport(tests.TestCaseWithTransport):
646
"""Tests for the convenience functions TestCaseWithTransport introduces."""
648
def test_get_readonly_url_none(self):
649
from bzrlib.transport.readonly import ReadonlyTransportDecorator
650
self.vfs_transport_factory = memory.MemoryServer
651
self.transport_readonly_server = None
652
# calling get_readonly_transport() constructs a decorator on the url
654
url = self.get_readonly_url()
655
url2 = self.get_readonly_url('foo/bar')
656
t = transport.get_transport(url)
657
t2 = transport.get_transport(url2)
658
self.assertIsInstance(t, ReadonlyTransportDecorator)
659
self.assertIsInstance(t2, ReadonlyTransportDecorator)
660
self.assertEqual(t2.base[:-1], t.abspath('foo/bar'))
662
def test_get_readonly_url_http(self):
663
from bzrlib.tests.http_server import HttpServer
664
from bzrlib.transport.http import HttpTransportBase
665
self.transport_server = test_server.LocalURLServer
666
self.transport_readonly_server = HttpServer
667
# calling get_readonly_transport() gives us a HTTP server instance.
668
url = self.get_readonly_url()
669
url2 = self.get_readonly_url('foo/bar')
670
# the transport returned may be any HttpTransportBase subclass
671
t = transport.get_transport(url)
672
t2 = transport.get_transport(url2)
673
self.assertIsInstance(t, HttpTransportBase)
674
self.assertIsInstance(t2, HttpTransportBase)
675
self.assertEqual(t2.base[:-1], t.abspath('foo/bar'))
677
def test_is_directory(self):
678
"""Test assertIsDirectory assertion"""
679
t = self.get_transport()
680
self.build_tree(['a_dir/', 'a_file'], transport=t)
681
self.assertIsDirectory('a_dir', t)
682
self.assertRaises(AssertionError, self.assertIsDirectory, 'a_file', t)
683
self.assertRaises(AssertionError, self.assertIsDirectory, 'not_here', t)
685
def test_make_branch_builder(self):
686
builder = self.make_branch_builder('dir')
687
rev_id = builder.build_commit()
688
self.assertPathExists('dir')
689
a_dir = bzrdir.BzrDir.open('dir')
690
self.assertRaises(errors.NoWorkingTree, a_dir.open_workingtree)
691
a_branch = a_dir.open_branch()
692
builder_branch = builder.get_branch()
693
self.assertEqual(a_branch.base, builder_branch.base)
694
self.assertEqual((1, rev_id), builder_branch.last_revision_info())
695
self.assertEqual((1, rev_id), a_branch.last_revision_info())
698
class TestTestCaseTransports(tests.TestCaseWithTransport):
701
super(TestTestCaseTransports, self).setUp()
702
self.vfs_transport_factory = memory.MemoryServer
704
def test_make_bzrdir_preserves_transport(self):
705
t = self.get_transport()
706
result_bzrdir = self.make_bzrdir('subdir')
707
self.assertIsInstance(result_bzrdir.transport,
708
memory.MemoryTransport)
709
# should not be on disk, should only be in memory
710
self.assertPathDoesNotExist('subdir')
713
class TestChrootedTest(tests.ChrootedTestCase):
715
def test_root_is_root(self):
716
t = transport.get_transport(self.get_readonly_url())
718
self.assertEqual(url, t.clone('..').base)
721
class TestProfileResult(tests.TestCase):
723
def test_profiles_tests(self):
724
self.requireFeature(test_lsprof.LSProfFeature)
725
terminal = testtools.testresult.doubles.ExtendedTestResult()
726
result = tests.ProfileResult(terminal)
727
class Sample(tests.TestCase):
729
self.sample_function()
730
def sample_function(self):
734
case = terminal._events[0][1]
735
self.assertLength(1, case._benchcalls)
736
# We must be able to unpack it as the test reporting code wants
737
(_, _, _), stats = case._benchcalls[0]
738
self.assertTrue(callable(stats.pprint))
741
class TestTestResult(tests.TestCase):
743
def check_timing(self, test_case, expected_re):
744
result = bzrlib.tests.TextTestResult(self._log_file,
748
capture = testtools.testresult.doubles.ExtendedTestResult()
749
test_case.run(MultiTestResult(result, capture))
750
run_case = capture._events[0][1]
751
timed_string = result._testTimeString(run_case)
752
self.assertContainsRe(timed_string, expected_re)
754
def test_test_reporting(self):
755
class ShortDelayTestCase(tests.TestCase):
756
def test_short_delay(self):
758
def test_short_benchmark(self):
759
self.time(time.sleep, 0.003)
760
self.check_timing(ShortDelayTestCase('test_short_delay'),
762
# if a benchmark time is given, we now show just that time followed by
764
self.check_timing(ShortDelayTestCase('test_short_benchmark'),
767
def test_unittest_reporting_unittest_class(self):
768
# getting the time from a non-bzrlib test works ok
769
class ShortDelayTestCase(unittest.TestCase):
770
def test_short_delay(self):
772
self.check_timing(ShortDelayTestCase('test_short_delay'),
775
def _time_hello_world_encoding(self):
776
"""Profile two sleep calls
778
This is used to exercise the test framework.
780
self.time(unicode, 'hello', errors='replace')
781
self.time(unicode, 'world', errors='replace')
783
def test_lsprofiling(self):
784
"""Verbose test result prints lsprof statistics from test cases."""
785
self.requireFeature(test_lsprof.LSProfFeature)
786
result_stream = StringIO()
787
result = bzrlib.tests.VerboseTestResult(
792
# we want profile a call of some sort and check it is output by
793
# addSuccess. We dont care about addError or addFailure as they
794
# are not that interesting for performance tuning.
795
# make a new test instance that when run will generate a profile
796
example_test_case = TestTestResult("_time_hello_world_encoding")
797
example_test_case._gather_lsprof_in_benchmarks = True
798
# execute the test, which should succeed and record profiles
799
example_test_case.run(result)
800
# lsprofile_something()
801
# if this worked we want
802
# LSProf output for <built in function unicode> (['hello'], {'errors': 'replace'})
803
# CallCount Recursive Total(ms) Inline(ms) module:lineno(function)
804
# (the lsprof header)
805
# ... an arbitrary number of lines
806
# and the function call which is time.sleep.
807
# 1 0 ??? ??? ???(sleep)
808
# and then repeated but with 'world', rather than 'hello'.
809
# this should appear in the output stream of our test result.
810
output = result_stream.getvalue()
811
self.assertContainsRe(output,
812
r"LSProf output for <type 'unicode'>\(\('hello',\), {'errors': 'replace'}\)")
813
self.assertContainsRe(output,
814
r" *CallCount *Recursive *Total\(ms\) *Inline\(ms\) *module:lineno\(function\)\n")
815
self.assertContainsRe(output,
816
r"( +1 +0 +0\.\d+ +0\.\d+ +<method 'disable' of '_lsprof\.Profiler' objects>\n)?")
817
self.assertContainsRe(output,
818
r"LSProf output for <type 'unicode'>\(\('world',\), {'errors': 'replace'}\)\n")
820
def test_uses_time_from_testtools(self):
821
"""Test case timings in verbose results should use testtools times"""
823
class TimeAddedVerboseTestResult(tests.VerboseTestResult):
824
def startTest(self, test):
825
self.time(datetime.datetime.utcfromtimestamp(1.145))
826
super(TimeAddedVerboseTestResult, self).startTest(test)
827
def addSuccess(self, test):
828
self.time(datetime.datetime.utcfromtimestamp(51.147))
829
super(TimeAddedVerboseTestResult, self).addSuccess(test)
830
def report_tests_starting(self): pass
832
self.get_passing_test().run(TimeAddedVerboseTestResult(sio, 0, 2))
833
self.assertEndsWith(sio.getvalue(), "OK 50002ms\n")
835
def test_known_failure(self):
836
"""A KnownFailure being raised should trigger several result actions."""
837
class InstrumentedTestResult(tests.ExtendedTestResult):
838
def stopTestRun(self): pass
839
def report_tests_starting(self): pass
840
def report_known_failure(self, test, err=None, details=None):
841
self._call = test, 'known failure'
842
result = InstrumentedTestResult(None, None, None, None)
843
class Test(tests.TestCase):
844
def test_function(self):
845
raise tests.KnownFailure('failed!')
846
test = Test("test_function")
848
# it should invoke 'report_known_failure'.
849
self.assertEqual(2, len(result._call))
850
self.assertEqual(test.id(), result._call[0].id())
851
self.assertEqual('known failure', result._call[1])
852
# we dont introspec the traceback, if the rest is ok, it would be
853
# exceptional for it not to be.
854
# it should update the known_failure_count on the object.
855
self.assertEqual(1, result.known_failure_count)
856
# the result should be successful.
857
self.assertTrue(result.wasSuccessful())
859
def test_verbose_report_known_failure(self):
860
# verbose test output formatting
861
result_stream = StringIO()
862
result = bzrlib.tests.VerboseTestResult(
867
test = self.get_passing_test()
868
result.startTest(test)
869
prefix = len(result_stream.getvalue())
870
# the err parameter has the shape:
871
# (class, exception object, traceback)
872
# KnownFailures dont get their tracebacks shown though, so we
874
err = (tests.KnownFailure, tests.KnownFailure('foo'), None)
875
result.report_known_failure(test, err)
876
output = result_stream.getvalue()[prefix:]
877
lines = output.splitlines()
878
self.assertContainsRe(lines[0], r'XFAIL *\d+ms$')
879
if sys.version_info > (2, 7):
880
self.expectFailure("_ExpectedFailure on 2.7 loses the message",
881
self.assertNotEqual, lines[1], ' ')
882
self.assertEqual(lines[1], ' foo')
883
self.assertEqual(2, len(lines))
885
def get_passing_test(self):
886
"""Return a test object that can't be run usefully."""
889
return unittest.FunctionTestCase(passing_test)
891
def test_add_not_supported(self):
892
"""Test the behaviour of invoking addNotSupported."""
893
class InstrumentedTestResult(tests.ExtendedTestResult):
894
def stopTestRun(self): pass
895
def report_tests_starting(self): pass
896
def report_unsupported(self, test, feature):
897
self._call = test, feature
898
result = InstrumentedTestResult(None, None, None, None)
899
test = SampleTestCase('_test_pass')
900
feature = tests.Feature()
901
result.startTest(test)
902
result.addNotSupported(test, feature)
903
# it should invoke 'report_unsupported'.
904
self.assertEqual(2, len(result._call))
905
self.assertEqual(test, result._call[0])
906
self.assertEqual(feature, result._call[1])
907
# the result should be successful.
908
self.assertTrue(result.wasSuccessful())
909
# it should record the test against a count of tests not run due to
911
self.assertEqual(1, result.unsupported['Feature'])
912
# and invoking it again should increment that counter
913
result.addNotSupported(test, feature)
914
self.assertEqual(2, result.unsupported['Feature'])
916
def test_verbose_report_unsupported(self):
917
# verbose test output formatting
918
result_stream = StringIO()
919
result = bzrlib.tests.VerboseTestResult(
924
test = self.get_passing_test()
925
feature = tests.Feature()
926
result.startTest(test)
927
prefix = len(result_stream.getvalue())
928
result.report_unsupported(test, feature)
929
output = result_stream.getvalue()[prefix:]
930
lines = output.splitlines()
931
# We don't check for the final '0ms' since it may fail on slow hosts
932
self.assertStartsWith(lines[0], 'NODEP')
933
self.assertEqual(lines[1],
934
" The feature 'Feature' is not available.")
936
def test_unavailable_exception(self):
937
"""An UnavailableFeature being raised should invoke addNotSupported."""
938
class InstrumentedTestResult(tests.ExtendedTestResult):
939
def stopTestRun(self): pass
940
def report_tests_starting(self): pass
941
def addNotSupported(self, test, feature):
942
self._call = test, feature
943
result = InstrumentedTestResult(None, None, None, None)
944
feature = tests.Feature()
945
class Test(tests.TestCase):
946
def test_function(self):
947
raise tests.UnavailableFeature(feature)
948
test = Test("test_function")
950
# it should invoke 'addNotSupported'.
951
self.assertEqual(2, len(result._call))
952
self.assertEqual(test.id(), result._call[0].id())
953
self.assertEqual(feature, result._call[1])
954
# and not count as an error
955
self.assertEqual(0, result.error_count)
957
def test_strict_with_unsupported_feature(self):
958
result = bzrlib.tests.TextTestResult(self._log_file, descriptions=0,
960
test = self.get_passing_test()
961
feature = "Unsupported Feature"
962
result.addNotSupported(test, feature)
963
self.assertFalse(result.wasStrictlySuccessful())
964
self.assertEqual(None, result._extractBenchmarkTime(test))
966
def test_strict_with_known_failure(self):
967
result = bzrlib.tests.TextTestResult(self._log_file, descriptions=0,
969
test = self.get_passing_test()
970
err = (tests.KnownFailure, tests.KnownFailure('foo'), None)
971
result.addExpectedFailure(test, err)
972
self.assertFalse(result.wasStrictlySuccessful())
973
self.assertEqual(None, result._extractBenchmarkTime(test))
975
def test_strict_with_success(self):
976
result = bzrlib.tests.TextTestResult(self._log_file, descriptions=0,
978
test = self.get_passing_test()
979
result.addSuccess(test)
980
self.assertTrue(result.wasStrictlySuccessful())
981
self.assertEqual(None, result._extractBenchmarkTime(test))
983
def test_startTests(self):
984
"""Starting the first test should trigger startTests."""
985
class InstrumentedTestResult(tests.ExtendedTestResult):
987
def startTests(self): self.calls += 1
988
result = InstrumentedTestResult(None, None, None, None)
991
test = unittest.FunctionTestCase(test_function)
993
self.assertEquals(1, result.calls)
995
def test_startTests_only_once(self):
996
"""With multiple tests startTests should still only be called once"""
997
class InstrumentedTestResult(tests.ExtendedTestResult):
999
def startTests(self): self.calls += 1
1000
result = InstrumentedTestResult(None, None, None, None)
1001
suite = unittest.TestSuite([
1002
unittest.FunctionTestCase(lambda: None),
1003
unittest.FunctionTestCase(lambda: None)])
1005
self.assertEquals(1, result.calls)
1006
self.assertEquals(2, result.count)
1009
class TestUnicodeFilenameFeature(tests.TestCase):
1011
def test_probe_passes(self):
1012
"""UnicodeFilenameFeature._probe passes."""
1013
# We can't test much more than that because the behaviour depends
1015
tests.UnicodeFilenameFeature._probe()
1018
class TestRunner(tests.TestCase):
1020
def dummy_test(self):
1023
def run_test_runner(self, testrunner, test):
1024
"""Run suite in testrunner, saving global state and restoring it.
1026
This current saves and restores:
1027
TestCaseInTempDir.TEST_ROOT
1029
There should be no tests in this file that use
1030
bzrlib.tests.TextTestRunner without using this convenience method,
1031
because of our use of global state.
1033
old_root = tests.TestCaseInTempDir.TEST_ROOT
1035
tests.TestCaseInTempDir.TEST_ROOT = None
1036
return testrunner.run(test)
1038
tests.TestCaseInTempDir.TEST_ROOT = old_root
1040
def test_known_failure_failed_run(self):
1041
# run a test that generates a known failure which should be printed in
1042
# the final output when real failures occur.
1043
class Test(tests.TestCase):
1044
def known_failure_test(self):
1045
self.expectFailure('failed', self.assertTrue, False)
1046
test = unittest.TestSuite()
1047
test.addTest(Test("known_failure_test"))
1049
raise AssertionError('foo')
1050
test.addTest(unittest.FunctionTestCase(failing_test))
1052
runner = tests.TextTestRunner(stream=stream)
1053
result = self.run_test_runner(runner, test)
1054
lines = stream.getvalue().splitlines()
1055
self.assertContainsRe(stream.getvalue(),
1056
'(?sm)^bzr selftest.*$'
1058
'^======================================================================\n'
1059
'^FAIL: failing_test\n'
1060
'^----------------------------------------------------------------------\n'
1061
'Traceback \\(most recent call last\\):\n'
1062
' .*' # File .*, line .*, in failing_test' - but maybe not from .pyc
1063
' raise AssertionError\\(\'foo\'\\)\n'
1065
'^----------------------------------------------------------------------\n'
1067
'FAILED \\(failures=1, known_failure_count=1\\)'
1070
def test_known_failure_ok_run(self):
1071
# run a test that generates a known failure which should be printed in
1073
class Test(tests.TestCase):
1074
def known_failure_test(self):
1075
self.knownFailure("Never works...")
1076
test = Test("known_failure_test")
1078
runner = tests.TextTestRunner(stream=stream)
1079
result = self.run_test_runner(runner, test)
1080
self.assertContainsRe(stream.getvalue(),
1083
'Ran 1 test in .*\n'
1085
'OK \\(known_failures=1\\)\n')
1087
def test_unexpected_success_bad(self):
1088
class Test(tests.TestCase):
1089
def test_truth(self):
1090
self.expectFailure("No absolute truth", self.assertTrue, True)
1091
runner = tests.TextTestRunner(stream=StringIO())
1092
result = self.run_test_runner(runner, Test("test_truth"))
1093
self.assertContainsRe(runner.stream.getvalue(),
1095
"FAIL: \\S+\.test_truth\n"
1098
"\\s*(?:Text attachment: )?reason"
1104
"Ran 1 test in .*\n"
1106
"FAILED \\(failures=1\\)\n\\Z")
1108
def test_result_decorator(self):
1111
class LoggingDecorator(ExtendedToOriginalDecorator):
1112
def startTest(self, test):
1113
ExtendedToOriginalDecorator.startTest(self, test)
1114
calls.append('start')
1115
test = unittest.FunctionTestCase(lambda:None)
1117
runner = tests.TextTestRunner(stream=stream,
1118
result_decorators=[LoggingDecorator])
1119
result = self.run_test_runner(runner, test)
1120
self.assertLength(1, calls)
1122
def test_skipped_test(self):
1123
# run a test that is skipped, and check the suite as a whole still
1125
# skipping_test must be hidden in here so it's not run as a real test
1126
class SkippingTest(tests.TestCase):
1127
def skipping_test(self):
1128
raise tests.TestSkipped('test intentionally skipped')
1129
runner = tests.TextTestRunner(stream=self._log_file)
1130
test = SkippingTest("skipping_test")
1131
result = self.run_test_runner(runner, test)
1132
self.assertTrue(result.wasSuccessful())
1134
def test_skipped_from_setup(self):
1136
class SkippedSetupTest(tests.TestCase):
1139
calls.append('setUp')
1140
self.addCleanup(self.cleanup)
1141
raise tests.TestSkipped('skipped setup')
1143
def test_skip(self):
1144
self.fail('test reached')
1147
calls.append('cleanup')
1149
runner = tests.TextTestRunner(stream=self._log_file)
1150
test = SkippedSetupTest('test_skip')
1151
result = self.run_test_runner(runner, test)
1152
self.assertTrue(result.wasSuccessful())
1153
# Check if cleanup was called the right number of times.
1154
self.assertEqual(['setUp', 'cleanup'], calls)
1156
def test_skipped_from_test(self):
1158
class SkippedTest(tests.TestCase):
1161
tests.TestCase.setUp(self)
1162
calls.append('setUp')
1163
self.addCleanup(self.cleanup)
1165
def test_skip(self):
1166
raise tests.TestSkipped('skipped test')
1169
calls.append('cleanup')
1171
runner = tests.TextTestRunner(stream=self._log_file)
1172
test = SkippedTest('test_skip')
1173
result = self.run_test_runner(runner, test)
1174
self.assertTrue(result.wasSuccessful())
1175
# Check if cleanup was called the right number of times.
1176
self.assertEqual(['setUp', 'cleanup'], calls)
1178
def test_not_applicable(self):
1179
# run a test that is skipped because it's not applicable
1180
class Test(tests.TestCase):
1181
def not_applicable_test(self):
1182
raise tests.TestNotApplicable('this test never runs')
1184
runner = tests.TextTestRunner(stream=out, verbosity=2)
1185
test = Test("not_applicable_test")
1186
result = self.run_test_runner(runner, test)
1187
self._log_file.write(out.getvalue())
1188
self.assertTrue(result.wasSuccessful())
1189
self.assertTrue(result.wasStrictlySuccessful())
1190
self.assertContainsRe(out.getvalue(),
1191
r'(?m)not_applicable_test * N/A')
1192
self.assertContainsRe(out.getvalue(),
1193
r'(?m)^ this test never runs')
1195
def test_unsupported_features_listed(self):
1196
"""When unsupported features are encountered they are detailed."""
1197
class Feature1(tests.Feature):
1198
def _probe(self): return False
1199
class Feature2(tests.Feature):
1200
def _probe(self): return False
1201
# create sample tests
1202
test1 = SampleTestCase('_test_pass')
1203
test1._test_needs_features = [Feature1()]
1204
test2 = SampleTestCase('_test_pass')
1205
test2._test_needs_features = [Feature2()]
1206
test = unittest.TestSuite()
1210
runner = tests.TextTestRunner(stream=stream)
1211
result = self.run_test_runner(runner, test)
1212
lines = stream.getvalue().splitlines()
1215
"Missing feature 'Feature1' skipped 1 tests.",
1216
"Missing feature 'Feature2' skipped 1 tests.",
1220
def test_verbose_test_count(self):
1221
"""A verbose test run reports the right test count at the start"""
1222
suite = TestUtil.TestSuite([
1223
unittest.FunctionTestCase(lambda:None),
1224
unittest.FunctionTestCase(lambda:None)])
1225
self.assertEqual(suite.countTestCases(), 2)
1227
runner = tests.TextTestRunner(stream=stream, verbosity=2)
1228
# Need to use the CountingDecorator as that's what sets num_tests
1229
result = self.run_test_runner(runner, tests.CountingDecorator(suite))
1230
self.assertStartsWith(stream.getvalue(), "running 2 tests")
1232
def test_startTestRun(self):
1233
"""run should call result.startTestRun()"""
1235
class LoggingDecorator(ExtendedToOriginalDecorator):
1236
def startTestRun(self):
1237
ExtendedToOriginalDecorator.startTestRun(self)
1238
calls.append('startTestRun')
1239
test = unittest.FunctionTestCase(lambda:None)
1241
runner = tests.TextTestRunner(stream=stream,
1242
result_decorators=[LoggingDecorator])
1243
result = self.run_test_runner(runner, test)
1244
self.assertLength(1, calls)
1246
def test_stopTestRun(self):
1247
"""run should call result.stopTestRun()"""
1249
class LoggingDecorator(ExtendedToOriginalDecorator):
1250
def stopTestRun(self):
1251
ExtendedToOriginalDecorator.stopTestRun(self)
1252
calls.append('stopTestRun')
1253
test = unittest.FunctionTestCase(lambda:None)
1255
runner = tests.TextTestRunner(stream=stream,
1256
result_decorators=[LoggingDecorator])
1257
result = self.run_test_runner(runner, test)
1258
self.assertLength(1, calls)
1260
def test_unicode_test_output_on_ascii_stream(self):
1261
"""Showing results should always succeed even on an ascii console"""
1262
class FailureWithUnicode(tests.TestCase):
1263
def test_log_unicode(self):
1265
self.fail("Now print that log!")
1267
self.overrideAttr(osutils, "get_terminal_encoding",
1268
lambda trace=False: "ascii")
1269
result = self.run_test_runner(tests.TextTestRunner(stream=out),
1270
FailureWithUnicode("test_log_unicode"))
1271
self.assertContainsRe(out.getvalue(),
1272
"(?:Text attachment: )?log"
1274
"\d+\.\d+ \\\\u2606"
1278
class SampleTestCase(tests.TestCase):
1280
def _test_pass(self):
1283
class _TestException(Exception):
1287
class TestTestCase(tests.TestCase):
1288
"""Tests that test the core bzrlib TestCase."""
1290
def test_assertLength_matches_empty(self):
1292
self.assertLength(0, a_list)
1294
def test_assertLength_matches_nonempty(self):
1296
self.assertLength(3, a_list)
1298
def test_assertLength_fails_different(self):
1300
self.assertRaises(AssertionError, self.assertLength, 1, a_list)
1302
def test_assertLength_shows_sequence_in_failure(self):
1304
exception = self.assertRaises(AssertionError, self.assertLength, 2,
1306
self.assertEqual('Incorrect length: wanted 2, got 3 for [1, 2, 3]',
1309
def test_base_setUp_not_called_causes_failure(self):
1310
class TestCaseWithBrokenSetUp(tests.TestCase):
1312
pass # does not call TestCase.setUp
1315
test = TestCaseWithBrokenSetUp('test_foo')
1316
result = unittest.TestResult()
1318
self.assertFalse(result.wasSuccessful())
1319
self.assertEqual(1, result.testsRun)
1321
def test_base_tearDown_not_called_causes_failure(self):
1322
class TestCaseWithBrokenTearDown(tests.TestCase):
1324
pass # does not call TestCase.tearDown
1327
test = TestCaseWithBrokenTearDown('test_foo')
1328
result = unittest.TestResult()
1330
self.assertFalse(result.wasSuccessful())
1331
self.assertEqual(1, result.testsRun)
1333
def test_debug_flags_sanitised(self):
1334
"""The bzrlib debug flags should be sanitised by setUp."""
1335
if 'allow_debug' in tests.selftest_debug_flags:
1336
raise tests.TestNotApplicable(
1337
'-Eallow_debug option prevents debug flag sanitisation')
1338
# we could set something and run a test that will check
1339
# it gets santised, but this is probably sufficient for now:
1340
# if someone runs the test with -Dsomething it will error.
1342
if self._lock_check_thorough:
1343
flags.add('strict_locks')
1344
self.assertEqual(flags, bzrlib.debug.debug_flags)
1346
def change_selftest_debug_flags(self, new_flags):
1347
self.overrideAttr(tests, 'selftest_debug_flags', set(new_flags))
1349
def test_allow_debug_flag(self):
1350
"""The -Eallow_debug flag prevents bzrlib.debug.debug_flags from being
1351
sanitised (i.e. cleared) before running a test.
1353
self.change_selftest_debug_flags(set(['allow_debug']))
1354
bzrlib.debug.debug_flags = set(['a-flag'])
1355
class TestThatRecordsFlags(tests.TestCase):
1356
def test_foo(nested_self):
1357
self.flags = set(bzrlib.debug.debug_flags)
1358
test = TestThatRecordsFlags('test_foo')
1359
test.run(self.make_test_result())
1360
flags = set(['a-flag'])
1361
if 'disable_lock_checks' not in tests.selftest_debug_flags:
1362
flags.add('strict_locks')
1363
self.assertEqual(flags, self.flags)
1365
def test_disable_lock_checks(self):
1366
"""The -Edisable_lock_checks flag disables thorough checks."""
1367
class TestThatRecordsFlags(tests.TestCase):
1368
def test_foo(nested_self):
1369
self.flags = set(bzrlib.debug.debug_flags)
1370
self.test_lock_check_thorough = nested_self._lock_check_thorough
1371
self.change_selftest_debug_flags(set())
1372
test = TestThatRecordsFlags('test_foo')
1373
test.run(self.make_test_result())
1374
# By default we do strict lock checking and thorough lock/unlock
1376
self.assertTrue(self.test_lock_check_thorough)
1377
self.assertEqual(set(['strict_locks']), self.flags)
1378
# Now set the disable_lock_checks flag, and show that this changed.
1379
self.change_selftest_debug_flags(set(['disable_lock_checks']))
1380
test = TestThatRecordsFlags('test_foo')
1381
test.run(self.make_test_result())
1382
self.assertFalse(self.test_lock_check_thorough)
1383
self.assertEqual(set(), self.flags)
1385
def test_this_fails_strict_lock_check(self):
1386
class TestThatRecordsFlags(tests.TestCase):
1387
def test_foo(nested_self):
1388
self.flags1 = set(bzrlib.debug.debug_flags)
1389
self.thisFailsStrictLockCheck()
1390
self.flags2 = set(bzrlib.debug.debug_flags)
1391
# Make sure lock checking is active
1392
self.change_selftest_debug_flags(set())
1393
test = TestThatRecordsFlags('test_foo')
1394
test.run(self.make_test_result())
1395
self.assertEqual(set(['strict_locks']), self.flags1)
1396
self.assertEqual(set(), self.flags2)
1398
def test_debug_flags_restored(self):
1399
"""The bzrlib debug flags should be restored to their original state
1400
after the test was run, even if allow_debug is set.
1402
self.change_selftest_debug_flags(set(['allow_debug']))
1403
# Now run a test that modifies debug.debug_flags.
1404
bzrlib.debug.debug_flags = set(['original-state'])
1405
class TestThatModifiesFlags(tests.TestCase):
1407
bzrlib.debug.debug_flags = set(['modified'])
1408
test = TestThatModifiesFlags('test_foo')
1409
test.run(self.make_test_result())
1410
self.assertEqual(set(['original-state']), bzrlib.debug.debug_flags)
1412
def make_test_result(self):
1413
"""Get a test result that writes to the test log file."""
1414
return tests.TextTestResult(self._log_file, descriptions=0, verbosity=1)
1416
def inner_test(self):
1417
# the inner child test
1420
def outer_child(self):
1421
# the outer child test
1423
self.inner_test = TestTestCase("inner_child")
1424
result = self.make_test_result()
1425
self.inner_test.run(result)
1426
note("outer finish")
1427
self.addCleanup(osutils.delete_any, self._log_file_name)
1429
def test_trace_nesting(self):
1430
# this tests that each test case nests its trace facility correctly.
1431
# we do this by running a test case manually. That test case (A)
1432
# should setup a new log, log content to it, setup a child case (B),
1433
# which should log independently, then case (A) should log a trailer
1435
# we do two nested children so that we can verify the state of the
1436
# logs after the outer child finishes is correct, which a bad clean
1437
# up routine in tearDown might trigger a fault in our test with only
1438
# one child, we should instead see the bad result inside our test with
1440
# the outer child test
1441
original_trace = bzrlib.trace._trace_file
1442
outer_test = TestTestCase("outer_child")
1443
result = self.make_test_result()
1444
outer_test.run(result)
1445
self.assertEqual(original_trace, bzrlib.trace._trace_file)
1447
def method_that_times_a_bit_twice(self):
1448
# call self.time twice to ensure it aggregates
1449
self.time(time.sleep, 0.007)
1450
self.time(time.sleep, 0.007)
1452
def test_time_creates_benchmark_in_result(self):
1453
"""Test that the TestCase.time() method accumulates a benchmark time."""
1454
sample_test = TestTestCase("method_that_times_a_bit_twice")
1455
output_stream = StringIO()
1456
result = bzrlib.tests.VerboseTestResult(
1460
sample_test.run(result)
1461
self.assertContainsRe(
1462
output_stream.getvalue(),
1465
def test_hooks_sanitised(self):
1466
"""The bzrlib hooks should be sanitised by setUp."""
1467
# Note this test won't fail with hooks that the core library doesn't
1468
# use - but it trigger with a plugin that adds hooks, so its still a
1469
# useful warning in that case.
1470
self.assertEqual(bzrlib.branch.BranchHooks(), bzrlib.branch.Branch.hooks)
1472
bzrlib.smart.server.SmartServerHooks(),
1473
bzrlib.smart.server.SmartTCPServer.hooks)
1475
bzrlib.commands.CommandHooks(), bzrlib.commands.Command.hooks)
1477
def test__gather_lsprof_in_benchmarks(self):
1478
"""When _gather_lsprof_in_benchmarks is on, accumulate profile data.
1480
Each self.time() call is individually and separately profiled.
1482
self.requireFeature(test_lsprof.LSProfFeature)
1483
# overrides the class member with an instance member so no cleanup
1485
self._gather_lsprof_in_benchmarks = True
1486
self.time(time.sleep, 0.000)
1487
self.time(time.sleep, 0.003)
1488
self.assertEqual(2, len(self._benchcalls))
1489
self.assertEqual((time.sleep, (0.000,), {}), self._benchcalls[0][0])
1490
self.assertEqual((time.sleep, (0.003,), {}), self._benchcalls[1][0])
1491
self.assertIsInstance(self._benchcalls[0][1], bzrlib.lsprof.Stats)
1492
self.assertIsInstance(self._benchcalls[1][1], bzrlib.lsprof.Stats)
1493
del self._benchcalls[:]
1495
def test_knownFailure(self):
1496
"""Self.knownFailure() should raise a KnownFailure exception."""
1497
self.assertRaises(tests.KnownFailure, self.knownFailure, "A Failure")
1499
def test_open_bzrdir_safe_roots(self):
1500
# even a memory transport should fail to open when its url isn't
1502
# Manually set one up (TestCase doesn't and shouldn't provide magic
1504
transport_server = memory.MemoryServer()
1505
transport_server.start_server()
1506
self.addCleanup(transport_server.stop_server)
1507
t = transport.get_transport(transport_server.get_url())
1508
bzrdir.BzrDir.create(t.base)
1509
self.assertRaises(errors.BzrError,
1510
bzrdir.BzrDir.open_from_transport, t)
1511
# But if we declare this as safe, we can open the bzrdir.
1512
self.permit_url(t.base)
1513
self._bzr_selftest_roots.append(t.base)
1514
bzrdir.BzrDir.open_from_transport(t)
1516
def test_requireFeature_available(self):
1517
"""self.requireFeature(available) is a no-op."""
1518
class Available(tests.Feature):
1519
def _probe(self):return True
1520
feature = Available()
1521
self.requireFeature(feature)
1523
def test_requireFeature_unavailable(self):
1524
"""self.requireFeature(unavailable) raises UnavailableFeature."""
1525
class Unavailable(tests.Feature):
1526
def _probe(self):return False
1527
feature = Unavailable()
1528
self.assertRaises(tests.UnavailableFeature,
1529
self.requireFeature, feature)
1531
def test_run_no_parameters(self):
1532
test = SampleTestCase('_test_pass')
1535
def test_run_enabled_unittest_result(self):
1536
"""Test we revert to regular behaviour when the test is enabled."""
1537
test = SampleTestCase('_test_pass')
1538
class EnabledFeature(object):
1539
def available(self):
1541
test._test_needs_features = [EnabledFeature()]
1542
result = unittest.TestResult()
1544
self.assertEqual(1, result.testsRun)
1545
self.assertEqual([], result.errors)
1546
self.assertEqual([], result.failures)
1548
def test_run_disabled_unittest_result(self):
1549
"""Test our compatability for disabled tests with unittest results."""
1550
test = SampleTestCase('_test_pass')
1551
class DisabledFeature(object):
1552
def available(self):
1554
test._test_needs_features = [DisabledFeature()]
1555
result = unittest.TestResult()
1557
self.assertEqual(1, result.testsRun)
1558
self.assertEqual([], result.errors)
1559
self.assertEqual([], result.failures)
1561
def test_run_disabled_supporting_result(self):
1562
"""Test disabled tests behaviour with support aware results."""
1563
test = SampleTestCase('_test_pass')
1564
class DisabledFeature(object):
1565
def __eq__(self, other):
1566
return isinstance(other, DisabledFeature)
1567
def available(self):
1569
the_feature = DisabledFeature()
1570
test._test_needs_features = [the_feature]
1571
class InstrumentedTestResult(unittest.TestResult):
1573
unittest.TestResult.__init__(self)
1575
def startTest(self, test):
1576
self.calls.append(('startTest', test))
1577
def stopTest(self, test):
1578
self.calls.append(('stopTest', test))
1579
def addNotSupported(self, test, feature):
1580
self.calls.append(('addNotSupported', test, feature))
1581
result = InstrumentedTestResult()
1583
case = result.calls[0][1]
1585
('startTest', case),
1586
('addNotSupported', case, the_feature),
1591
def test_start_server_registers_url(self):
1592
transport_server = memory.MemoryServer()
1593
# A little strict, but unlikely to be changed soon.
1594
self.assertEqual([], self._bzr_selftest_roots)
1595
self.start_server(transport_server)
1596
self.assertSubset([transport_server.get_url()],
1597
self._bzr_selftest_roots)
1599
def test_assert_list_raises_on_generator(self):
1600
def generator_which_will_raise():
1601
# This will not raise until after the first yield
1603
raise _TestException()
1605
e = self.assertListRaises(_TestException, generator_which_will_raise)
1606
self.assertIsInstance(e, _TestException)
1608
e = self.assertListRaises(Exception, generator_which_will_raise)
1609
self.assertIsInstance(e, _TestException)
1611
def test_assert_list_raises_on_plain(self):
1612
def plain_exception():
1613
raise _TestException()
1616
e = self.assertListRaises(_TestException, plain_exception)
1617
self.assertIsInstance(e, _TestException)
1619
e = self.assertListRaises(Exception, plain_exception)
1620
self.assertIsInstance(e, _TestException)
1622
def test_assert_list_raises_assert_wrong_exception(self):
1623
class _NotTestException(Exception):
1626
def wrong_exception():
1627
raise _NotTestException()
1629
def wrong_exception_generator():
1632
raise _NotTestException()
1634
# Wrong exceptions are not intercepted
1635
self.assertRaises(_NotTestException,
1636
self.assertListRaises, _TestException, wrong_exception)
1637
self.assertRaises(_NotTestException,
1638
self.assertListRaises, _TestException, wrong_exception_generator)
1640
def test_assert_list_raises_no_exception(self):
1644
def success_generator():
1648
self.assertRaises(AssertionError,
1649
self.assertListRaises, _TestException, success)
1651
self.assertRaises(AssertionError,
1652
self.assertListRaises, _TestException, success_generator)
1654
def test_overrideAttr_without_value(self):
1655
self.test_attr = 'original' # Define a test attribute
1656
obj = self # Make 'obj' visible to the embedded test
1657
class Test(tests.TestCase):
1660
tests.TestCase.setUp(self)
1661
self.orig = self.overrideAttr(obj, 'test_attr')
1663
def test_value(self):
1664
self.assertEqual('original', self.orig)
1665
self.assertEqual('original', obj.test_attr)
1666
obj.test_attr = 'modified'
1667
self.assertEqual('modified', obj.test_attr)
1669
test = Test('test_value')
1670
test.run(unittest.TestResult())
1671
self.assertEqual('original', obj.test_attr)
1673
def test_overrideAttr_with_value(self):
1674
self.test_attr = 'original' # Define a test attribute
1675
obj = self # Make 'obj' visible to the embedded test
1676
class Test(tests.TestCase):
1679
tests.TestCase.setUp(self)
1680
self.orig = self.overrideAttr(obj, 'test_attr', new='modified')
1682
def test_value(self):
1683
self.assertEqual('original', self.orig)
1684
self.assertEqual('modified', obj.test_attr)
1686
test = Test('test_value')
1687
test.run(unittest.TestResult())
1688
self.assertEqual('original', obj.test_attr)
1690
def test_recordCalls(self):
1691
from bzrlib.tests import test_selftest
1692
calls = self.recordCalls(
1693
test_selftest, '_add_numbers')
1694
self.assertEqual(test_selftest._add_numbers(2, 10),
1696
self.assertEquals(calls, [((2, 10), {})])
1699
def _add_numbers(a, b):
1703
class _MissingFeature(tests.Feature):
1706
missing_feature = _MissingFeature()
1709
def _get_test(name):
1710
"""Get an instance of a specific example test.
1712
We protect this in a function so that they don't auto-run in the test
1716
class ExampleTests(tests.TestCase):
1718
def test_fail(self):
1719
mutter('this was a failing test')
1720
self.fail('this test will fail')
1722
def test_error(self):
1723
mutter('this test errored')
1724
raise RuntimeError('gotcha')
1726
def test_missing_feature(self):
1727
mutter('missing the feature')
1728
self.requireFeature(missing_feature)
1730
def test_skip(self):
1731
mutter('this test will be skipped')
1732
raise tests.TestSkipped('reason')
1734
def test_success(self):
1735
mutter('this test succeeds')
1737
def test_xfail(self):
1738
mutter('test with expected failure')
1739
self.knownFailure('this_fails')
1741
def test_unexpected_success(self):
1742
mutter('test with unexpected success')
1743
self.expectFailure('should_fail', lambda: None)
1745
return ExampleTests(name)
1748
class TestTestCaseLogDetails(tests.TestCase):
1750
def _run_test(self, test_name):
1751
test = _get_test(test_name)
1752
result = testtools.TestResult()
1756
def test_fail_has_log(self):
1757
result = self._run_test('test_fail')
1758
self.assertEqual(1, len(result.failures))
1759
result_content = result.failures[0][1]
1760
self.assertContainsRe(result_content,
1761
'(?m)^(?:Text attachment: )?log(?:$|: )')
1762
self.assertContainsRe(result_content, 'this was a failing test')
1764
def test_error_has_log(self):
1765
result = self._run_test('test_error')
1766
self.assertEqual(1, len(result.errors))
1767
result_content = result.errors[0][1]
1768
self.assertContainsRe(result_content,
1769
'(?m)^(?:Text attachment: )?log(?:$|: )')
1770
self.assertContainsRe(result_content, 'this test errored')
1772
def test_skip_has_no_log(self):
1773
result = self._run_test('test_skip')
1774
self.assertEqual(['reason'], result.skip_reasons.keys())
1775
skips = result.skip_reasons['reason']
1776
self.assertEqual(1, len(skips))
1778
self.assertFalse('log' in test.getDetails())
1780
def test_missing_feature_has_no_log(self):
1781
# testtools doesn't know about addNotSupported, so it just gets
1782
# considered as a skip
1783
result = self._run_test('test_missing_feature')
1784
self.assertEqual([missing_feature], result.skip_reasons.keys())
1785
skips = result.skip_reasons[missing_feature]
1786
self.assertEqual(1, len(skips))
1788
self.assertFalse('log' in test.getDetails())
1790
def test_xfail_has_no_log(self):
1791
result = self._run_test('test_xfail')
1792
self.assertEqual(1, len(result.expectedFailures))
1793
result_content = result.expectedFailures[0][1]
1794
self.assertNotContainsRe(result_content,
1795
'(?m)^(?:Text attachment: )?log(?:$|: )')
1796
self.assertNotContainsRe(result_content, 'test with expected failure')
1798
def test_unexpected_success_has_log(self):
1799
result = self._run_test('test_unexpected_success')
1800
self.assertEqual(1, len(result.unexpectedSuccesses))
1801
# Inconsistency, unexpectedSuccesses is a list of tests,
1802
# expectedFailures is a list of reasons?
1803
test = result.unexpectedSuccesses[0]
1804
details = test.getDetails()
1805
self.assertTrue('log' in details)
1808
class TestTestCloning(tests.TestCase):
1809
"""Tests that test cloning of TestCases (as used by multiply_tests)."""
1811
def test_cloned_testcase_does_not_share_details(self):
1812
"""A TestCase cloned with clone_test does not share mutable attributes
1813
such as details or cleanups.
1815
class Test(tests.TestCase):
1817
self.addDetail('foo', Content('text/plain', lambda: 'foo'))
1818
orig_test = Test('test_foo')
1819
cloned_test = tests.clone_test(orig_test, orig_test.id() + '(cloned)')
1820
orig_test.run(unittest.TestResult())
1821
self.assertEqual('foo', orig_test.getDetails()['foo'].iter_bytes())
1822
self.assertEqual(None, cloned_test.getDetails().get('foo'))
1824
def test_double_apply_scenario_preserves_first_scenario(self):
1825
"""Applying two levels of scenarios to a test preserves the attributes
1826
added by both scenarios.
1828
class Test(tests.TestCase):
1831
test = Test('test_foo')
1832
scenarios_x = [('x=1', {'x': 1}), ('x=2', {'x': 2})]
1833
scenarios_y = [('y=1', {'y': 1}), ('y=2', {'y': 2})]
1834
suite = tests.multiply_tests(test, scenarios_x, unittest.TestSuite())
1835
suite = tests.multiply_tests(suite, scenarios_y, unittest.TestSuite())
1836
all_tests = list(tests.iter_suite_tests(suite))
1837
self.assertLength(4, all_tests)
1838
all_xys = sorted((t.x, t.y) for t in all_tests)
1839
self.assertEqual([(1, 1), (1, 2), (2, 1), (2, 2)], all_xys)
1842
# NB: Don't delete this; it's not actually from 0.11!
1843
@deprecated_function(deprecated_in((0, 11, 0)))
1844
def sample_deprecated_function():
1845
"""A deprecated function to test applyDeprecated with."""
1849
def sample_undeprecated_function(a_param):
1850
"""A undeprecated function to test applyDeprecated with."""
1853
class ApplyDeprecatedHelper(object):
1854
"""A helper class for ApplyDeprecated tests."""
1856
@deprecated_method(deprecated_in((0, 11, 0)))
1857
def sample_deprecated_method(self, param_one):
1858
"""A deprecated method for testing with."""
1861
def sample_normal_method(self):
1862
"""A undeprecated method."""
1864
@deprecated_method(deprecated_in((0, 10, 0)))
1865
def sample_nested_deprecation(self):
1866
return sample_deprecated_function()
1869
class TestExtraAssertions(tests.TestCase):
1870
"""Tests for new test assertions in bzrlib test suite"""
1872
def test_assert_isinstance(self):
1873
self.assertIsInstance(2, int)
1874
self.assertIsInstance(u'', basestring)
1875
e = self.assertRaises(AssertionError, self.assertIsInstance, None, int)
1876
self.assertEquals(str(e),
1877
"None is an instance of <type 'NoneType'> rather than <type 'int'>")
1878
self.assertRaises(AssertionError, self.assertIsInstance, 23.3, int)
1879
e = self.assertRaises(AssertionError,
1880
self.assertIsInstance, None, int, "it's just not")
1881
self.assertEquals(str(e),
1882
"None is an instance of <type 'NoneType'> rather than <type 'int'>"
1885
def test_assertEndsWith(self):
1886
self.assertEndsWith('foo', 'oo')
1887
self.assertRaises(AssertionError, self.assertEndsWith, 'o', 'oo')
1889
def test_assertEqualDiff(self):
1890
e = self.assertRaises(AssertionError,
1891
self.assertEqualDiff, '', '\n')
1892
self.assertEquals(str(e),
1893
# Don't blink ! The '+' applies to the second string
1894
'first string is missing a final newline.\n+ \n')
1895
e = self.assertRaises(AssertionError,
1896
self.assertEqualDiff, '\n', '')
1897
self.assertEquals(str(e),
1898
# Don't blink ! The '-' applies to the second string
1899
'second string is missing a final newline.\n- \n')
1902
class TestDeprecations(tests.TestCase):
1904
def test_applyDeprecated_not_deprecated(self):
1905
sample_object = ApplyDeprecatedHelper()
1906
# calling an undeprecated callable raises an assertion
1907
self.assertRaises(AssertionError, self.applyDeprecated,
1908
deprecated_in((0, 11, 0)),
1909
sample_object.sample_normal_method)
1910
self.assertRaises(AssertionError, self.applyDeprecated,
1911
deprecated_in((0, 11, 0)),
1912
sample_undeprecated_function, "a param value")
1913
# calling a deprecated callable (function or method) with the wrong
1914
# expected deprecation fails.
1915
self.assertRaises(AssertionError, self.applyDeprecated,
1916
deprecated_in((0, 10, 0)),
1917
sample_object.sample_deprecated_method, "a param value")
1918
self.assertRaises(AssertionError, self.applyDeprecated,
1919
deprecated_in((0, 10, 0)),
1920
sample_deprecated_function)
1921
# calling a deprecated callable (function or method) with the right
1922
# expected deprecation returns the functions result.
1923
self.assertEqual("a param value",
1924
self.applyDeprecated(deprecated_in((0, 11, 0)),
1925
sample_object.sample_deprecated_method, "a param value"))
1926
self.assertEqual(2, self.applyDeprecated(deprecated_in((0, 11, 0)),
1927
sample_deprecated_function))
1928
# calling a nested deprecation with the wrong deprecation version
1929
# fails even if a deeper nested function was deprecated with the
1931
self.assertRaises(AssertionError, self.applyDeprecated,
1932
deprecated_in((0, 11, 0)), sample_object.sample_nested_deprecation)
1933
# calling a nested deprecation with the right deprecation value
1934
# returns the calls result.
1935
self.assertEqual(2, self.applyDeprecated(deprecated_in((0, 10, 0)),
1936
sample_object.sample_nested_deprecation))
1938
def test_callDeprecated(self):
1939
def testfunc(be_deprecated, result=None):
1940
if be_deprecated is True:
1941
symbol_versioning.warn('i am deprecated', DeprecationWarning,
1944
result = self.callDeprecated(['i am deprecated'], testfunc, True)
1945
self.assertIs(None, result)
1946
result = self.callDeprecated([], testfunc, False, 'result')
1947
self.assertEqual('result', result)
1948
self.callDeprecated(['i am deprecated'], testfunc, be_deprecated=True)
1949
self.callDeprecated([], testfunc, be_deprecated=False)
1952
class TestWarningTests(tests.TestCase):
1953
"""Tests for calling methods that raise warnings."""
1955
def test_callCatchWarnings(self):
1957
warnings.warn("this is your last warning")
1959
wlist, result = self.callCatchWarnings(meth, 1, 2)
1960
self.assertEquals(3, result)
1961
# would like just to compare them, but UserWarning doesn't implement
1964
self.assertIsInstance(w0, UserWarning)
1965
self.assertEquals("this is your last warning", str(w0))
1968
class TestConvenienceMakers(tests.TestCaseWithTransport):
1969
"""Test for the make_* convenience functions."""
1971
def test_make_branch_and_tree_with_format(self):
1972
# we should be able to supply a format to make_branch_and_tree
1973
self.make_branch_and_tree('a', format=bzrlib.bzrdir.BzrDirMetaFormat1())
1974
self.assertIsInstance(bzrlib.bzrdir.BzrDir.open('a')._format,
1975
bzrlib.bzrdir.BzrDirMetaFormat1)
1977
def test_make_branch_and_memory_tree(self):
1978
# we should be able to get a new branch and a mutable tree from
1979
# TestCaseWithTransport
1980
tree = self.make_branch_and_memory_tree('a')
1981
self.assertIsInstance(tree, bzrlib.memorytree.MemoryTree)
1983
def test_make_tree_for_local_vfs_backed_transport(self):
1984
# make_branch_and_tree has to use local branch and repositories
1985
# when the vfs transport and local disk are colocated, even if
1986
# a different transport is in use for url generation.
1987
self.transport_server = test_server.FakeVFATServer
1988
self.assertFalse(self.get_url('t1').startswith('file://'))
1989
tree = self.make_branch_and_tree('t1')
1990
base = tree.bzrdir.root_transport.base
1991
self.assertStartsWith(base, 'file://')
1992
self.assertEquals(tree.bzrdir.root_transport,
1993
tree.branch.bzrdir.root_transport)
1994
self.assertEquals(tree.bzrdir.root_transport,
1995
tree.branch.repository.bzrdir.root_transport)
1998
class SelfTestHelper(object):
2000
def run_selftest(self, **kwargs):
2001
"""Run selftest returning its output."""
2003
old_transport = bzrlib.tests.default_transport
2004
old_root = tests.TestCaseWithMemoryTransport.TEST_ROOT
2005
tests.TestCaseWithMemoryTransport.TEST_ROOT = None
2007
self.assertEqual(True, tests.selftest(stream=output, **kwargs))
2009
bzrlib.tests.default_transport = old_transport
2010
tests.TestCaseWithMemoryTransport.TEST_ROOT = old_root
2015
class TestSelftest(tests.TestCase, SelfTestHelper):
2016
"""Tests of bzrlib.tests.selftest."""
2018
def test_selftest_benchmark_parameter_invokes_test_suite__benchmark__(self):
2021
factory_called.append(True)
2022
return TestUtil.TestSuite()
2025
self.apply_redirected(out, err, None, bzrlib.tests.selftest,
2026
test_suite_factory=factory)
2027
self.assertEqual([True], factory_called)
2030
"""A test suite factory."""
2031
class Test(tests.TestCase):
2038
return TestUtil.TestSuite([Test("a"), Test("b"), Test("c")])
2040
def test_list_only(self):
2041
output = self.run_selftest(test_suite_factory=self.factory,
2043
self.assertEqual(3, len(output.readlines()))
2045
def test_list_only_filtered(self):
2046
output = self.run_selftest(test_suite_factory=self.factory,
2047
list_only=True, pattern="Test.b")
2048
self.assertEndsWith(output.getvalue(), "Test.b\n")
2049
self.assertLength(1, output.readlines())
2051
def test_list_only_excludes(self):
2052
output = self.run_selftest(test_suite_factory=self.factory,
2053
list_only=True, exclude_pattern="Test.b")
2054
self.assertNotContainsRe("Test.b", output.getvalue())
2055
self.assertLength(2, output.readlines())
2057
def test_lsprof_tests(self):
2058
self.requireFeature(test_lsprof.LSProfFeature)
2061
def __call__(test, result):
2063
def run(test, result):
2064
results.append(result)
2065
def countTestCases(self):
2067
self.run_selftest(test_suite_factory=Test, lsprof_tests=True)
2068
self.assertLength(1, results)
2069
self.assertIsInstance(results.pop(), ExtendedToOriginalDecorator)
2071
def test_random(self):
2072
# test randomising by listing a number of tests.
2073
output_123 = self.run_selftest(test_suite_factory=self.factory,
2074
list_only=True, random_seed="123")
2075
output_234 = self.run_selftest(test_suite_factory=self.factory,
2076
list_only=True, random_seed="234")
2077
self.assertNotEqual(output_123, output_234)
2078
# "Randominzing test order..\n\n
2079
self.assertLength(5, output_123.readlines())
2080
self.assertLength(5, output_234.readlines())
2082
def test_random_reuse_is_same_order(self):
2083
# test randomising by listing a number of tests.
2084
expected = self.run_selftest(test_suite_factory=self.factory,
2085
list_only=True, random_seed="123")
2086
repeated = self.run_selftest(test_suite_factory=self.factory,
2087
list_only=True, random_seed="123")
2088
self.assertEqual(expected.getvalue(), repeated.getvalue())
2090
def test_runner_class(self):
2091
self.requireFeature(features.subunit)
2092
from subunit import ProtocolTestCase
2093
stream = self.run_selftest(runner_class=tests.SubUnitBzrRunner,
2094
test_suite_factory=self.factory)
2095
test = ProtocolTestCase(stream)
2096
result = unittest.TestResult()
2098
self.assertEqual(3, result.testsRun)
2100
def test_starting_with_single_argument(self):
2101
output = self.run_selftest(test_suite_factory=self.factory,
2102
starting_with=['bzrlib.tests.test_selftest.Test.a'],
2104
self.assertEqual('bzrlib.tests.test_selftest.Test.a\n',
2107
def test_starting_with_multiple_argument(self):
2108
output = self.run_selftest(test_suite_factory=self.factory,
2109
starting_with=['bzrlib.tests.test_selftest.Test.a',
2110
'bzrlib.tests.test_selftest.Test.b'],
2112
self.assertEqual('bzrlib.tests.test_selftest.Test.a\n'
2113
'bzrlib.tests.test_selftest.Test.b\n',
2116
def check_transport_set(self, transport_server):
2117
captured_transport = []
2118
def seen_transport(a_transport):
2119
captured_transport.append(a_transport)
2120
class Capture(tests.TestCase):
2122
seen_transport(bzrlib.tests.default_transport)
2124
return TestUtil.TestSuite([Capture("a")])
2125
self.run_selftest(transport=transport_server, test_suite_factory=factory)
2126
self.assertEqual(transport_server, captured_transport[0])
2128
def test_transport_sftp(self):
2129
self.requireFeature(features.paramiko)
2130
from bzrlib.tests import stub_sftp
2131
self.check_transport_set(stub_sftp.SFTPAbsoluteServer)
2133
def test_transport_memory(self):
2134
self.check_transport_set(memory.MemoryServer)
2137
class TestSelftestWithIdList(tests.TestCaseInTempDir, SelfTestHelper):
2138
# Does IO: reads test.list
2140
def test_load_list(self):
2141
# Provide a list with one test - this test.
2142
test_id_line = '%s\n' % self.id()
2143
self.build_tree_contents([('test.list', test_id_line)])
2144
# And generate a list of the tests in the suite.
2145
stream = self.run_selftest(load_list='test.list', list_only=True)
2146
self.assertEqual(test_id_line, stream.getvalue())
2148
def test_load_unknown(self):
2149
# Provide a list with one test - this test.
2150
# And generate a list of the tests in the suite.
2151
err = self.assertRaises(errors.NoSuchFile, self.run_selftest,
2152
load_list='missing file name', list_only=True)
2155
class TestSubunitLogDetails(tests.TestCase, SelfTestHelper):
2157
_test_needs_features = [features.subunit]
2159
def run_subunit_stream(self, test_name):
2160
from subunit import ProtocolTestCase
2162
return TestUtil.TestSuite([_get_test(test_name)])
2163
stream = self.run_selftest(runner_class=tests.SubUnitBzrRunner,
2164
test_suite_factory=factory)
2165
test = ProtocolTestCase(stream)
2166
result = testtools.TestResult()
2168
content = stream.getvalue()
2169
return content, result
2171
def test_fail_has_log(self):
2172
content, result = self.run_subunit_stream('test_fail')
2173
self.assertEqual(1, len(result.failures))
2174
self.assertContainsRe(content, '(?m)^log$')
2175
self.assertContainsRe(content, 'this test will fail')
2177
def test_error_has_log(self):
2178
content, result = self.run_subunit_stream('test_error')
2179
self.assertContainsRe(content, '(?m)^log$')
2180
self.assertContainsRe(content, 'this test errored')
2182
def test_skip_has_no_log(self):
2183
content, result = self.run_subunit_stream('test_skip')
2184
self.assertNotContainsRe(content, '(?m)^log$')
2185
self.assertNotContainsRe(content, 'this test will be skipped')
2186
self.assertEqual(['reason'], result.skip_reasons.keys())
2187
skips = result.skip_reasons['reason']
2188
self.assertEqual(1, len(skips))
2190
# RemotedTestCase doesn't preserve the "details"
2191
## self.assertFalse('log' in test.getDetails())
2193
def test_missing_feature_has_no_log(self):
2194
content, result = self.run_subunit_stream('test_missing_feature')
2195
self.assertNotContainsRe(content, '(?m)^log$')
2196
self.assertNotContainsRe(content, 'missing the feature')
2197
self.assertEqual(['_MissingFeature\n'], result.skip_reasons.keys())
2198
skips = result.skip_reasons['_MissingFeature\n']
2199
self.assertEqual(1, len(skips))
2201
# RemotedTestCase doesn't preserve the "details"
2202
## self.assertFalse('log' in test.getDetails())
2204
def test_xfail_has_no_log(self):
2205
content, result = self.run_subunit_stream('test_xfail')
2206
self.assertNotContainsRe(content, '(?m)^log$')
2207
self.assertNotContainsRe(content, 'test with expected failure')
2208
self.assertEqual(1, len(result.expectedFailures))
2209
result_content = result.expectedFailures[0][1]
2210
self.assertNotContainsRe(result_content,
2211
'(?m)^(?:Text attachment: )?log(?:$|: )')
2212
self.assertNotContainsRe(result_content, 'test with expected failure')
2214
def test_unexpected_success_has_log(self):
2215
content, result = self.run_subunit_stream('test_unexpected_success')
2216
self.assertContainsRe(content, '(?m)^log$')
2217
self.assertContainsRe(content, 'test with unexpected success')
2218
# GZ 2011-05-18: Old versions of subunit treat unexpected success as a
2219
# success, if a min version check is added remove this
2220
from subunit import TestProtocolClient as _Client
2221
if _Client.addUnexpectedSuccess.im_func is _Client.addSuccess.im_func:
2222
self.expectFailure('subunit treats "unexpectedSuccess"'
2223
' as a plain success',
2224
self.assertEqual, 1, len(result.unexpectedSuccesses))
2225
self.assertEqual(1, len(result.unexpectedSuccesses))
2226
test = result.unexpectedSuccesses[0]
2227
# RemotedTestCase doesn't preserve the "details"
2228
## self.assertTrue('log' in test.getDetails())
2230
def test_success_has_no_log(self):
2231
content, result = self.run_subunit_stream('test_success')
2232
self.assertEqual(1, result.testsRun)
2233
self.assertNotContainsRe(content, '(?m)^log$')
2234
self.assertNotContainsRe(content, 'this test succeeds')
2237
class TestRunBzr(tests.TestCase):
2242
def _run_bzr_core(self, argv, retcode=0, encoding=None, stdin=None,
2244
"""Override _run_bzr_core to test how it is invoked by run_bzr.
2246
Attempts to run bzr from inside this class don't actually run it.
2248
We test how run_bzr actually invokes bzr in another location. Here we
2249
only need to test that it passes the right parameters to run_bzr.
2251
self.argv = list(argv)
2252
self.retcode = retcode
2253
self.encoding = encoding
2255
self.working_dir = working_dir
2256
return self.retcode, self.out, self.err
2258
def test_run_bzr_error(self):
2259
self.out = "It sure does!\n"
2260
out, err = self.run_bzr_error(['^$'], ['rocks'], retcode=34)
2261
self.assertEqual(['rocks'], self.argv)
2262
self.assertEqual(34, self.retcode)
2263
self.assertEqual('It sure does!\n', out)
2264
self.assertEquals(out, self.out)
2265
self.assertEqual('', err)
2266
self.assertEquals(err, self.err)
2268
def test_run_bzr_error_regexes(self):
2270
self.err = "bzr: ERROR: foobarbaz is not versioned"
2271
out, err = self.run_bzr_error(
2272
["bzr: ERROR: foobarbaz is not versioned"],
2273
['file-id', 'foobarbaz'])
2275
def test_encoding(self):
2276
"""Test that run_bzr passes encoding to _run_bzr_core"""
2277
self.run_bzr('foo bar')
2278
self.assertEqual(None, self.encoding)
2279
self.assertEqual(['foo', 'bar'], self.argv)
2281
self.run_bzr('foo bar', encoding='baz')
2282
self.assertEqual('baz', self.encoding)
2283
self.assertEqual(['foo', 'bar'], self.argv)
2285
def test_retcode(self):
2286
"""Test that run_bzr passes retcode to _run_bzr_core"""
2287
# Default is retcode == 0
2288
self.run_bzr('foo bar')
2289
self.assertEqual(0, self.retcode)
2290
self.assertEqual(['foo', 'bar'], self.argv)
2292
self.run_bzr('foo bar', retcode=1)
2293
self.assertEqual(1, self.retcode)
2294
self.assertEqual(['foo', 'bar'], self.argv)
2296
self.run_bzr('foo bar', retcode=None)
2297
self.assertEqual(None, self.retcode)
2298
self.assertEqual(['foo', 'bar'], self.argv)
2300
self.run_bzr(['foo', 'bar'], retcode=3)
2301
self.assertEqual(3, self.retcode)
2302
self.assertEqual(['foo', 'bar'], self.argv)
2304
def test_stdin(self):
2305
# test that the stdin keyword to run_bzr is passed through to
2306
# _run_bzr_core as-is. We do this by overriding
2307
# _run_bzr_core in this class, and then calling run_bzr,
2308
# which is a convenience function for _run_bzr_core, so
2310
self.run_bzr('foo bar', stdin='gam')
2311
self.assertEqual('gam', self.stdin)
2312
self.assertEqual(['foo', 'bar'], self.argv)
2314
self.run_bzr('foo bar', stdin='zippy')
2315
self.assertEqual('zippy', self.stdin)
2316
self.assertEqual(['foo', 'bar'], self.argv)
2318
def test_working_dir(self):
2319
"""Test that run_bzr passes working_dir to _run_bzr_core"""
2320
self.run_bzr('foo bar')
2321
self.assertEqual(None, self.working_dir)
2322
self.assertEqual(['foo', 'bar'], self.argv)
2324
self.run_bzr('foo bar', working_dir='baz')
2325
self.assertEqual('baz', self.working_dir)
2326
self.assertEqual(['foo', 'bar'], self.argv)
2328
def test_reject_extra_keyword_arguments(self):
2329
self.assertRaises(TypeError, self.run_bzr, "foo bar",
2330
error_regex=['error message'])
2333
class TestRunBzrCaptured(tests.TestCaseWithTransport):
2334
# Does IO when testing the working_dir parameter.
2336
def apply_redirected(self, stdin=None, stdout=None, stderr=None,
2337
a_callable=None, *args, **kwargs):
2339
self.factory_stdin = getattr(bzrlib.ui.ui_factory, "stdin", None)
2340
self.factory = bzrlib.ui.ui_factory
2341
self.working_dir = osutils.getcwd()
2342
stdout.write('foo\n')
2343
stderr.write('bar\n')
2346
def test_stdin(self):
2347
# test that the stdin keyword to _run_bzr_core is passed through to
2348
# apply_redirected as a StringIO. We do this by overriding
2349
# apply_redirected in this class, and then calling _run_bzr_core,
2350
# which calls apply_redirected.
2351
self.run_bzr(['foo', 'bar'], stdin='gam')
2352
self.assertEqual('gam', self.stdin.read())
2353
self.assertTrue(self.stdin is self.factory_stdin)
2354
self.run_bzr(['foo', 'bar'], stdin='zippy')
2355
self.assertEqual('zippy', self.stdin.read())
2356
self.assertTrue(self.stdin is self.factory_stdin)
2358
def test_ui_factory(self):
2359
# each invocation of self.run_bzr should get its
2360
# own UI factory, which is an instance of TestUIFactory,
2361
# with stdin, stdout and stderr attached to the stdin,
2362
# stdout and stderr of the invoked run_bzr
2363
current_factory = bzrlib.ui.ui_factory
2364
self.run_bzr(['foo'])
2365
self.assertFalse(current_factory is self.factory)
2366
self.assertNotEqual(sys.stdout, self.factory.stdout)
2367
self.assertNotEqual(sys.stderr, self.factory.stderr)
2368
self.assertEqual('foo\n', self.factory.stdout.getvalue())
2369
self.assertEqual('bar\n', self.factory.stderr.getvalue())
2370
self.assertIsInstance(self.factory, tests.TestUIFactory)
2372
def test_working_dir(self):
2373
self.build_tree(['one/', 'two/'])
2374
cwd = osutils.getcwd()
2376
# Default is to work in the current directory
2377
self.run_bzr(['foo', 'bar'])
2378
self.assertEqual(cwd, self.working_dir)
2380
self.run_bzr(['foo', 'bar'], working_dir=None)
2381
self.assertEqual(cwd, self.working_dir)
2383
# The function should be run in the alternative directory
2384
# but afterwards the current working dir shouldn't be changed
2385
self.run_bzr(['foo', 'bar'], working_dir='one')
2386
self.assertNotEqual(cwd, self.working_dir)
2387
self.assertEndsWith(self.working_dir, 'one')
2388
self.assertEqual(cwd, osutils.getcwd())
2390
self.run_bzr(['foo', 'bar'], working_dir='two')
2391
self.assertNotEqual(cwd, self.working_dir)
2392
self.assertEndsWith(self.working_dir, 'two')
2393
self.assertEqual(cwd, osutils.getcwd())
2396
class StubProcess(object):
2397
"""A stub process for testing run_bzr_subprocess."""
2399
def __init__(self, out="", err="", retcode=0):
2402
self.returncode = retcode
2404
def communicate(self):
2405
return self.out, self.err
2408
class TestWithFakedStartBzrSubprocess(tests.TestCaseWithTransport):
2409
"""Base class for tests testing how we might run bzr."""
2412
tests.TestCaseWithTransport.setUp(self)
2413
self.subprocess_calls = []
2415
def start_bzr_subprocess(self, process_args, env_changes=None,
2416
skip_if_plan_to_signal=False,
2418
allow_plugins=False):
2419
"""capture what run_bzr_subprocess tries to do."""
2420
self.subprocess_calls.append({'process_args':process_args,
2421
'env_changes':env_changes,
2422
'skip_if_plan_to_signal':skip_if_plan_to_signal,
2423
'working_dir':working_dir, 'allow_plugins':allow_plugins})
2424
return self.next_subprocess
2427
class TestRunBzrSubprocess(TestWithFakedStartBzrSubprocess):
2429
def assertRunBzrSubprocess(self, expected_args, process, *args, **kwargs):
2430
"""Run run_bzr_subprocess with args and kwargs using a stubbed process.
2432
Inside TestRunBzrSubprocessCommands we use a stub start_bzr_subprocess
2433
that will return static results. This assertion method populates those
2434
results and also checks the arguments run_bzr_subprocess generates.
2436
self.next_subprocess = process
2438
result = self.run_bzr_subprocess(*args, **kwargs)
2440
self.next_subprocess = None
2441
for key, expected in expected_args.iteritems():
2442
self.assertEqual(expected, self.subprocess_calls[-1][key])
2445
self.next_subprocess = None
2446
for key, expected in expected_args.iteritems():
2447
self.assertEqual(expected, self.subprocess_calls[-1][key])
2450
def test_run_bzr_subprocess(self):
2451
"""The run_bzr_helper_external command behaves nicely."""
2452
self.assertRunBzrSubprocess({'process_args':['--version']},
2453
StubProcess(), '--version')
2454
self.assertRunBzrSubprocess({'process_args':['--version']},
2455
StubProcess(), ['--version'])
2456
# retcode=None disables retcode checking
2457
result = self.assertRunBzrSubprocess({},
2458
StubProcess(retcode=3), '--version', retcode=None)
2459
result = self.assertRunBzrSubprocess({},
2460
StubProcess(out="is free software"), '--version')
2461
self.assertContainsRe(result[0], 'is free software')
2462
# Running a subcommand that is missing errors
2463
self.assertRaises(AssertionError, self.assertRunBzrSubprocess,
2464
{'process_args':['--versionn']}, StubProcess(retcode=3),
2466
# Unless it is told to expect the error from the subprocess
2467
result = self.assertRunBzrSubprocess({},
2468
StubProcess(retcode=3), '--versionn', retcode=3)
2469
# Or to ignore retcode checking
2470
result = self.assertRunBzrSubprocess({},
2471
StubProcess(err="unknown command", retcode=3), '--versionn',
2473
self.assertContainsRe(result[1], 'unknown command')
2475
def test_env_change_passes_through(self):
2476
self.assertRunBzrSubprocess(
2477
{'env_changes':{'new':'value', 'changed':'newvalue', 'deleted':None}},
2479
env_changes={'new':'value', 'changed':'newvalue', 'deleted':None})
2481
def test_no_working_dir_passed_as_None(self):
2482
self.assertRunBzrSubprocess({'working_dir': None}, StubProcess(), '')
2484
def test_no_working_dir_passed_through(self):
2485
self.assertRunBzrSubprocess({'working_dir': 'dir'}, StubProcess(), '',
2488
def test_run_bzr_subprocess_no_plugins(self):
2489
self.assertRunBzrSubprocess({'allow_plugins': False},
2492
def test_allow_plugins(self):
2493
self.assertRunBzrSubprocess({'allow_plugins': True},
2494
StubProcess(), '', allow_plugins=True)
2497
class TestFinishBzrSubprocess(TestWithFakedStartBzrSubprocess):
2499
def test_finish_bzr_subprocess_with_error(self):
2500
"""finish_bzr_subprocess allows specification of the desired exit code.
2502
process = StubProcess(err="unknown command", retcode=3)
2503
result = self.finish_bzr_subprocess(process, retcode=3)
2504
self.assertEqual('', result[0])
2505
self.assertContainsRe(result[1], 'unknown command')
2507
def test_finish_bzr_subprocess_ignoring_retcode(self):
2508
"""finish_bzr_subprocess allows the exit code to be ignored."""
2509
process = StubProcess(err="unknown command", retcode=3)
2510
result = self.finish_bzr_subprocess(process, retcode=None)
2511
self.assertEqual('', result[0])
2512
self.assertContainsRe(result[1], 'unknown command')
2514
def test_finish_subprocess_with_unexpected_retcode(self):
2515
"""finish_bzr_subprocess raises self.failureException if the retcode is
2516
not the expected one.
2518
process = StubProcess(err="unknown command", retcode=3)
2519
self.assertRaises(self.failureException, self.finish_bzr_subprocess,
2523
class _DontSpawnProcess(Exception):
2524
"""A simple exception which just allows us to skip unnecessary steps"""
2527
class TestStartBzrSubProcess(tests.TestCase):
2528
"""Stub test start_bzr_subprocess."""
2530
def _subprocess_log_cleanup(self):
2531
"""Inhibits the base version as we don't produce a log file."""
2533
def _popen(self, *args, **kwargs):
2534
"""Override the base version to record the command that is run.
2536
From there we can ensure it is correct without spawning a real process.
2538
self.check_popen_state()
2539
self._popen_args = args
2540
self._popen_kwargs = kwargs
2541
raise _DontSpawnProcess()
2543
def check_popen_state(self):
2544
"""Replace to make assertions when popen is called."""
2546
def test_run_bzr_subprocess_no_plugins(self):
2547
self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [])
2548
command = self._popen_args[0]
2549
self.assertEqual(sys.executable, command[0])
2550
self.assertEqual(self.get_bzr_path(), command[1])
2551
self.assertEqual(['--no-plugins'], command[2:])
2553
def test_allow_plugins(self):
2554
self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [],
2556
command = self._popen_args[0]
2557
self.assertEqual([], command[2:])
2559
def test_set_env(self):
2560
self.assertFalse('EXISTANT_ENV_VAR' in os.environ)
2562
def check_environment():
2563
self.assertEqual('set variable', os.environ['EXISTANT_ENV_VAR'])
2564
self.check_popen_state = check_environment
2565
self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [],
2566
env_changes={'EXISTANT_ENV_VAR':'set variable'})
2567
# not set in theparent
2568
self.assertFalse('EXISTANT_ENV_VAR' in os.environ)
2570
def test_run_bzr_subprocess_env_del(self):
2571
"""run_bzr_subprocess can remove environment variables too."""
2572
self.assertFalse('EXISTANT_ENV_VAR' in os.environ)
2573
def check_environment():
2574
self.assertFalse('EXISTANT_ENV_VAR' in os.environ)
2575
os.environ['EXISTANT_ENV_VAR'] = 'set variable'
2576
self.check_popen_state = check_environment
2577
self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [],
2578
env_changes={'EXISTANT_ENV_VAR':None})
2579
# Still set in parent
2580
self.assertEqual('set variable', os.environ['EXISTANT_ENV_VAR'])
2581
del os.environ['EXISTANT_ENV_VAR']
2583
def test_env_del_missing(self):
2584
self.assertFalse('NON_EXISTANT_ENV_VAR' in os.environ)
2585
def check_environment():
2586
self.assertFalse('NON_EXISTANT_ENV_VAR' in os.environ)
2587
self.check_popen_state = check_environment
2588
self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [],
2589
env_changes={'NON_EXISTANT_ENV_VAR':None})
2591
def test_working_dir(self):
2592
"""Test that we can specify the working dir for the child"""
2593
orig_getcwd = osutils.getcwd
2594
orig_chdir = os.chdir
2598
self.overrideAttr(os, 'chdir', chdir)
2601
self.overrideAttr(osutils, 'getcwd', getcwd)
2602
self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [],
2604
self.assertEqual(['foo', 'current'], chdirs)
2606
def test_get_bzr_path_with_cwd_bzrlib(self):
2607
self.get_source_path = lambda: ""
2608
self.overrideAttr(os.path, "isfile", lambda path: True)
2609
self.assertEqual(self.get_bzr_path(), "bzr")
2612
class TestActuallyStartBzrSubprocess(tests.TestCaseWithTransport):
2613
"""Tests that really need to do things with an external bzr."""
2615
def test_start_and_stop_bzr_subprocess_send_signal(self):
2616
"""finish_bzr_subprocess raises self.failureException if the retcode is
2617
not the expected one.
2619
self.disable_missing_extensions_warning()
2620
process = self.start_bzr_subprocess(['wait-until-signalled'],
2621
skip_if_plan_to_signal=True)
2622
self.assertEqual('running\n', process.stdout.readline())
2623
result = self.finish_bzr_subprocess(process, send_signal=signal.SIGINT,
2625
self.assertEqual('', result[0])
2626
self.assertEqual('bzr: interrupted\n', result[1])
2629
class TestFeature(tests.TestCase):
2631
def test_caching(self):
2632
"""Feature._probe is called by the feature at most once."""
2633
class InstrumentedFeature(tests.Feature):
2635
super(InstrumentedFeature, self).__init__()
2638
self.calls.append('_probe')
2640
feature = InstrumentedFeature()
2642
self.assertEqual(['_probe'], feature.calls)
2644
self.assertEqual(['_probe'], feature.calls)
2646
def test_named_str(self):
2647
"""Feature.__str__ should thunk to feature_name()."""
2648
class NamedFeature(tests.Feature):
2649
def feature_name(self):
2651
feature = NamedFeature()
2652
self.assertEqual('symlinks', str(feature))
2654
def test_default_str(self):
2655
"""Feature.__str__ should default to __class__.__name__."""
2656
class NamedFeature(tests.Feature):
2658
feature = NamedFeature()
2659
self.assertEqual('NamedFeature', str(feature))
2662
class TestUnavailableFeature(tests.TestCase):
2664
def test_access_feature(self):
2665
feature = tests.Feature()
2666
exception = tests.UnavailableFeature(feature)
2667
self.assertIs(feature, exception.args[0])
2670
simple_thunk_feature = tests._CompatabilityThunkFeature(
2671
deprecated_in((2, 1, 0)),
2672
'bzrlib.tests.test_selftest',
2673
'simple_thunk_feature','UnicodeFilename',
2674
replacement_module='bzrlib.tests'
2677
class Test_CompatibilityFeature(tests.TestCase):
2679
def test_does_thunk(self):
2680
res = self.callDeprecated(
2681
['bzrlib.tests.test_selftest.simple_thunk_feature was deprecated'
2682
' in version 2.1.0. Use bzrlib.tests.UnicodeFilename instead.'],
2683
simple_thunk_feature.available)
2684
self.assertEqual(tests.UnicodeFilename.available(), res)
2687
class TestModuleAvailableFeature(tests.TestCase):
2689
def test_available_module(self):
2690
feature = tests.ModuleAvailableFeature('bzrlib.tests')
2691
self.assertEqual('bzrlib.tests', feature.module_name)
2692
self.assertEqual('bzrlib.tests', str(feature))
2693
self.assertTrue(feature.available())
2694
self.assertIs(tests, feature.module)
2696
def test_unavailable_module(self):
2697
feature = tests.ModuleAvailableFeature('bzrlib.no_such_module_exists')
2698
self.assertEqual('bzrlib.no_such_module_exists', str(feature))
2699
self.assertFalse(feature.available())
2700
self.assertIs(None, feature.module)
2703
class TestSelftestFiltering(tests.TestCase):
2706
tests.TestCase.setUp(self)
2707
self.suite = TestUtil.TestSuite()
2708
self.loader = TestUtil.TestLoader()
2709
self.suite.addTest(self.loader.loadTestsFromModule(
2710
sys.modules['bzrlib.tests.test_selftest']))
2711
self.all_names = _test_ids(self.suite)
2713
def test_condition_id_re(self):
2714
test_name = ('bzrlib.tests.test_selftest.TestSelftestFiltering.'
2715
'test_condition_id_re')
2716
filtered_suite = tests.filter_suite_by_condition(
2717
self.suite, tests.condition_id_re('test_condition_id_re'))
2718
self.assertEqual([test_name], _test_ids(filtered_suite))
2720
def test_condition_id_in_list(self):
2721
test_names = ['bzrlib.tests.test_selftest.TestSelftestFiltering.'
2722
'test_condition_id_in_list']
2723
id_list = tests.TestIdList(test_names)
2724
filtered_suite = tests.filter_suite_by_condition(
2725
self.suite, tests.condition_id_in_list(id_list))
2726
my_pattern = 'TestSelftestFiltering.*test_condition_id_in_list'
2727
re_filtered = tests.filter_suite_by_re(self.suite, my_pattern)
2728
self.assertEqual(_test_ids(re_filtered), _test_ids(filtered_suite))
2730
def test_condition_id_startswith(self):
2731
klass = 'bzrlib.tests.test_selftest.TestSelftestFiltering.'
2732
start1 = klass + 'test_condition_id_starts'
2733
start2 = klass + 'test_condition_id_in'
2734
test_names = [ klass + 'test_condition_id_in_list',
2735
klass + 'test_condition_id_startswith',
2737
filtered_suite = tests.filter_suite_by_condition(
2738
self.suite, tests.condition_id_startswith([start1, start2]))
2739
self.assertEqual(test_names, _test_ids(filtered_suite))
2741
def test_condition_isinstance(self):
2742
filtered_suite = tests.filter_suite_by_condition(
2743
self.suite, tests.condition_isinstance(self.__class__))
2744
class_pattern = 'bzrlib.tests.test_selftest.TestSelftestFiltering.'
2745
re_filtered = tests.filter_suite_by_re(self.suite, class_pattern)
2746
self.assertEqual(_test_ids(re_filtered), _test_ids(filtered_suite))
2748
def test_exclude_tests_by_condition(self):
2749
excluded_name = ('bzrlib.tests.test_selftest.TestSelftestFiltering.'
2750
'test_exclude_tests_by_condition')
2751
filtered_suite = tests.exclude_tests_by_condition(self.suite,
2752
lambda x:x.id() == excluded_name)
2753
self.assertEqual(len(self.all_names) - 1,
2754
filtered_suite.countTestCases())
2755
self.assertFalse(excluded_name in _test_ids(filtered_suite))
2756
remaining_names = list(self.all_names)
2757
remaining_names.remove(excluded_name)
2758
self.assertEqual(remaining_names, _test_ids(filtered_suite))
2760
def test_exclude_tests_by_re(self):
2761
self.all_names = _test_ids(self.suite)
2762
filtered_suite = tests.exclude_tests_by_re(self.suite,
2763
'exclude_tests_by_re')
2764
excluded_name = ('bzrlib.tests.test_selftest.TestSelftestFiltering.'
2765
'test_exclude_tests_by_re')
2766
self.assertEqual(len(self.all_names) - 1,
2767
filtered_suite.countTestCases())
2768
self.assertFalse(excluded_name in _test_ids(filtered_suite))
2769
remaining_names = list(self.all_names)
2770
remaining_names.remove(excluded_name)
2771
self.assertEqual(remaining_names, _test_ids(filtered_suite))
2773
def test_filter_suite_by_condition(self):
2774
test_name = ('bzrlib.tests.test_selftest.TestSelftestFiltering.'
2775
'test_filter_suite_by_condition')
2776
filtered_suite = tests.filter_suite_by_condition(self.suite,
2777
lambda x:x.id() == test_name)
2778
self.assertEqual([test_name], _test_ids(filtered_suite))
2780
def test_filter_suite_by_re(self):
2781
filtered_suite = tests.filter_suite_by_re(self.suite,
2782
'test_filter_suite_by_r')
2783
filtered_names = _test_ids(filtered_suite)
2784
self.assertEqual(filtered_names, ['bzrlib.tests.test_selftest.'
2785
'TestSelftestFiltering.test_filter_suite_by_re'])
2787
def test_filter_suite_by_id_list(self):
2788
test_list = ['bzrlib.tests.test_selftest.'
2789
'TestSelftestFiltering.test_filter_suite_by_id_list']
2790
filtered_suite = tests.filter_suite_by_id_list(
2791
self.suite, tests.TestIdList(test_list))
2792
filtered_names = _test_ids(filtered_suite)
2795
['bzrlib.tests.test_selftest.'
2796
'TestSelftestFiltering.test_filter_suite_by_id_list'])
2798
def test_filter_suite_by_id_startswith(self):
2799
# By design this test may fail if another test is added whose name also
2800
# begins with one of the start value used.
2801
klass = 'bzrlib.tests.test_selftest.TestSelftestFiltering.'
2802
start1 = klass + 'test_filter_suite_by_id_starts'
2803
start2 = klass + 'test_filter_suite_by_id_li'
2804
test_list = [klass + 'test_filter_suite_by_id_list',
2805
klass + 'test_filter_suite_by_id_startswith',
2807
filtered_suite = tests.filter_suite_by_id_startswith(
2808
self.suite, [start1, start2])
2811
_test_ids(filtered_suite),
2814
def test_preserve_input(self):
2815
# NB: Surely this is something in the stdlib to do this?
2816
self.assertTrue(self.suite is tests.preserve_input(self.suite))
2817
self.assertTrue("@#$" is tests.preserve_input("@#$"))
2819
def test_randomize_suite(self):
2820
randomized_suite = tests.randomize_suite(self.suite)
2821
# randomizing should not add or remove test names.
2822
self.assertEqual(set(_test_ids(self.suite)),
2823
set(_test_ids(randomized_suite)))
2824
# Technically, this *can* fail, because random.shuffle(list) can be
2825
# equal to list. Trying multiple times just pushes the frequency back.
2826
# As its len(self.all_names)!:1, the failure frequency should be low
2827
# enough to ignore. RBC 20071021.
2828
# It should change the order.
2829
self.assertNotEqual(self.all_names, _test_ids(randomized_suite))
2830
# But not the length. (Possibly redundant with the set test, but not
2832
self.assertEqual(len(self.all_names), len(_test_ids(randomized_suite)))
2834
def test_split_suit_by_condition(self):
2835
self.all_names = _test_ids(self.suite)
2836
condition = tests.condition_id_re('test_filter_suite_by_r')
2837
split_suite = tests.split_suite_by_condition(self.suite, condition)
2838
filtered_name = ('bzrlib.tests.test_selftest.TestSelftestFiltering.'
2839
'test_filter_suite_by_re')
2840
self.assertEqual([filtered_name], _test_ids(split_suite[0]))
2841
self.assertFalse(filtered_name in _test_ids(split_suite[1]))
2842
remaining_names = list(self.all_names)
2843
remaining_names.remove(filtered_name)
2844
self.assertEqual(remaining_names, _test_ids(split_suite[1]))
2846
def test_split_suit_by_re(self):
2847
self.all_names = _test_ids(self.suite)
2848
split_suite = tests.split_suite_by_re(self.suite,
2849
'test_filter_suite_by_r')
2850
filtered_name = ('bzrlib.tests.test_selftest.TestSelftestFiltering.'
2851
'test_filter_suite_by_re')
2852
self.assertEqual([filtered_name], _test_ids(split_suite[0]))
2853
self.assertFalse(filtered_name in _test_ids(split_suite[1]))
2854
remaining_names = list(self.all_names)
2855
remaining_names.remove(filtered_name)
2856
self.assertEqual(remaining_names, _test_ids(split_suite[1]))
2859
class TestCheckTreeShape(tests.TestCaseWithTransport):
2861
def test_check_tree_shape(self):
2862
files = ['a', 'b/', 'b/c']
2863
tree = self.make_branch_and_tree('.')
2864
self.build_tree(files)
2868
self.check_tree_shape(tree, files)
2873
class TestBlackboxSupport(tests.TestCase):
2874
"""Tests for testsuite blackbox features."""
2876
def test_run_bzr_failure_not_caught(self):
2877
# When we run bzr in blackbox mode, we want any unexpected errors to
2878
# propagate up to the test suite so that it can show the error in the
2879
# usual way, and we won't get a double traceback.
2880
e = self.assertRaises(
2882
self.run_bzr, ['assert-fail'])
2883
# make sure we got the real thing, not an error from somewhere else in
2884
# the test framework
2885
self.assertEquals('always fails', str(e))
2886
# check that there's no traceback in the test log
2887
self.assertNotContainsRe(self.get_log(), r'Traceback')
2889
def test_run_bzr_user_error_caught(self):
2890
# Running bzr in blackbox mode, normal/expected/user errors should be
2891
# caught in the regular way and turned into an error message plus exit
2893
transport_server = memory.MemoryServer()
2894
transport_server.start_server()
2895
self.addCleanup(transport_server.stop_server)
2896
url = transport_server.get_url()
2897
self.permit_url(url)
2898
out, err = self.run_bzr(["log", "%s/nonexistantpath" % url], retcode=3)
2899
self.assertEqual(out, '')
2900
self.assertContainsRe(err,
2901
'bzr: ERROR: Not a branch: ".*nonexistantpath/".\n')
2904
class TestTestLoader(tests.TestCase):
2905
"""Tests for the test loader."""
2907
def _get_loader_and_module(self):
2908
"""Gets a TestLoader and a module with one test in it."""
2909
loader = TestUtil.TestLoader()
2911
class Stub(tests.TestCase):
2914
class MyModule(object):
2916
MyModule.a_class = Stub
2918
return loader, module
2920
def test_module_no_load_tests_attribute_loads_classes(self):
2921
loader, module = self._get_loader_and_module()
2922
self.assertEqual(1, loader.loadTestsFromModule(module).countTestCases())
2924
def test_module_load_tests_attribute_gets_called(self):
2925
loader, module = self._get_loader_and_module()
2926
# 'self' is here because we're faking the module with a class. Regular
2927
# load_tests do not need that :)
2928
def load_tests(self, standard_tests, module, loader):
2929
result = loader.suiteClass()
2930
for test in tests.iter_suite_tests(standard_tests):
2931
result.addTests([test, test])
2933
# add a load_tests() method which multiplies the tests from the module.
2934
module.__class__.load_tests = load_tests
2935
self.assertEqual(2, loader.loadTestsFromModule(module).countTestCases())
2937
def test_load_tests_from_module_name_smoke_test(self):
2938
loader = TestUtil.TestLoader()
2939
suite = loader.loadTestsFromModuleName('bzrlib.tests.test_sampler')
2940
self.assertEquals(['bzrlib.tests.test_sampler.DemoTest.test_nothing'],
2943
def test_load_tests_from_module_name_with_bogus_module_name(self):
2944
loader = TestUtil.TestLoader()
2945
self.assertRaises(ImportError, loader.loadTestsFromModuleName, 'bogus')
2948
class TestTestIdList(tests.TestCase):
2950
def _create_id_list(self, test_list):
2951
return tests.TestIdList(test_list)
2953
def _create_suite(self, test_id_list):
2955
class Stub(tests.TestCase):
2959
def _create_test_id(id):
2962
suite = TestUtil.TestSuite()
2963
for id in test_id_list:
2964
t = Stub('test_foo')
2965
t.id = _create_test_id(id)
2969
def _test_ids(self, test_suite):
2970
"""Get the ids for the tests in a test suite."""
2971
return [t.id() for t in tests.iter_suite_tests(test_suite)]
2973
def test_empty_list(self):
2974
id_list = self._create_id_list([])
2975
self.assertEquals({}, id_list.tests)
2976
self.assertEquals({}, id_list.modules)
2978
def test_valid_list(self):
2979
id_list = self._create_id_list(
2980
['mod1.cl1.meth1', 'mod1.cl1.meth2',
2981
'mod1.func1', 'mod1.cl2.meth2',
2983
'mod1.submod2.cl1.meth1', 'mod1.submod2.cl2.meth2',
2985
self.assertTrue(id_list.refers_to('mod1'))
2986
self.assertTrue(id_list.refers_to('mod1.submod1'))
2987
self.assertTrue(id_list.refers_to('mod1.submod2'))
2988
self.assertTrue(id_list.includes('mod1.cl1.meth1'))
2989
self.assertTrue(id_list.includes('mod1.submod1'))
2990
self.assertTrue(id_list.includes('mod1.func1'))
2992
def test_bad_chars_in_params(self):
2993
id_list = self._create_id_list(['mod1.cl1.meth1(xx.yy)'])
2994
self.assertTrue(id_list.refers_to('mod1'))
2995
self.assertTrue(id_list.includes('mod1.cl1.meth1(xx.yy)'))
2997
def test_module_used(self):
2998
id_list = self._create_id_list(['mod.class.meth'])
2999
self.assertTrue(id_list.refers_to('mod'))
3000
self.assertTrue(id_list.refers_to('mod.class'))
3001
self.assertTrue(id_list.refers_to('mod.class.meth'))
3003
def test_test_suite_matches_id_list_with_unknown(self):
3004
loader = TestUtil.TestLoader()
3005
suite = loader.loadTestsFromModuleName('bzrlib.tests.test_sampler')
3006
test_list = ['bzrlib.tests.test_sampler.DemoTest.test_nothing',
3008
not_found, duplicates = tests.suite_matches_id_list(suite, test_list)
3009
self.assertEquals(['bogus'], not_found)
3010
self.assertEquals([], duplicates)
3012
def test_suite_matches_id_list_with_duplicates(self):
3013
loader = TestUtil.TestLoader()
3014
suite = loader.loadTestsFromModuleName('bzrlib.tests.test_sampler')
3015
dupes = loader.suiteClass()
3016
for test in tests.iter_suite_tests(suite):
3018
dupes.addTest(test) # Add it again
3020
test_list = ['bzrlib.tests.test_sampler.DemoTest.test_nothing',]
3021
not_found, duplicates = tests.suite_matches_id_list(
3023
self.assertEquals([], not_found)
3024
self.assertEquals(['bzrlib.tests.test_sampler.DemoTest.test_nothing'],
3028
class TestTestSuite(tests.TestCase):
3030
def test__test_suite_testmod_names(self):
3031
# Test that a plausible list of test module names are returned
3032
# by _test_suite_testmod_names.
3033
test_list = tests._test_suite_testmod_names()
3035
'bzrlib.tests.blackbox',
3036
'bzrlib.tests.per_transport',
3037
'bzrlib.tests.test_selftest',
3041
def test__test_suite_modules_to_doctest(self):
3042
# Test that a plausible list of modules to doctest is returned
3043
# by _test_suite_modules_to_doctest.
3044
test_list = tests._test_suite_modules_to_doctest()
3046
# When docstrings are stripped, there are no modules to doctest
3047
self.assertEqual([], test_list)
3054
def test_test_suite(self):
3055
# test_suite() loads the entire test suite to operate. To avoid this
3056
# overhead, and yet still be confident that things are happening,
3057
# we temporarily replace two functions used by test_suite with
3058
# test doubles that supply a few sample tests to load, and check they
3061
def testmod_names():
3062
calls.append("testmod_names")
3064
'bzrlib.tests.blackbox.test_branch',
3065
'bzrlib.tests.per_transport',
3066
'bzrlib.tests.test_selftest',
3068
self.overrideAttr(tests, '_test_suite_testmod_names', testmod_names)
3070
calls.append("modules_to_doctest")
3073
return ['bzrlib.timestamp']
3074
self.overrideAttr(tests, '_test_suite_modules_to_doctest', doctests)
3075
expected_test_list = [
3077
'bzrlib.tests.blackbox.test_branch.TestBranch.test_branch',
3078
('bzrlib.tests.per_transport.TransportTests'
3079
'.test_abspath(LocalTransport,LocalURLServer)'),
3080
'bzrlib.tests.test_selftest.TestTestSuite.test_test_suite',
3081
# plugins can't be tested that way since selftest may be run with
3084
if __doc__ is not None:
3085
expected_test_list.extend([
3086
# modules_to_doctest
3087
'bzrlib.timestamp.format_highres_date',
3089
suite = tests.test_suite()
3090
self.assertEqual(set(["testmod_names", "modules_to_doctest"]),
3092
self.assertSubset(expected_test_list, _test_ids(suite))
3094
def test_test_suite_list_and_start(self):
3095
# We cannot test this at the same time as the main load, because we want
3096
# to know that starting_with == None works. So a second load is
3097
# incurred - note that the starting_with parameter causes a partial load
3098
# rather than a full load so this test should be pretty quick.
3099
test_list = ['bzrlib.tests.test_selftest.TestTestSuite.test_test_suite']
3100
suite = tests.test_suite(test_list,
3101
['bzrlib.tests.test_selftest.TestTestSuite'])
3102
# test_test_suite_list_and_start is not included
3103
self.assertEquals(test_list, _test_ids(suite))
3106
class TestLoadTestIdList(tests.TestCaseInTempDir):
3108
def _create_test_list_file(self, file_name, content):
3109
fl = open(file_name, 'wt')
3113
def test_load_unknown(self):
3114
self.assertRaises(errors.NoSuchFile,
3115
tests.load_test_id_list, 'i_do_not_exist')
3117
def test_load_test_list(self):
3118
test_list_fname = 'test.list'
3119
self._create_test_list_file(test_list_fname,
3120
'mod1.cl1.meth1\nmod2.cl2.meth2\n')
3121
tlist = tests.load_test_id_list(test_list_fname)
3122
self.assertEquals(2, len(tlist))
3123
self.assertEquals('mod1.cl1.meth1', tlist[0])
3124
self.assertEquals('mod2.cl2.meth2', tlist[1])
3126
def test_load_dirty_file(self):
3127
test_list_fname = 'test.list'
3128
self._create_test_list_file(test_list_fname,
3129
' mod1.cl1.meth1\n\nmod2.cl2.meth2 \n'
3131
tlist = tests.load_test_id_list(test_list_fname)
3132
self.assertEquals(4, len(tlist))
3133
self.assertEquals('mod1.cl1.meth1', tlist[0])
3134
self.assertEquals('', tlist[1])
3135
self.assertEquals('mod2.cl2.meth2', tlist[2])
3136
self.assertEquals('bar baz', tlist[3])
3139
class TestFilteredByModuleTestLoader(tests.TestCase):
3141
def _create_loader(self, test_list):
3142
id_filter = tests.TestIdList(test_list)
3143
loader = TestUtil.FilteredByModuleTestLoader(id_filter.refers_to)
3146
def test_load_tests(self):
3147
test_list = ['bzrlib.tests.test_sampler.DemoTest.test_nothing']
3148
loader = self._create_loader(test_list)
3149
suite = loader.loadTestsFromModuleName('bzrlib.tests.test_sampler')
3150
self.assertEquals(test_list, _test_ids(suite))
3152
def test_exclude_tests(self):
3153
test_list = ['bogus']
3154
loader = self._create_loader(test_list)
3155
suite = loader.loadTestsFromModuleName('bzrlib.tests.test_sampler')
3156
self.assertEquals([], _test_ids(suite))
3159
class TestFilteredByNameStartTestLoader(tests.TestCase):
3161
def _create_loader(self, name_start):
3162
def needs_module(name):
3163
return name.startswith(name_start) or name_start.startswith(name)
3164
loader = TestUtil.FilteredByModuleTestLoader(needs_module)
3167
def test_load_tests(self):
3168
test_list = ['bzrlib.tests.test_sampler.DemoTest.test_nothing']
3169
loader = self._create_loader('bzrlib.tests.test_samp')
3171
suite = loader.loadTestsFromModuleName('bzrlib.tests.test_sampler')
3172
self.assertEquals(test_list, _test_ids(suite))
3174
def test_load_tests_inside_module(self):
3175
test_list = ['bzrlib.tests.test_sampler.DemoTest.test_nothing']
3176
loader = self._create_loader('bzrlib.tests.test_sampler.Demo')
3178
suite = loader.loadTestsFromModuleName('bzrlib.tests.test_sampler')
3179
self.assertEquals(test_list, _test_ids(suite))
3181
def test_exclude_tests(self):
3182
test_list = ['bogus']
3183
loader = self._create_loader('bogus')
3185
suite = loader.loadTestsFromModuleName('bzrlib.tests.test_sampler')
3186
self.assertEquals([], _test_ids(suite))
3189
class TestTestPrefixRegistry(tests.TestCase):
3191
def _get_registry(self):
3192
tp_registry = tests.TestPrefixAliasRegistry()
3195
def test_register_new_prefix(self):
3196
tpr = self._get_registry()
3197
tpr.register('foo', 'fff.ooo.ooo')
3198
self.assertEquals('fff.ooo.ooo', tpr.get('foo'))
3200
def test_register_existing_prefix(self):
3201
tpr = self._get_registry()
3202
tpr.register('bar', 'bbb.aaa.rrr')
3203
tpr.register('bar', 'bBB.aAA.rRR')
3204
self.assertEquals('bbb.aaa.rrr', tpr.get('bar'))
3205
self.assertThat(self.get_log(),
3206
DocTestMatches("...bar...bbb.aaa.rrr...BB.aAA.rRR",
3209
def test_get_unknown_prefix(self):
3210
tpr = self._get_registry()
3211
self.assertRaises(KeyError, tpr.get, 'I am not a prefix')
3213
def test_resolve_prefix(self):
3214
tpr = self._get_registry()
3215
tpr.register('bar', 'bb.aa.rr')
3216
self.assertEquals('bb.aa.rr', tpr.resolve_alias('bar'))
3218
def test_resolve_unknown_alias(self):
3219
tpr = self._get_registry()
3220
self.assertRaises(errors.BzrCommandError,
3221
tpr.resolve_alias, 'I am not a prefix')
3223
def test_predefined_prefixes(self):
3224
tpr = tests.test_prefix_alias_registry
3225
self.assertEquals('bzrlib', tpr.resolve_alias('bzrlib'))
3226
self.assertEquals('bzrlib.doc', tpr.resolve_alias('bd'))
3227
self.assertEquals('bzrlib.utils', tpr.resolve_alias('bu'))
3228
self.assertEquals('bzrlib.tests', tpr.resolve_alias('bt'))
3229
self.assertEquals('bzrlib.tests.blackbox', tpr.resolve_alias('bb'))
3230
self.assertEquals('bzrlib.plugins', tpr.resolve_alias('bp'))
3233
class TestThreadLeakDetection(tests.TestCase):
3234
"""Ensure when tests leak threads we detect and report it"""
3236
class LeakRecordingResult(tests.ExtendedTestResult):
3238
tests.ExtendedTestResult.__init__(self, StringIO(), 0, 1)
3240
def _report_thread_leak(self, test, leaks, alive):
3241
self.leaks.append((test, leaks))
3243
def test_testcase_without_addCleanups(self):
3244
"""Check old TestCase instances don't break with leak detection"""
3245
class Test(unittest.TestCase):
3248
result = self.LeakRecordingResult()
3250
result.startTestRun()
3252
result.stopTestRun()
3253
self.assertEqual(result._tests_leaking_threads_count, 0)
3254
self.assertEqual(result.leaks, [])
3256
def test_thread_leak(self):
3257
"""Ensure a thread that outlives the running of a test is reported
3259
Uses a thread that blocks on an event, and is started by the inner
3260
test case. As the thread outlives the inner case's run, it should be
3261
detected as a leak, but the event is then set so that the thread can
3262
be safely joined in cleanup so it's not leaked for real.
3264
event = threading.Event()
3265
thread = threading.Thread(name="Leaker", target=event.wait)
3266
class Test(tests.TestCase):
3267
def test_leak(self):
3269
result = self.LeakRecordingResult()
3270
test = Test("test_leak")
3271
self.addCleanup(thread.join)
3272
self.addCleanup(event.set)
3273
result.startTestRun()
3275
result.stopTestRun()
3276
self.assertEqual(result._tests_leaking_threads_count, 1)
3277
self.assertEqual(result._first_thread_leaker_id, test.id())
3278
self.assertEqual(result.leaks, [(test, set([thread]))])
3279
self.assertContainsString(result.stream.getvalue(), "leaking threads")
3281
def test_multiple_leaks(self):
3282
"""Check multiple leaks are blamed on the test cases at fault
3284
Same concept as the previous test, but has one inner test method that
3285
leaks two threads, and one that doesn't leak at all.
3287
event = threading.Event()
3288
thread_a = threading.Thread(name="LeakerA", target=event.wait)
3289
thread_b = threading.Thread(name="LeakerB", target=event.wait)
3290
thread_c = threading.Thread(name="LeakerC", target=event.wait)
3291
class Test(tests.TestCase):
3292
def test_first_leak(self):
3294
def test_second_no_leak(self):
3296
def test_third_leak(self):
3299
result = self.LeakRecordingResult()
3300
first_test = Test("test_first_leak")
3301
third_test = Test("test_third_leak")
3302
self.addCleanup(thread_a.join)
3303
self.addCleanup(thread_b.join)
3304
self.addCleanup(thread_c.join)
3305
self.addCleanup(event.set)
3306
result.startTestRun()
3308
[first_test, Test("test_second_no_leak"), third_test]
3310
result.stopTestRun()
3311
self.assertEqual(result._tests_leaking_threads_count, 2)
3312
self.assertEqual(result._first_thread_leaker_id, first_test.id())
3313
self.assertEqual(result.leaks, [
3314
(first_test, set([thread_b])),
3315
(third_test, set([thread_a, thread_c]))])
3316
self.assertContainsString(result.stream.getvalue(), "leaking threads")
3319
class TestPostMortemDebugging(tests.TestCase):
3320
"""Check post mortem debugging works when tests fail or error"""
3322
class TracebackRecordingResult(tests.ExtendedTestResult):
3324
tests.ExtendedTestResult.__init__(self, StringIO(), 0, 1)
3325
self.postcode = None
3326
def _post_mortem(self, tb=None):
3327
"""Record the code object at the end of the current traceback"""
3328
tb = tb or sys.exc_info()[2]
3331
while next is not None:
3334
self.postcode = tb.tb_frame.f_code
3335
def report_error(self, test, err):
3337
def report_failure(self, test, err):
3340
def test_location_unittest_error(self):
3341
"""Needs right post mortem traceback with erroring unittest case"""
3342
class Test(unittest.TestCase):
3345
result = self.TracebackRecordingResult()
3347
self.assertEqual(result.postcode, Test.runTest.func_code)
3349
def test_location_unittest_failure(self):
3350
"""Needs right post mortem traceback with failing unittest case"""
3351
class Test(unittest.TestCase):
3353
raise self.failureException
3354
result = self.TracebackRecordingResult()
3356
self.assertEqual(result.postcode, Test.runTest.func_code)
3358
def test_location_bt_error(self):
3359
"""Needs right post mortem traceback with erroring bzrlib.tests case"""
3360
class Test(tests.TestCase):
3361
def test_error(self):
3363
result = self.TracebackRecordingResult()
3364
Test("test_error").run(result)
3365
self.assertEqual(result.postcode, Test.test_error.func_code)
3367
def test_location_bt_failure(self):
3368
"""Needs right post mortem traceback with failing bzrlib.tests case"""
3369
class Test(tests.TestCase):
3370
def test_failure(self):
3371
raise self.failureException
3372
result = self.TracebackRecordingResult()
3373
Test("test_failure").run(result)
3374
self.assertEqual(result.postcode, Test.test_failure.func_code)
3376
def test_env_var_triggers_post_mortem(self):
3377
"""Check pdb.post_mortem is called iff BZR_TEST_PDB is set"""
3379
result = tests.ExtendedTestResult(StringIO(), 0, 1)
3380
post_mortem_calls = []
3381
self.overrideAttr(pdb, "post_mortem", post_mortem_calls.append)
3382
self.overrideEnv('BZR_TEST_PDB', None)
3383
result._post_mortem(1)
3384
self.overrideEnv('BZR_TEST_PDB', 'on')
3385
result._post_mortem(2)
3386
self.assertEqual([2], post_mortem_calls)
3389
class TestRunSuite(tests.TestCase):
3391
def test_runner_class(self):
3392
"""run_suite accepts and uses a runner_class keyword argument."""
3393
class Stub(tests.TestCase):
3396
suite = Stub("test_foo")
3398
class MyRunner(tests.TextTestRunner):
3399
def run(self, test):
3401
return tests.ExtendedTestResult(self.stream, self.descriptions,
3403
tests.run_suite(suite, runner_class=MyRunner, stream=StringIO())
3404
self.assertLength(1, calls)
3407
class TestEnvironHandling(tests.TestCase):
3409
def test_overrideEnv_None_called_twice_doesnt_leak(self):
3410
self.assertFalse('MYVAR' in os.environ)
3411
self.overrideEnv('MYVAR', '42')
3412
# We use an embedded test to make sure we fix the _captureVar bug
3413
class Test(tests.TestCase):
3415
# The first call save the 42 value
3416
self.overrideEnv('MYVAR', None)
3417
self.assertEquals(None, os.environ.get('MYVAR'))
3418
# Make sure we can call it twice
3419
self.overrideEnv('MYVAR', None)
3420
self.assertEquals(None, os.environ.get('MYVAR'))
3422
result = tests.TextTestResult(output, 0, 1)
3423
Test('test_me').run(result)
3424
if not result.wasStrictlySuccessful():
3425
self.fail(output.getvalue())
3426
# We get our value back
3427
self.assertEquals('42', os.environ.get('MYVAR'))
3430
class TestIsolatedEnv(tests.TestCase):
3431
"""Test isolating tests from os.environ.
3433
Since we use tests that are already isolated from os.environ a bit of care
3434
should be taken when designing the tests to avoid bootstrap side-effects.
3435
The tests start an already clean os.environ which allow doing valid
3436
assertions about which variables are present or not and design tests around
3440
class ScratchMonkey(tests.TestCase):
3445
def test_basics(self):
3446
# Make sure we know the definition of BZR_HOME: not part of os.environ
3447
# for tests.TestCase.
3448
self.assertTrue('BZR_HOME' in tests.isolated_environ)
3449
self.assertEquals(None, tests.isolated_environ['BZR_HOME'])
3450
# Being part of isolated_environ, BZR_HOME should not appear here
3451
self.assertFalse('BZR_HOME' in os.environ)
3452
# Make sure we know the definition of LINES: part of os.environ for
3454
self.assertTrue('LINES' in tests.isolated_environ)
3455
self.assertEquals('25', tests.isolated_environ['LINES'])
3456
self.assertEquals('25', os.environ['LINES'])
3458
def test_injecting_unknown_variable(self):
3459
# BZR_HOME is known to be absent from os.environ
3460
test = self.ScratchMonkey('test_me')
3461
tests.override_os_environ(test, {'BZR_HOME': 'foo'})
3462
self.assertEquals('foo', os.environ['BZR_HOME'])
3463
tests.restore_os_environ(test)
3464
self.assertFalse('BZR_HOME' in os.environ)
3466
def test_injecting_known_variable(self):
3467
test = self.ScratchMonkey('test_me')
3468
# LINES is known to be present in os.environ
3469
tests.override_os_environ(test, {'LINES': '42'})
3470
self.assertEquals('42', os.environ['LINES'])
3471
tests.restore_os_environ(test)
3472
self.assertEquals('25', os.environ['LINES'])
3474
def test_deleting_variable(self):
3475
test = self.ScratchMonkey('test_me')
3476
# LINES is known to be present in os.environ
3477
tests.override_os_environ(test, {'LINES': None})
3478
self.assertTrue('LINES' not in os.environ)
3479
tests.restore_os_environ(test)
3480
self.assertEquals('25', os.environ['LINES'])
3483
class TestDocTestSuiteIsolation(tests.TestCase):
3484
"""Test that `tests.DocTestSuite` isolates doc tests from os.environ.
3486
Since tests.TestCase alreay provides an isolation from os.environ, we use
3487
the clean environment as a base for testing. To precisely capture the
3488
isolation provided by tests.DocTestSuite, we use doctest.DocTestSuite to
3491
We want to make sure `tests.DocTestSuite` respect `tests.isolated_environ`,
3492
not `os.environ` so each test overrides it to suit its needs.
3496
def get_doctest_suite_for_string(self, klass, string):
3497
class Finder(doctest.DocTestFinder):
3499
def find(*args, **kwargs):
3500
test = doctest.DocTestParser().get_doctest(
3501
string, {}, 'foo', 'foo.py', 0)
3504
suite = klass(test_finder=Finder())
3507
def run_doctest_suite_for_string(self, klass, string):
3508
suite = self.get_doctest_suite_for_string(klass, string)
3510
result = tests.TextTestResult(output, 0, 1)
3512
return result, output
3514
def assertDocTestStringSucceds(self, klass, string):
3515
result, output = self.run_doctest_suite_for_string(klass, string)
3516
if not result.wasStrictlySuccessful():
3517
self.fail(output.getvalue())
3519
def assertDocTestStringFails(self, klass, string):
3520
result, output = self.run_doctest_suite_for_string(klass, string)
3521
if result.wasStrictlySuccessful():
3522
self.fail(output.getvalue())
3524
def test_injected_variable(self):
3525
self.overrideAttr(tests, 'isolated_environ', {'LINES': '42'})
3528
>>> os.environ['LINES']
3531
# doctest.DocTestSuite fails as it sees '25'
3532
self.assertDocTestStringFails(doctest.DocTestSuite, test)
3533
# tests.DocTestSuite sees '42'
3534
self.assertDocTestStringSucceds(tests.IsolatedDocTestSuite, test)
3536
def test_deleted_variable(self):
3537
self.overrideAttr(tests, 'isolated_environ', {'LINES': None})
3540
>>> os.environ.get('LINES')
3542
# doctest.DocTestSuite fails as it sees '25'
3543
self.assertDocTestStringFails(doctest.DocTestSuite, test)
3544
# tests.DocTestSuite sees None
3545
self.assertDocTestStringSucceds(tests.IsolatedDocTestSuite, test)
3548
class TestSelftestExcludePatterns(tests.TestCase):
3551
super(TestSelftestExcludePatterns, self).setUp()
3552
self.overrideAttr(tests, 'test_suite', self.suite_factory)
3554
def suite_factory(self, keep_only=None, starting_with=None):
3555
"""A test suite factory with only a few tests."""
3556
class Test(tests.TestCase):
3558
# We don't need the full class path
3559
return self._testMethodName
3566
return TestUtil.TestSuite([Test("a"), Test("b"), Test("c")])
3568
def assertTestList(self, expected, *selftest_args):
3569
# We rely on setUp installing the right test suite factory so we can
3570
# test at the command level without loading the whole test suite
3571
out, err = self.run_bzr(('selftest', '--list') + selftest_args)
3572
actual = out.splitlines()
3573
self.assertEquals(expected, actual)
3575
def test_full_list(self):
3576
self.assertTestList(['a', 'b', 'c'])
3578
def test_single_exclude(self):
3579
self.assertTestList(['b', 'c'], '-x', 'a')
3581
def test_mutiple_excludes(self):
3582
self.assertTestList(['c'], '-x', 'a', '-x', 'b')
3585
class TestCounterHooks(tests.TestCase, SelfTestHelper):
3587
_test_needs_features = [features.subunit]
3590
super(TestCounterHooks, self).setUp()
3591
class Test(tests.TestCase):
3594
super(Test, self).setUp()
3595
self.hooks = hooks.Hooks()
3596
self.hooks.add_hook('myhook', 'Foo bar blah', (2,4))
3597
self.install_counter_hook(self.hooks, 'myhook')
3602
def run_hook_once(self):
3603
for hook in self.hooks['myhook']:
3606
self.test_class = Test
3608
def assertHookCalls(self, expected_calls, test_name):
3609
test = self.test_class(test_name)
3610
result = unittest.TestResult()
3612
self.assertTrue(hasattr(test, '_counters'))
3613
self.assertTrue(test._counters.has_key('myhook'))
3614
self.assertEquals(expected_calls, test._counters['myhook'])
3616
def test_no_hook(self):
3617
self.assertHookCalls(0, 'no_hook')
3619
def test_run_hook_once(self):
3620
tt = features.testtools
3621
if tt.module.__version__ < (0, 9, 8):
3622
raise tests.TestSkipped('testtools-0.9.8 required for addDetail')
3623
self.assertHookCalls(1, 'run_hook_once')