~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_dirstate.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2009-04-09 20:23:07 UTC
  • mfrom: (4265.1.4 bbc-merge)
  • Revision ID: pqm@pqm.ubuntu.com-20090409202307-n0depb16qepoe21o
(jam) Change _fetch_uses_deltas = False for CHK repos until we can
        write a better fix.

Show diffs side-by-side

added added

removed removed

Lines of Context:
23
23
    dirstate,
24
24
    errors,
25
25
    inventory,
26
 
    memorytree,
27
26
    osutils,
28
27
    revision as _mod_revision,
29
 
    tests,
30
28
    )
31
 
from bzrlib.tests import test_osutils
 
29
from bzrlib.memorytree import MemoryTree
 
30
from bzrlib.tests import (
 
31
        SymlinkFeature,
 
32
        TestCase,
 
33
        TestCaseInTempDir,
 
34
        TestCaseWithTransport,
 
35
        )
32
36
 
33
37
 
34
38
# TODO:
44
48
# set_path_id  setting id when state is in memory modified
45
49
 
46
50
 
47
 
def load_tests(basic_tests, module, loader):
48
 
    suite = loader.suiteClass()
49
 
    dir_reader_tests, remaining_tests = tests.split_suite_by_condition(
50
 
        basic_tests, tests.condition_isinstance(TestCaseWithDirState))
51
 
    tests.multiply_tests(dir_reader_tests,
52
 
                         test_osutils.dir_reader_scenarios(), suite)
53
 
    suite.addTest(remaining_tests)
54
 
    return suite
55
 
 
56
 
 
57
 
class TestCaseWithDirState(tests.TestCaseWithTransport):
 
51
class TestCaseWithDirState(TestCaseWithTransport):
58
52
    """Helper functions for creating DirState objects with various content."""
59
53
 
60
 
    # Set by load_tests
61
 
    _dir_reader_class = None
62
 
    _native_to_unicode = None # Not used yet
63
 
 
64
 
    def setUp(self):
65
 
        tests.TestCaseWithTransport.setUp(self)
66
 
 
67
 
        # Save platform specific info and reset it
68
 
        cur_dir_reader = osutils._selected_dir_reader
69
 
 
70
 
        def restore():
71
 
            osutils._selected_dir_reader = cur_dir_reader
72
 
        self.addCleanup(restore)
73
 
 
74
 
        osutils._selected_dir_reader = self._dir_reader_class()
75
 
 
76
54
    def create_empty_dirstate(self):
77
55
        """Return a locked but empty dirstate"""
78
56
        state = dirstate.DirState.initialize('dirstate')
419
397
            (('', '', tree.get_root_id()), # common details
420
398
             [('d', '', 0, False, dirstate.DirState.NULLSTAT), # current tree
421
399
              ('d', '', 0, False, rev_id), # first parent details
422
 
              ('d', '', 0, False, rev_id), # second parent details
 
400
              ('d', '', 0, False, rev_id2), # second parent details
423
401
             ])])
424
402
        state = dirstate.DirState.from_tree(tree, 'dirstate')
425
403
        self.check_state_with_reopen(expected_result, state)
500
478
            (('', '', tree.get_root_id()), # common details
501
479
             [('d', '', 0, False, dirstate.DirState.NULLSTAT), # current tree
502
480
              ('d', '', 0, False, rev_id), # first parent details
503
 
              ('d', '', 0, False, rev_id), # second parent details
 
481
              ('d', '', 0, False, rev_id2), # second parent details
504
482
             ]),
