~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_bundle.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2009-04-27 22:07:03 UTC
  • mfrom: (4301.2.5 bzr.ab.integration)
  • Revision ID: pqm@pqm.ubuntu.com-20090427220703-oy9b0mxobrksvuyq
(gbache) Handle symlinks better in bzr add

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2011 Canonical Ltd
 
1
# Copyright (C) 2004, 2005, 2006, 2007 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
27
27
    inventory,
28
28
    merge,
29
29
    osutils,
 
30
    repository,
30
31
    revision as _mod_revision,
31
 
    symbol_versioning,
32
32
    tests,
33
33
    treebuilder,
34
34
    )
35
35
from bzrlib.bundle import read_mergeable_from_url
36
36
from bzrlib.bundle.apply_bundle import install_bundle, merge_bundle
37
37
from bzrlib.bundle.bundle_data import BundleTree
 
38
from bzrlib.bzrdir import BzrDir
38
39
from bzrlib.directory_service import directories
39
40
from bzrlib.bundle.serializer import write_bundle, read_bundle, v09, v4
40
41
from bzrlib.bundle.serializer.v08 import BundleSerializerV08
41
42
from bzrlib.bundle.serializer.v09 import BundleSerializerV09
42
43
from bzrlib.bundle.serializer.v4 import BundleSerializerV4
 
44
from bzrlib.branch import Branch
43
45
from bzrlib.repofmt import knitrepo
44
46
from bzrlib.tests import (
45
47
    test_read_bundle,
48
50
from bzrlib.transform import TreeTransform
49
51
 
50
52
 
51
 
def get_text(vf, key):
52
 
    """Get the fulltext for a given revision id that is present in the vf"""
53
 
    stream = vf.get_record_stream([key], 'unordered', True)
54
 
    record = stream.next()
55
 
    return record.get_bytes_as('fulltext')
56
 
 
57
 
 
58
 
def get_inventory_text(repo, revision_id):
59
 
    """Get the fulltext for the inventory at revision id"""
60
 
    repo.lock_read()
61
 
    try:
62
 
        return get_text(repo.inventories, (revision_id,))
63
 
    finally:
64
 
        repo.unlock()
65
 
 
66
 
 
67
53
class MockTree(object):
68
 
 
69
54
    def __init__(self):
70
55
        from bzrlib.inventory import InventoryDirectory, ROOT_ID
71
56
        object.__init__(self)
76
61
 
77
62
    inventory = property(lambda x:x)
78
63
 
79
 
    def all_file_ids(self):
80
 
        return set(self.paths.keys())
 
64
    def __iter__(self):
 
65
        return self.paths.iterkeys()
81
66
 
82
67
    def __getitem__(self, file_id):
83
68
        if file_id == self.root.file_id:
113
98
            ie = InventoryDirectory(file_id, name, parent_id)
114
99
        elif kind == 'file':
115
100
            ie = InventoryFile(file_id, name, parent_id)
116
 
            ie.text_sha1 = text_sha_1
117
 
            ie.text_size = text_size
118
101
        elif kind == 'symlink':
119
102
            ie = InventoryLink(file_id, name, parent_id)
120
103
        else:
121
104
            raise errors.BzrError('unknown kind %r' % kind)
 
105
        ie.text_sha1 = text_sha_1
 
106
        ie.text_size = text_size
122
107
        return ie
123
108
 
124
109
    def add_dir(self, file_id, path):
144
129
        result.seek(0,0)
145
130
        return result
146
131
 
147
 
    def get_file_revision(self, file_id):
148
 
        return self.inventory[file_id].revision
149
 
 
150
132
    def contents_stats(self, file_id):
151
133
        if file_id not in self.contents:
152
134
            return None, None
494
476
                                 % (ancestor,))
495
477
 
496
478
                # Now check that the file contents are all correct
497
 
                for inventory_id in old.all_file_ids():
 
479
                for inventory_id in old:
498
480
                    try:
499
481
                        old_file = old.get_file(inventory_id)
500
482
                    except errors.NoSuchFile:
508
490
                old.unlock()