505
483
            (('', 'a file', 'a-file-id'), # common
506
484
             [('f', '', 0, False, dirstate.DirState.NULLSTAT), # current
827
805
        finally:
828
806
            tree.unlock()
829
807
 
 
808
 
830
809
    def test_set_state_from_inventory_mixed_paths(self):
831
810
        tree1 = self.make_branch_and_tree('tree1')
832
811
        self.build_tree(['tree1/a/', 'tree1/a/b/', 'tree1/a-b/',
941
920
        finally:
942
921
            state.unlock()
943
922
 
 
923
 
944
924
    def test_set_parent_trees_no_content(self):
945
925
        # set_parent_trees is a slow but important api to support.
946
926
        tree1 = self.make_branch_and_memory_tree('tree1')
951
931
        finally:
952
932
            tree1.unlock()
953
933
        branch2 = tree1.branch.bzrdir.clone('tree2').open_branch()
954
 
        tree2 = memorytree.MemoryTree.create_on_branch(branch2)
 
934
        tree2 = MemoryTree.create_on_branch(branch2)
955
935
        tree2.lock_write()
956
936
        try:
957
937
            revid2 = tree2.commit('foo')
1000
980
                [(('', '', root_id), [
1001
981
                  ('d', '', 0, False, dirstate.DirState.NULLSTAT),
1002
982
                  ('d', '', 0, False, revid1),
1003
 
                  ('d', '', 0, False, revid1)
 
983
                  ('d', '', 0, False, revid2)
1004
984
                  ])],
1005
985
                list(state._iter_entries()))
1006
986
        finally:
1021
1001
        finally:
1022
1002
            tree1.unlock()
1023
1003
        branch2 = tree1.branch.bzrdir.clone('tree2').open_branch()
1024
 
        tree2 = memorytree.MemoryTree.create_on_branch(branch2)
 
1004
        tree2 = MemoryTree.create_on_branch(branch2)
1025
1005
        tree2.lock_write()
1026
1006
        try:
1027
1007
            tree2.put_file_bytes_non_atomic('file-id', 'new file-content')
1034
1014
            (('', '', root_id), [
1035
1015
             ('d', '', 0, False, dirstate.DirState.NULLSTAT),
1036
1016
             ('d', '', 0, False, revid1.encode('utf8')),
1037
 
             ('d', '', 0, False, revid1.encode('utf8'))
 
1017
             ('d', '', 0, False, revid2.encode('utf8'))
1038
1018
             ]),
1039
1019
            (('', 'a file', 'file-id'), [
1040
1020
             ('a', '', 0, False, ''),
1086
1066
            state.unlock()
1087
1067
        state = dirstate.DirState.on_file('dirstate')
1088
1068
        state.lock_read()
1089
 
        self.addCleanup(state.unlock)
1090
 
        self.assertEqual(expected_entries, list(state._iter_entries()))
 
1069
        try:
 
1070
            self.assertEqual(expected_entries, list(state._iter_entries()))
 
1071
        finally:
 
1072
            state.unlock()
1091
1073
 
1092
1074
    def test_add_path_to_unversioned_directory(self):
1093
1075
        """Adding a path to an unversioned directory should error.
1098
1080
        """
1099
1081
        self.build_tree(['unversioned/', 'unversioned/a file'])
1100
1082
        state = dirstate.DirState.initialize('dirstate')
1101
 
        self.addCleanup(state.unlock)
1102
 
        self.assertRaises(errors.NotVersionedError, state.add,
1103
 
                          'unversioned/a file', 'a-file-id', 'file', None, None)
 
1083
        try:
 
1084
            self.assertRaises(errors.NotVersionedError, state.add,
 
1085
                'unversioned/a file', 'a-file-id', 'file', None, None)
 
1086
        finally:
 
1087
            state.unlock()
1104
1088
 
1105
1089
    def test_add_directory_to_root_no_parents_all_data(self):
1106
1090
        # The most trivial addition of a dir is when there are no parents and
1126
1110
            state.unlock()
1127
1111
        state = dirstate.DirState.on_file('dirstate')
1128
1112
        state.lock_read()
1129
 
        self.addCleanup(state.unlock)
1130
1113
        state._validate()
1131
 
        self.assertEqual(expected_entries, list(state._iter_entries()))
 
1114
        try:
 
1115
            self.assertEqual(expected_entries, list(state._iter_entries()))
 
1116
        finally:
 
1117
            state.unlock()
1132
1118
 
1133
 
    def _test_add_symlink_to_root_no_parents_all_data(self, link_name, target):
 
1119
    def test_add_symlink_to_root_no_parents_all_data(self):
1134
1120
        # The most trivial addition of a symlink when there are no parents and
1135
1121
        # its in the root and all data about the file is supplied
1136
1122
        # bzr doesn't support fake symlinks on windows, yet.
1137
 
        self.requireFeature(tests.SymlinkFeature)
1138
 
        os.symlink(target, link_name)
1139
 
        stat = os.lstat(link_name)
 
1123
        self.requireFeature(SymlinkFeature)
 
1124
        os.symlink('target', 'a link')
 
1125
        stat = os.lstat('a link')
1140
1126
        expected_entries = [
1141
1127
            (('', '', 'TREE_ROOT'), [
1142
1128
             ('d', '', 0, False, dirstate.DirState.NULLSTAT), # current tree
1143
1129
             ]),
1144
 
            (('', link_name.encode('UTF-8'), 'a link id'), [
1145
 
             ('l', target.encode('UTF-8'), stat[6],
1146
 
              False, dirstate.pack_stat(stat)), # current tree
 
1130
            (('', 'a link', 'a link id'), [
 
1131
             ('l', 'target', 6, False, dirstate.pack_stat(stat)), # current tree
1147
1132
             ]),
1148
1133
            ]
1149
1134
        state = dirstate.DirState.initialize('dirstate')
1150
1135
        try:
1151
 
            state.add(link_name, 'a link id', 'symlink', stat,
1152
 
                      target.encode('UTF-8'))
 
1136
            state.add('a link', 'a link id', 'symlink', stat, 'target')
1153
1137
            # having added it, it should be in the output of iter_entries.
1154
1138
            self.assertEqual(expected_entries, list(state._iter_entries()))
1155
1139
            # saving and reloading should not affect this.
1158
1142
            state.unlock()
1159
1143
        state = dirstate.DirState.on_file('dirstate')
1160
1144
        state.lock_read()
1161
 
        self.addCleanup(state.unlock)
1162
 
        self.assertEqual(expected_entries, list(state._iter_entries()))
1163
 
 
1164
 
    def test_add_symlink_to_root_no_parents_all_data(self):
1165
 
        self._test_add_symlink_to_root_no_parents_all_data('a link', 'target')
1166
 
 
1167
 
    def test_add_symlink_unicode_to_root_no_parents_all_data(self):
1168
 
        self.requireFeature(tests.UnicodeFilenameFeature)
1169
 
        self._test_add_symlink_to_root_no_parents_all_data(
1170
 
            u'\N{Euro Sign}link', u'targ\N{Euro Sign}et')
 
1145
        try:
 
1146
            self.assertEqual(expected_entries, list(state._iter_entries()))
 
1147
        finally:
 
1148
            state.unlock()
1171
1149
 
1172
1150
    def test_add_directory_and_child_no_parents_all_data(self):
1173
1151
        # after adding a directory, we should be able to add children to it.
1198
1176
            state.unlock()
1199
1177
        state = dirstate.DirState.on_file('dirstate')
1200
1178
        state.lock_read()
1201
 
        self.addCleanup(state.unlock)
1202
 
        self.assertEqual(expected_entries, list(state._iter_entries()))
 
1179
        try:
 
1180
            self.assertEqual(expected_entries, list(state._iter_entries()))
 
1181
        finally:
 
1182
            state.unlock()
1203
1183
 
1204
1184
    def test_add_tree_reference(self):
1205
1185
        # make a dirstate and add a tree reference
1219
1199
            state.unlock()
1220
1200
        # now check we can read it back
1221
1201
        state.lock_read()
1222
 
        self.addCleanup(state.unlock)
1223
1202
        state._validate()
1224
 
        entry2 = state._get_entry(0, 'subdir-id', 'subdir')
1225
 
        self.assertEqual(entry, entry2)
1226
 
        self.assertEqual(entry, expected_entry)
1227
 
        # and lookup by id should work too
1228
 
        entry2 = state._get_entry(0, fileid_utf8='subdir-id')
1229
 
        self.assertEqual(entry, expected_entry)
 
1203
        try:
 
1204
            entry2 = state._get_entry(0, 'subdir-id', 'subdir')
 
1205
            self.assertEqual(entry, entry2)
 
1206
            self.assertEqual(entry, expected_entry)
 
1207
            # and lookup by id should work too
 
1208
            entry2 = state._get_entry(0, fileid_utf8='subdir-id')
 
1209
            self.assertEqual(entry, expected_entry)
 
1210
        finally:
 
1211
            state.unlock()
1230
1212
 
1231
1213
    def test_add_forbidden_names(self):
1232
1214
        state = dirstate.DirState.initialize('dirstate')
1236
1218
        self.assertRaises(errors.BzrError,
1237
1219
            state.add, '..', 'ass-id', 'directory', None, None)
1238
1220
 
1239
 
    def test_set_state_with_rename_b_a_bug_395556(self):
1240
 
        # bug 395556 uncovered a bug where the dirstate ends up with a false
1241
 
        # relocation record - in a tree with no parents there should be no
1242
 
        # absent or relocated records. This then leads to further corruption
1243
 
        # when a commit occurs, as the incorrect relocation gathers an
1244
 
        # incorrect absent in tree 1, and future changes go to pot.
1245
 
        tree1 = self.make_branch_and_tree('tree1')
1246
 
        self.build_tree(['tree1/b'])
1247
 
        tree1.lock_write()
1248
 
        try:
1249
 
            tree1.add(['b'], ['b-id'])
1250
 
            root_id = tree1.get_root_id()
1251
 
            inv = tree1.inventory
1252
 
            state = dirstate.DirState.initialize('dirstate')
1253
 
            try:
1254
 
                # Set the initial state with 'b'
1255
 
                state.set_state_from_inventory(inv)
1256
 
                inv.rename('b-id', root_id, 'a')
1257
 
                # Set the new state with 'a', which currently corrupts.
1258
 
                state.set_state_from_inventory(inv)
1259
 
                expected_result1 = [('', '', root_id, 'd'),
1260
 
                                    ('', 'a', 'b-id', 'f'),
1261
 
                                   ]
1262
 
                values = []
1263
 
                for entry in state._iter_entries():
1264
 
                    values.append(entry[0] + entry[1][0][:1])
1265
 
                self.assertEqual(expected_result1, values)
1266
 
            finally:
1267
 
                state.unlock()
1268
 
        finally:
1269
 
            tree1.unlock()
1270
 
 
1271
1221
 
1272
1222
class TestGetLines(TestCaseWithDirState):
1273
1223
 
1602
1552
            list(state._iter_child_entries(1, '')))
1603
1553
 
1604
1554
 
1605
 
class TestDirstateSortOrder(tests.TestCaseWithTransport):
 
1555
class TestDirstateSortOrder(TestCaseWithTransport):
1606
1556
    """Test that DirState adds entries in the right order."""
1607
1557
 
1608
1558
    def test_add_sorting(self):
1724
1674
            st.st_ino, st.st_mode)
1725
1675
 
1726
1676
 
1727
 
class TestPackStat(tests.TestCaseWithTransport):
 
1677
class TestPackStat(TestCaseWithTransport):
1728
1678
 
1729
1679
    def assertPackStat(self, expected, stat_value):
1730
1680
        """Check the packed and serialized form of a stat value."""
2257
2207
        self.assertEqual(exp_dirblocks, state._dirblocks)
2258
2208
 
2259
2209
 
2260
 
class Test_InvEntryToDetails(tests.TestCase):
 
2210
class Test_InvEntryToDetails(TestCaseWithDirState):
2261
2211
 
2262
2212
    def assertDetails(self, expected, inv_entry):
2263
2213
        details = dirstate.DirState._inv_entry_to_details(inv_entry)
2270
2220
        self.assertIsInstance(tree_data, str)
2271
2221
 
2272
2222
    def test_unicode_symlink(self):
2273
 
        inv_entry = inventory.InventoryLink('link-file-id',
2274
 
                                            u'nam\N{Euro Sign}e',
 
2223
        # In general, the code base doesn't support a target that contains
 
2224
        # non-ascii characters. So we just assert tha
 
2225
        inv_entry = inventory.InventoryLink('link-file-id', 'name',
2275
2226
                                            'link-parent-id')
2276
2227
        inv_entry.revision = 'link-revision-id'
2277
 
        target = u'link-targ\N{Euro Sign}t'
2278
 
        inv_entry.symlink_target = target
2279
 
        self.assertDetails(('l', target.encode('UTF-8'), 0, False,
2280
 
                            'link-revision-id'), inv_entry)
2281
 
 
2282
 
 
2283
 
class TestSHA1Provider(tests.TestCaseInTempDir):
 
2228
        inv_entry.symlink_target = u'link-target'
 
2229
        details = self.assertDetails(('l', 'link-target', 0, False,
 
2230
                                      'link-revision-id'), inv_entry)
 
2231
 
 
2232
 
 
2233
class TestSHA1Provider(TestCaseInTempDir):
2284
2234
 
2285
2235
    def test_sha1provider_is_an_interface(self):
2286
2236
        p = dirstate.SHA1Provider()