509
491
        if not _mod_revision.is_null(rev_id):
510
492
            rh = self.b1.revision_history()
511
 
            self.applyDeprecated(symbol_versioning.deprecated_in((2, 4, 0)),
512
 
                tree.branch.set_revision_history, rh[:rh.index(rev_id)+1])
 
493
            tree.branch.set_revision_history(rh[:rh.index(rev_id)+1])
513
494
            tree.update()
514
495
            delta = tree.changes_from(self.b1.repository.revision_tree(rev_id))
515
496
            self.assertFalse(delta.has_changed(),
577
558
        self.tree1 = self.make_branch_and_tree('b1')
578
559
        self.b1 = self.tree1.branch
579
560
 
580
 
        self.build_tree_contents([('b1/one', 'one\n')])
581
 
        self.tree1.add('one', 'one-id')
582
 
        self.tree1.set_root_id('root-id')
 
561
        open('b1/one', 'wb').write('one\n')
 
562
        self.tree1.add('one')
583
563
        self.tree1.commit('add one', rev_id='a@cset-0-1')
584
564
 
585
565
        bundle = self.get_valid_bundle('null:', 'a@cset-0-1')
596
576
                , 'b1/sub/sub/'
597
577
                , 'b1/sub/sub/nonempty.txt'
598
578
                ])
599
 
        self.build_tree_contents([('b1/sub/sub/emptyfile.txt', ''),
600
 
                                  ('b1/dir/nolastnewline.txt', 'bloop')])
 
579
        open('b1/sub/sub/emptyfile.txt', 'wb').close()
 
580
        open('b1/dir/nolastnewline.txt', 'wb').write('bloop')
601
581
        tt = TreeTransform(self.tree1)
602
582
        tt.new_file('executable', tt.root, '#!/bin/sh\n', 'exe-1', True)
603
583
        tt.apply()
636
616
 
637
617
        bundle = self.get_valid_bundle('a@cset-0-2', 'a@cset-0-3')
638
618
        self.assertRaises((errors.TestamentMismatch,
639
 
            errors.VersionedFileInvalidChecksum,
640
 
            errors.BadBundle), self.get_invalid_bundle,
 
619
            errors.VersionedFileInvalidChecksum), self.get_invalid_bundle,
641
620
            'a@cset-0-2', 'a@cset-0-3')
642
621
        # Check a rollup bundle
643
622
        bundle = self.get_valid_bundle('null:', 'a@cset-0-3')
667
646
                          verbose=False)
668
647
        bundle = self.get_valid_bundle('a@cset-0-5', 'a@cset-0-6')
669
648
        other = self.get_checkout('a@cset-0-5')
670
 
        tree1_inv = get_inventory_text(self.tree1.branch.repository,
671
 
                                       'a@cset-0-5')
672
 
        tree2_inv = get_inventory_text(other.branch.repository,
673
 
                                       'a@cset-0-5')
 
649
        tree1_inv = self.tree1.branch.repository.get_inventory_xml(
 
650
            'a@cset-0-5')
 
651
        tree2_inv = other.branch.repository.get_inventory_xml('a@cset-0-5')
674
652
        self.assertEqualDiff(tree1_inv, tree2_inv)
675
653
        other.rename_one('sub/dir/nolastnewline.txt', 'sub/nolastnewline.txt')
676
654
        other.commit('rename file', rev_id='a@cset-0-6b')
679
657
                          verbose=False)
680
658
        bundle = self.get_valid_bundle('a@cset-0-6', 'a@cset-0-7')
681
659
 
682
 
    def _test_symlink_bundle(self, link_name, link_target, new_link_target):
683
 
        link_id = 'link-1'
684
 
 
 
660
    def test_symlink_bundle(self):
685
661
        self.requireFeature(tests.SymlinkFeature)
686
662
        self.tree1 = self.make_branch_and_tree('b1')
687
663
        self.b1 = self.tree1.branch
688
 
 
689
664
        tt = TreeTransform(self.tree1)
690
 
        tt.new_symlink(link_name, tt.root, link_target, link_id)
 
665
        tt.new_symlink('link', tt.root, 'bar/foo', 'link-1')
691
666
        tt.apply()
692
667
        self.tree1.commit('add symlink', rev_id='l@cset-0-1')
693
 
        bundle = self.get_valid_bundle('null:', 'l@cset-0-1')
694
 
        if getattr(bundle ,'revision_tree', None) is not None:
695
 
            # Not all bundle formats supports revision_tree
696
 
            bund_tree = bundle.revision_tree(self.b1.repository, 'l@cset-0-1')
697
 
            self.assertEqual(link_target, bund_tree.get_symlink_target(link_id))
698
 
 
 
668
        self.get_valid_bundle('null:', 'l@cset-0-1')
699
669
        tt = TreeTransform(self.tree1)
700
 
        trans_id = tt.trans_id_tree_file_id(link_id)
 
670
        trans_id = tt.trans_id_tree_file_id('link-1')
701
671
        tt.adjust_path('link2', tt.root, trans_id)
702
672
        tt.delete_contents(trans_id)
703
 
        tt.create_symlink(new_link_target, trans_id)
 
673
        tt.create_symlink('mars', trans_id)
704
674
        tt.apply()
705
675
        self.tree1.commit('rename and change symlink', rev_id='l@cset-0-2')
706
 
        bundle = self.get_valid_bundle('l@cset-0-1', 'l@cset-0-2')
707
 
        if getattr(bundle ,'revision_tree', None) is not None:
708
 
            # Not all bundle formats supports revision_tree
709
 
            bund_tree = bundle.revision_tree(self.b1.repository, 'l@cset-0-2')
710
 
            self.assertEqual(new_link_target,
711
 
                             bund_tree.get_symlink_target(link_id))
712
 
 
 
676
        self.get_valid_bundle('l@cset-0-1', 'l@cset-0-2')
713
677
        tt = TreeTransform(self.tree1)
714
 
        trans_id = tt.trans_id_tree_file_id(link_id)
 
678
        trans_id = tt.trans_id_tree_file_id('link-1')
715
679
        tt.delete_contents(trans_id)
716
680
        tt.create_symlink('jupiter', trans_id)
717
681
        tt.apply()
718
682
        self.tree1.commit('just change symlink target', rev_id='l@cset-0-3')
719
 
        bundle = self.get_valid_bundle('l@cset-0-2', 'l@cset-0-3')
720
 
 
 
683
        self.get_valid_bundle('l@cset-0-2', 'l@cset-0-3')
721
684
        tt = TreeTransform(self.tree1)
722
 
        trans_id = tt.trans_id_tree_file_id(link_id)
 
685
        trans_id = tt.trans_id_tree_file_id('link-1')
723
686
        tt.delete_contents(trans_id)
724
687
        tt.apply()
725
688
        self.tree1.commit('Delete symlink', rev_id='l@cset-0-4')
726
 
        bundle = self.get_valid_bundle('l@cset-0-3', 'l@cset-0-4')
727
 
 
728
 
    def test_symlink_bundle(self):
729
 
        self._test_symlink_bundle('link', 'bar/foo', 'mars')
730
 
 
731
 
    def test_unicode_symlink_bundle(self):
732
 
        self.requireFeature(tests.UnicodeFilenameFeature)
733
 
        self._test_symlink_bundle(u'\N{Euro Sign}link',
734
 
                                  u'bar/\N{Euro Sign}foo',
735
 
                                  u'mars\N{Euro Sign}')
 
689
        self.get_valid_bundle('l@cset-0-3', 'l@cset-0-4')
736
690
 
737
691
    def test_binary_bundle(self):
738
692
        self.tree1 = self.make_branch_and_tree('b1')
1042
996
        bundle = read_bundle(self.create_bundle_text('null:', 'rev2')[0])
1043
997
        repo = self.make_repository('repo', format='dirstate-with-subtree')
1044
998
        bundle.install_revisions(repo)
1045
 
        inv_text = repo._get_inventory_xml('rev2')
 
999
        inv_text = repo.get_inventory_xml('rev2')
1046
1000
        self.assertNotContainsRe(inv_text, 'format="5"')
1047
1001
        self.assertContainsRe(inv_text, 'format="7"')
1048
1002
 
1068
1022
 
1069
1023
    def test_inv_hash_across_serializers(self):
1070
1024
        repo = self.make_repo_with_installed_revisions()
1071
 
        recorded_inv_sha1 = repo.get_revision('rev2').inventory_sha1
1072
 
        xml = repo._get_inventory_xml('rev2')
 
1025
        recorded_inv_sha1 = repo.get_inventory_sha1('rev2')
 
1026
        xml = repo.get_inventory_xml('rev2')
1073
1027
        self.assertEqual(osutils.sha_string(xml), recorded_inv_sha1)
1074
1028
 
1075
1029
    def test_across_models_incompatible(self):
1339
1293
        new_text = self.get_raw(StringIO(''.join(bundle_txt)))
1340
1294
        new_text = new_text.replace('<file file_id="exe-1"',
1341
1295
                                    '<file executable="y" file_id="exe-1"')
1342
 
        new_text = new_text.replace('B260', 'B275')
 
1296
        new_text = new_text.replace('B222', 'B237')
1343
1297
        bundle_txt = StringIO()
1344
1298
        bundle_txt.write(serializer._get_bundle_header('4'))
1345
1299
        bundle_txt.write('\n')
1415
1369
        branch = tree_a.branch
1416
1370
        repo_a = branch.repository
1417
1371
        tree_a.commit("base", allow_pointless=True, rev_id='A')
1418
 
        self.assertFalse(branch.repository.has_signature_for_revision_id('A'))
 
1372
        self.failIf(branch.repository.has_signature_for_revision_id('A'))
1419
1373
        try:
1420
1374
            from bzrlib.testament import Testament
1421
1375
            # monkey patch gpg signing mechanism
1445
1399
        install_bundle(repo_b, serializer.read(s))
1446
1400
 
1447
1401
 
1448
 
class V4_2aBundleTester(V4BundleTester):
 
1402
class V4WeaveBundleTester(V4BundleTester):
1449
1403
 
1450
1404
    def bzrdir_format(self):
1451
 
        return '2a'
1452
 
 
1453
 
    def get_invalid_bundle(self, base_rev_id, rev_id):
1454
 
        """Create a bundle from base_rev_id -> rev_id in built-in branch.
1455
 
        Munge the text so that it's invalid.
1456
 
 
1457
 
        :return: The in-memory bundle
1458
 
        """
1459
 
        from bzrlib.bundle import serializer
1460
 
        bundle_txt, rev_ids = self.create_bundle_text(base_rev_id, rev_id)
1461
 
        new_text = self.get_raw(StringIO(''.join(bundle_txt)))
1462
 
        # We are going to be replacing some text to set the executable bit on a
1463
 
        # file. Make sure the text replacement actually works correctly.
1464
 
        self.assertContainsRe(new_text, '(?m)B244\n\ni 1\n<inventory')
1465
 
        new_text = new_text.replace('<file file_id="exe-1"',
1466
 
                                    '<file executable="y" file_id="exe-1"')
1467
 
        new_text = new_text.replace('B244', 'B259')
1468
 
        bundle_txt = StringIO()
1469
 
        bundle_txt.write(serializer._get_bundle_header('4'))
1470
 
        bundle_txt.write('\n')
1471
 
        bundle_txt.write(new_text.encode('bz2'))
1472
 
        bundle_txt.seek(0)
1473
 
        bundle = read_bundle(bundle_txt)
1474
 
        self.valid_apply_bundle(base_rev_id, bundle)
1475
 
        return bundle
1476
 
 
1477
 
    def make_merged_branch(self):
1478
 
        builder = self.make_branch_builder('source')
1479
 
        builder.start_series()
1480
 
        builder.build_snapshot('a@cset-0-1', None, [
1481
 
            ('add', ('', 'root-id', 'directory', None)),
1482
 
            ('add', ('file', 'file-id', 'file', 'original content\n')),
1483
 
            ])
1484
 
        builder.build_snapshot('a@cset-0-2a', ['a@cset-0-1'], [
1485
 
            ('modify', ('file-id', 'new-content\n')),
1486
 
            ])
1487
 
        builder.build_snapshot('a@cset-0-2b', ['a@cset-0-1'], [
1488
 
            ('add', ('other-file', 'file2-id', 'file', 'file2-content\n')),
1489
 
            ])
1490
 
        builder.build_snapshot('a@cset-0-3', ['a@cset-0-2a', 'a@cset-0-2b'], [
1491
 
            ('add', ('other-file', 'file2-id', 'file', 'file2-content\n')),
1492
 
            ])
1493
 
        builder.finish_series()
1494
 
        self.b1 = builder.get_branch()
1495
 
        self.b1.lock_read()
1496
 
        self.addCleanup(self.b1.unlock)
1497
 
 
1498
 
    def make_bundle_just_inventories(self, base_revision_id,
1499
 
                                     target_revision_id,
1500
 
                                     revision_ids):
1501
 
        sio = StringIO()
1502
 
        writer = v4.BundleWriteOperation(base_revision_id, target_revision_id,
1503
 
                                         self.b1.repository, sio)
1504
 
        writer.bundle.begin()
1505
 
        writer._add_inventory_mpdiffs_from_serializer(revision_ids)
1506
 
        writer.bundle.end()
1507
 
        sio.seek(0)
1508
 
        return sio
1509
 
 
1510
 
    def test_single_inventory_multiple_parents_as_xml(self):
1511
 
        self.make_merged_branch()
1512
 
        sio = self.make_bundle_just_inventories('a@cset-0-1', 'a@cset-0-3',
1513
 
                                                ['a@cset-0-3'])
1514
 
        reader = v4.BundleReader(sio, stream_input=False)
1515
 
        records = list(reader.iter_records())
1516
 
        self.assertEqual(1, len(records))
1517
 
        (bytes, metadata, repo_kind, revision_id,
1518
 
         file_id) = records[0]
1519
 
        self.assertIs(None, file_id)
1520
 
        self.assertEqual('a@cset-0-3', revision_id)
1521
 
        self.assertEqual('inventory', repo_kind)
1522
 
        self.assertEqual({'parents': ['a@cset-0-2a', 'a@cset-0-2b'],
1523
 
                          'sha1': '09c53b0c4de0895e11a2aacc34fef60a6e70865c',
1524
 
                          'storage_kind': 'mpdiff',
1525
 
                         }, metadata)
1526
 
        # We should have an mpdiff that takes some lines from both parents.
1527
 
        self.assertEqualDiff(
1528
 
            'i 1\n'
1529
 
            '<inventory format="10" revision_id="a@cset-0-3">\n'
1530
 
            '\n'
1531
 
            'c 0 1 1 2\n'
1532
 
            'c 1 3 3 2\n', bytes)
1533
 
 
1534
 
    def test_single_inv_no_parents_as_xml(self):
1535
 
        self.make_merged_branch()
1536
 
        sio = self.make_bundle_just_inventories('null:', 'a@cset-0-1',
1537
 
                                                ['a@cset-0-1'])
1538
 
        reader = v4.BundleReader(sio, stream_input=False)
1539
 
        records = list(reader.iter_records())
1540
 
        self.assertEqual(1, len(records))
1541
 
        (bytes, metadata, repo_kind, revision_id,
1542
 
         file_id) = records[0]
1543
 
        self.assertIs(None, file_id)
1544
 
        self.assertEqual('a@cset-0-1', revision_id)
1545
 
        self.assertEqual('inventory', repo_kind)
1546
 
        self.assertEqual({'parents': [],
1547
 
                          'sha1': 'a13f42b142d544aac9b085c42595d304150e31a2',
1548
 
                          'storage_kind': 'mpdiff',
1549
 
                         }, metadata)
1550
 
        # We should have an mpdiff that takes some lines from both parents.
1551
 
        self.assertEqualDiff(
1552
 
            'i 4\n'
1553
 
            '<inventory format="10" revision_id="a@cset-0-1">\n'
1554
 
            '<directory file_id="root-id" name=""'
1555
 
                ' revision="a@cset-0-1" />\n'
1556
 
            '<file file_id="file-id" name="file" parent_id="root-id"'
1557
 
                ' revision="a@cset-0-1"'
1558
 
                ' text_sha1="09c2f8647e14e49e922b955c194102070597c2d1"'
1559
 
                ' text_size="17" />\n'
1560
 
            '</inventory>\n'
1561
 
            '\n', bytes)
1562
 
 
1563
 
    def test_multiple_inventories_as_xml(self):
1564
 
        self.make_merged_branch()
1565
 
        sio = self.make_bundle_just_inventories('a@cset-0-1', 'a@cset-0-3',
1566
 
            ['a@cset-0-2a', 'a@cset-0-2b', 'a@cset-0-3'])
1567
 
        reader = v4.BundleReader(sio, stream_input=False)
1568
 
        records = list(reader.iter_records())
1569
 
        self.assertEqual(3, len(records))
1570
 
        revision_ids = [rev_id for b, m, k, rev_id, f in records]
1571
 
        self.assertEqual(['a@cset-0-2a', 'a@cset-0-2b', 'a@cset-0-3'],
1572
 
                         revision_ids)
1573
 
        metadata_2a = records[0][1]
1574
 
        self.assertEqual({'parents': ['a@cset-0-1'],
1575
 
                          'sha1': '1e105886d62d510763e22885eec733b66f5f09bf',
1576
 
                          'storage_kind': 'mpdiff',
1577
 
                         }, metadata_2a)
1578
 
        metadata_2b = records[1][1]
1579
 
        self.assertEqual({'parents': ['a@cset-0-1'],
1580
 
                          'sha1': 'f03f12574bdb5ed2204c28636c98a8547544ccd8',
1581
 
                          'storage_kind': 'mpdiff',
1582
 
                         }, metadata_2b)
1583
 
        metadata_3 = records[2][1]
1584
 
        self.assertEqual({'parents': ['a@cset-0-2a', 'a@cset-0-2b'],
1585
 
                          'sha1': '09c53b0c4de0895e11a2aacc34fef60a6e70865c',
1586
 
                          'storage_kind': 'mpdiff',
1587
 
                         }, metadata_3)
1588
 
        bytes_2a = records[0][0]
1589
 
        self.assertEqualDiff(
1590
 
            'i 1\n'
1591
 
            '<inventory format="10" revision_id="a@cset-0-2a">\n'
1592
 
            '\n'
1593
 
            'c 0 1 1 1\n'
1594
 
            'i 1\n'
1595
 
            '<file file_id="file-id" name="file" parent_id="root-id"'
1596
 
                ' revision="a@cset-0-2a"'
1597
 
                ' text_sha1="50f545ff40e57b6924b1f3174b267ffc4576e9a9"'
1598
 
                ' text_size="12" />\n'
1599
 
            '\n'
1600
 
            'c 0 3 3 1\n', bytes_2a)
1601
 
        bytes_2b = records[1][0]
1602
 
        self.assertEqualDiff(
1603
 
            'i 1\n'
1604
 
            '<inventory format="10" revision_id="a@cset-0-2b">\n'
1605
 
            '\n'
1606
 
            'c 0 1 1 2\n'
1607
 
            'i 1\n'
1608
 
            '<file file_id="file2-id" name="other-file" parent_id="root-id"'
1609
 
                ' revision="a@cset-0-2b"'
1610
 
                ' text_sha1="b46c0c8ea1e5ef8e46fc8894bfd4752a88ec939e"'
1611
 
                ' text_size="14" />\n'
1612
 
            '\n'
1613
 
            'c 0 3 4 1\n', bytes_2b)
1614
 
        bytes_3 = records[2][0]
1615
 
        self.assertEqualDiff(
1616
 
            'i 1\n'
1617
 
            '<inventory format="10" revision_id="a@cset-0-3">\n'
1618
 
            '\n'
1619
 
            'c 0 1 1 2\n'
1620
 
            'c 1 3 3 2\n', bytes_3)
1621
 
 
1622
 
    def test_creating_bundle_preserves_chk_pages(self):
1623
 
        self.make_merged_branch()
1624
 
        target = self.b1.bzrdir.sprout('target',
1625
 
                                       revision_id='a@cset-0-2a').open_branch()
1626
 
        bundle_txt, rev_ids = self.create_bundle_text('a@cset-0-2a',
1627
 
                                                      'a@cset-0-3')
1628
 
        self.assertEqual(['a@cset-0-2b', 'a@cset-0-3'], rev_ids)
1629
 
        bundle = read_bundle(bundle_txt)
1630
 
        target.lock_write()
1631
 
        self.addCleanup(target.unlock)
1632
 
        install_bundle(target.repository, bundle)
1633
 
        inv1 = self.b1.repository.inventories.get_record_stream([
1634
 
            ('a@cset-0-3',)], 'unordered',
1635
 
            True).next().get_bytes_as('fulltext')
1636
 
        inv2 = target.repository.inventories.get_record_stream([
1637
 
            ('a@cset-0-3',)], 'unordered',
1638
 
            True).next().get_bytes_as('fulltext')
1639
 
        self.assertEqualDiff(inv1, inv2)
 
1405
        return 'metaweave'
1640
1406
 
1641
1407
 
1642
1408
class MungedBundleTester(object):
1817
1583
            def look_up(self, name, url):
1818
1584
                return 'source'
1819
1585
        directories.register('foo:', FooService, 'Testing directory service')
1820
 
        self.addCleanup(directories.remove, 'foo:')
 
1586
        self.addCleanup(lambda: directories.remove('foo:'))
1821
1587
        self.build_tree_contents([('./foo:bar', out.getvalue())])
1822
1588
        self.assertRaises(errors.NotABundle, read_mergeable_from_url,
1823
1589
                          'foo:bar')
1824
1590
 
1825
 
    def test_infinite_redirects_are_not_a_bundle(self):
1826
 
        """If a URL causes TooManyRedirections then NotABundle is raised.
1827
 
        """
1828
 
        from bzrlib.tests.blackbox.test_push import RedirectingMemoryServer
1829
 
        server = RedirectingMemoryServer()
1830
 
        self.start_server(server)
1831
 
        url = server.get_url() + 'infinite-loop'
1832
 
        self.assertRaises(errors.NotABundle, read_mergeable_from_url, url)
1833
 
 
1834
1591
    def test_smart_server_connection_reset(self):
1835
1592
        """If a smart server connection fails during the attempt to read a
1836
1593
        bundle, then the ConnectionReset error should be propagated.
1837
1594
        """
1838
1595
        # Instantiate a server that will provoke a ConnectionReset
1839
1596
        sock_server = _DisconnectingTCPServer()
1840
 
        self.start_server(sock_server)
 
1597
        sock_server.setUp()
 
1598
        self.addCleanup(sock_server.tearDown)
1841
1599
        # We don't really care what the url is since the server will close the
1842
1600
        # connection without interpreting it
1843
1601
        url = sock_server.get_url()
1847
1605
class _DisconnectingTCPServer(object):
1848
1606
    """A TCP server that immediately closes any connection made to it."""
1849
1607
 
1850
 
    def start_server(self):
 
1608
    def setUp(self):
1851
1609
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1852
1610
        self.sock.bind(('127.0.0.1', 0))
1853
1611
        self.sock.listen(1)
1865
1623
    def get_url(self):
1866
1624
        return 'bzr://127.0.0.1:%d/' % (self.port,)
1867
1625
 
1868
 
    def stop_server(self):
 
1626
    def tearDown(self):
1869
1627
        try:
1870
1628
            # make sure the thread dies by connecting to the listening socket,
1871
1629
            # just in case the test failed to do so.
1876
1634
            pass
1877
1635
        self.sock.close()
1878
1636
        self.thread.join()
 
1637