~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: 2007-06-28 07:08:27 UTC
  • mfrom: (2553.1.3 integration)
  • Revision ID: pqm@pqm.ubuntu.com-20070628070827-h5s313dg5tnag9vj
(robertc) Show the names of commit hooks during commit.

Show diffs side-by-side

added added

removed removed

Lines of Context:
189
189
              c
190
190
              d/
191
191
                e
192
 
            b-c
193
192
            f
194
193
        """
195
194
        tree = self.make_branch_and_tree('tree')
196
 
        paths = ['a', 'b/', 'b/c', 'b/d/', 'b/d/e', 'b-c', 'f']
197
 
        file_ids = ['a-id', 'b-id', 'c-id', 'd-id', 'e-id', 'b-c-id', 'f-id']
 
195
        paths = ['a', 'b/', 'b/c', 'b/d/', 'b/d/e', 'f']
 
196
        file_ids = ['a-id', 'b-id', 'c-id', 'd-id', 'e-id', 'f-id']
198
197
        self.build_tree(['tree/' + p for p in paths])
199
198
        tree.set_root_id('TREE_ROOT')
200
199
        tree.add([p.rstrip('/') for p in paths], file_ids)
201
200
        tree.commit('initial', rev_id='rev-1')
202
201
        revision_id = 'rev-1'
203
202
        # a_packed_stat = dirstate.pack_stat(os.stat('tree/a'))
204
 
        t = self.get_transport('tree')
 
203
        t = self.get_transport().clone('tree')
205
204
        a_text = t.get_bytes('a')
206
205
        a_sha = osutils.sha_string(a_text)
207
206
        a_len = len(a_text)
215
214
        e_text = t.get_bytes('b/d/e')
216
215
        e_sha = osutils.sha_string(e_text)
217
216
        e_len = len(e_text)
218
 
        b_c_text = t.get_bytes('b-c')
219
 
        b_c_sha = osutils.sha_string(b_c_text)
220
 
        b_c_len = len(b_c_text)
221
217
        # f_packed_stat = dirstate.pack_stat(os.stat('tree/f'))
222
218
        f_text = t.get_bytes('f')
223
219
        f_sha = osutils.sha_string(f_text)
248
244
                      ('f', '', 0, False, null_stat),
249
245
                      ('f', e_sha, e_len, False, revision_id),
250
246
                     ]),
251
 
            'b-c':(('', 'b-c', 'b-c-id'), [
252
 
                      ('f', '', 0, False, null_stat),
253
 
                      ('f', b_c_sha, b_c_len, False, revision_id),
254
 
                     ]),
255
247
            'f':(('', 'f', 'f-id'), [
256
248
                  ('f', '', 0, False, null_stat),
257
249
                  ('f', f_sha, f_len, False, revision_id),
284
276
        tree, state, expected = self.create_basic_dirstate()
285
277
        # Now we will just remove and add every file so we get an extra entry
286
278
        # per entry. Unversion in reverse order so we handle subdirs
287
 
        tree.unversion(['f-id', 'b-c-id', 'e-id', 'd-id', 'c-id', 'b-id', 'a-id'])
288
 
        tree.add(['a', 'b', 'b/c', 'b/d', 'b/d/e', 'b-c', 'f'],
289
 
                 ['a-id2', 'b-id2', 'c-id2', 'd-id2', 'e-id2', 'b-c-id2', 'f-id2'])
 
279
        tree.unversion(['f-id', 'e-id', 'd-id', 'c-id', 'b-id', 'a-id'])
 
280
        tree.add(['a', 'b', 'b/c', 'b/d', 'b/d/e', 'f'],
 
281
                 ['a-id2', 'b-id2', 'c-id2', 'd-id2', 'e-id2', 'f-id2'])
290
282
 
291
283
        # Update the expected dictionary.
292
 
        for path in ['a', 'b', 'b/c', 'b/d', 'b/d/e', 'b-c', 'f']:
 
284
        for path in ['a', 'b', 'b/c', 'b/d', 'b/d/e', 'f']:
293
285
            orig = expected[path]
294
286
            path2 = path + '2'
295
287
            # This record was deleted in the current tree
352
344
            state.lock_read()
353
345
        return tree, state, expected
354
346
 
355
 
 
356
347
class TestTreeToDirState(TestCaseWithDirState):
357
348
 
358
349
    def test_empty_to_dirstate(self):
1827
1818
class TestBisect(TestCaseWithDirState):
1828
1819
    """Test the ability to bisect into the disk format."""
1829
1820
 
 
1821
 
1830
1822
    def assertBisect(self, expected_map, map_keys, state, paths):
1831
1823
        """Assert that bisecting for paths returns the right result.
1832
1824
 
1837
1829
                      (dir, name) tuples, and sorted according to how _bisect
1838
1830
                      requires.
1839
1831
        """
1840
 
        result = state._bisect(paths)
 
1832
        dir_names = sorted(osutils.split(p) for p in paths)
 
1833
        result = state._bisect(dir_names)
1841
1834
        # For now, results are just returned in whatever order we read them.
1842
1835
        # We could sort by (dir, name, file_id) or something like that, but in
1843
1836
        # the end it would still be fairly arbitrary, and we don't want the
1844
1837
        # extra overhead if we can avoid it. So sort everything to make sure
1845
1838
        # equality is true
1846
 
        assert len(map_keys) == len(paths)
 
1839
        assert len(map_keys) == len(dir_names)
1847
1840
        expected = {}
1848
 
        for path, keys in zip(paths, map_keys):
 
1841
        for dir_name, keys in zip(dir_names, map_keys):
1849
1842
            if keys is None:
1850
1843
                # This should not be present in the output
1851
1844
                continue
1852
 
            expected[path] = sorted(expected_map[k] for k in keys)
 
1845
            expected[dir_name] = sorted(expected_map[k] for k in keys)
1853
1846
 
1854
 
        # The returned values are just arranged randomly based on when they
1855
 
        # were read, for testing, make sure it is properly sorted.
1856
 
        for path in result:
1857
 
            result[path].sort()
 
1847
        for dir_name in result:
 
1848
            result[dir_name].sort()
1858
1849
 
1859
1850
        self.assertEqual(expected, result)
1860
1851
 
1897
1888
            dir_name_id, trees_info = entry
1898
1889
            expected[dir_name_id] = trees_info
1899
1890
 
1900
 
        result = state._bisect_recursive(paths)
 
1891
        dir_names = sorted(osutils.split(p) for p in paths)
 
1892
        result = state._bisect_recursive(dir_names)
1901
1893
 
1902
1894
        self.assertEqual(expected, result)
1903
1895
 
1912
1904
        self.assertBisect(expected, [['b/c']], state, ['b/c'])
1913
1905
        self.assertBisect(expected, [['b/d']], state, ['b/d'])
1914
1906
        self.assertBisect(expected, [['b/d/e']], state, ['b/d/e'])
1915
 
        self.assertBisect(expected, [['b-c']], state, ['b-c'])
1916
1907
        self.assertBisect(expected, [['f']], state, ['f'])
1917
1908
 
1918
1909
    def test_bisect_multi(self):
1921
1912
        # Bisect should be capable of finding multiple entries at the same time
1922
1913
        self.assertBisect(expected, [['a'], ['b'], ['f']],
1923
1914
                          state, ['a', 'b', 'f'])
 
1915
        # ('', 'f') sorts before the others
1924
1916
        self.assertBisect(expected, [['f'], ['b/d'], ['b/d/e']],
1925
 
                          state, ['f', 'b/d', 'b/d/e'])
1926
 
        self.assertBisect(expected, [['b'], ['b-c'], ['b/c']],
1927
 
                          state, ['b', 'b-c', 'b/c'])
 
1917
                          state, ['b/d', 'b/d/e', 'f'])
1928
1918
 
1929
1919
    def test_bisect_one_page(self):
1930
1920
        """Test bisect when there is only 1 page to read"""
1936
1926
        self.assertBisect(expected,[['b/c']], state, ['b/c'])
1937
1927
        self.assertBisect(expected,[['b/d']], state, ['b/d'])
1938
1928
        self.assertBisect(expected,[['b/d/e']], state, ['b/d/e'])
1939
 
        self.assertBisect(expected,[['b-c']], state, ['b-c'])
1940
1929
        self.assertBisect(expected,[['f']], state, ['f'])
1941
1930
        self.assertBisect(expected,[['a'], ['b'], ['f']],
1942
1931
                          state, ['a', 'b', 'f'])
1943
 
        self.assertBisect(expected, [['b/d'], ['b/d/e'], ['f']],
 
1932
        # ('', 'f') sorts before the others
 
1933
        self.assertBisect(expected, [['f'], ['b/d'], ['b/d/e']],
1944
1934
                          state, ['b/d', 'b/d/e', 'f'])
1945
 
        self.assertBisect(expected, [['b'], ['b/c'], ['b-c']],
1946
 
                          state, ['b', 'b/c', 'b-c'])
1947
1935
 
1948
1936
    def test_bisect_duplicate_paths(self):
1949
1937
        """When bisecting for a path, handle multiple entries."""
1957
1945
        self.assertBisect(expected, [['b/d', 'b/d2']], state, ['b/d'])
1958
1946
        self.assertBisect(expected, [['b/d/e', 'b/d/e2']],
1959
1947
                          state, ['b/d/e'])
1960
 
        self.assertBisect(expected, [['b-c', 'b-c2']], state, ['b-c'])
1961
1948
        self.assertBisect(expected, [['f', 'f2']], state, ['f'])
1962
1949
 
1963
1950
    def test_bisect_page_size_too_small(self):
1970
1957
        self.assertBisect(expected, [['b/c']], state, ['b/c'])
1971
1958
        self.assertBisect(expected, [['b/d']], state, ['b/d'])
1972
1959
        self.assertBisect(expected, [['b/d/e']], state, ['b/d/e'])
1973
 
        self.assertBisect(expected, [['b-c']], state, ['b-c'])
1974
1960
        self.assertBisect(expected, [['f']], state, ['f'])
1975
1961
 
1976
1962
    def test_bisect_missing(self):
1979
1965
        self.assertBisect(expected, [None], state, ['foo'])
1980
1966
        self.assertBisect(expected, [None], state, ['b/foo'])
1981
1967
        self.assertBisect(expected, [None], state, ['bar/foo'])
1982
 
        self.assertBisect(expected, [None], state, ['b-c/foo'])
1983
1968
 
1984
1969
        self.assertBisect(expected, [['a'], None, ['b/d']],
1985
1970
                          state, ['a', 'foo', 'b/d'])
2001
1986
    def test_bisect_dirblocks(self):
2002
1987
        tree, state, expected = self.create_duplicated_dirstate()
2003
1988
        self.assertBisectDirBlocks(expected,
2004
 
            [['', 'a', 'a2', 'b', 'b2', 'b-c', 'b-c2', 'f', 'f2']],
2005
 
            state, [''])
 
1989
            [['', 'a', 'a2', 'b', 'b2', 'f', 'f2']], state, [''])
2006
1990
        self.assertBisectDirBlocks(expected,
2007
1991
            [['b/c', 'b/c2', 'b/d', 'b/d2']], state, ['b'])
2008
1992
        self.assertBisectDirBlocks(expected,
2009
1993
            [['b/d/e', 'b/d/e2']], state, ['b/d'])
2010
1994
        self.assertBisectDirBlocks(expected,
2011
 
            [['', 'a', 'a2', 'b', 'b2', 'b-c', 'b-c2', 'f', 'f2'],
 
1995
            [['', 'a', 'a2', 'b', 'b2', 'f', 'f2'],
2012
1996
             ['b/c', 'b/c2', 'b/d', 'b/d2'],
2013
1997
             ['b/d/e', 'b/d/e2'],
2014
1998
            ], state, ['', 'b', 'b/d'])
2029
2013
        self.assertBisectRecursive(expected, ['a'], state, ['a'])
2030
2014
        self.assertBisectRecursive(expected, ['b/c'], state, ['b/c'])
2031
2015
        self.assertBisectRecursive(expected, ['b/d/e'], state, ['b/d/e'])
2032
 
        self.assertBisectRecursive(expected, ['b-c'], state, ['b-c'])
2033
2016
        self.assertBisectRecursive(expected, ['b/d', 'b/d/e'],
2034
2017
                                   state, ['b/d'])
2035
2018
        self.assertBisectRecursive(expected, ['b', 'b/c', 'b/d', 'b/d/e'],
2036
2019
                                   state, ['b'])
2037
 
        self.assertBisectRecursive(expected, ['', 'a', 'b', 'b-c', 'f', 'b/c',
 
2020
        self.assertBisectRecursive(expected, ['', 'a', 'b', 'f', 'b/c',
2038
2021
                                              'b/d', 'b/d/e'],
2039
2022
                                   state, [''])
2040
2023
 
2064
2047
                                   state, ['b'])
2065
2048
 
2066
2049
 
 
2050
class TestBisectDirblock(TestCase):
 
2051
    """Test that bisect_dirblock() returns the expected values.
 
2052
 
 
2053
    bisect_dirblock is intended to work like bisect.bisect_left() except it
 
2054
    knows it is working on dirblocks and that dirblocks are sorted by ('path',
 
2055
    'to', 'foo') chunks rather than by raw 'path/to/foo'.
 
2056
    """
 
2057
 
 
2058
    def assertBisect(self, dirblocks, split_dirblocks, path, *args, **kwargs):
 
2059
        """Assert that bisect_split works like bisect_left on the split paths.
 
2060
 
 
2061
        :param dirblocks: A list of (path, [info]) pairs.
 
2062
        :param split_dirblocks: A list of ((split, path), [info]) pairs.
 
2063
        :param path: The path we are indexing.
 
2064
 
 
2065
        All other arguments will be passed along.
 
2066
        """
 
2067
        bisect_split_idx = dirstate.bisect_dirblock(dirblocks, path,
 
2068
                                                 *args, **kwargs)
 
2069
        split_dirblock = (path.split('/'), [])
 
2070
        bisect_left_idx = bisect.bisect_left(split_dirblocks, split_dirblock,
 
2071
                                             *args)
 
2072
        self.assertEqual(bisect_left_idx, bisect_split_idx,
 
2073
                         'bisect_split disagreed. %s != %s'
 
2074
                         ' for key %s'
 
2075
                         % (bisect_left_idx, bisect_split_idx, path)
 
2076
                         )
 
2077
 
 
2078
    def paths_to_dirblocks(self, paths):
 
2079
        """Convert a list of paths into dirblock form.
 
2080
 
 
2081
        Also, ensure that the paths are in proper sorted order.
 
2082
        """
 
2083
        dirblocks = [(path, []) for path in paths]
 
2084
        split_dirblocks = [(path.split('/'), []) for path in paths]
 
2085
        self.assertEqual(sorted(split_dirblocks), split_dirblocks)
 
2086
        return dirblocks, split_dirblocks
 
2087
 
 
2088
    def test_simple(self):
 
2089
        """In the simple case it works just like bisect_left"""
 
2090
        paths = ['', 'a', 'b', 'c', 'd']
 
2091
        dirblocks, split_dirblocks = self.paths_to_dirblocks(paths)
 
2092
        for path in paths:
 
2093
            self.assertBisect(dirblocks, split_dirblocks, path)
 
2094
        self.assertBisect(dirblocks, split_dirblocks, '_')
 
2095
        self.assertBisect(dirblocks, split_dirblocks, 'aa')
 
2096
        self.assertBisect(dirblocks, split_dirblocks, 'bb')
 
2097
        self.assertBisect(dirblocks, split_dirblocks, 'cc')
 
2098
        self.assertBisect(dirblocks, split_dirblocks, 'dd')
 
2099
        self.assertBisect(dirblocks, split_dirblocks, 'a/a')
 
2100
        self.assertBisect(dirblocks, split_dirblocks, 'b/b')
 
2101
        self.assertBisect(dirblocks, split_dirblocks, 'c/c')
 
2102
        self.assertBisect(dirblocks, split_dirblocks, 'd/d')
 
2103
 
 
2104
    def test_involved(self):
 
2105
        """This is where bisect_left diverges slightly."""
 
2106
        paths = ['', 'a',
 
2107
                 'a/a', 'a/a/a', 'a/a/z', 'a/a-a', 'a/a-z',
 
2108
                 'a/z', 'a/z/a', 'a/z/z', 'a/z-a', 'a/z-z',
 
2109
                 'a-a', 'a-z',
 
2110
                 'z', 'z/a/a', 'z/a/z', 'z/a-a', 'z/a-z',
 
2111
                 'z/z', 'z/z/a', 'z/z/z', 'z/z-a', 'z/z-z',
 
2112
                 'z-a', 'z-z',
 
2113
                ]
 
2114
        dirblocks, split_dirblocks = self.paths_to_dirblocks(paths)
 
2115
        for path in paths:
 
2116
            self.assertBisect(dirblocks, split_dirblocks, path)
 
2117
 
 
2118
    def test_involved_cached(self):
 
2119
        """This is where bisect_left diverges slightly."""
 
2120
        paths = ['', 'a',
 
2121
                 'a/a', 'a/a/a', 'a/a/z', 'a/a-a', 'a/a-z',
 
2122
                 'a/z', 'a/z/a', 'a/z/z', 'a/z-a', 'a/z-z',
 
2123
                 'a-a', 'a-z',
 
2124
                 'z', 'z/a/a', 'z/a/z', 'z/a-a', 'z/a-z',
 
2125
                 'z/z', 'z/z/a', 'z/z/z', 'z/z-a', 'z/z-z',
 
2126
                 'z-a', 'z-z',
 
2127
                ]
 
2128
        cache = {}
 
2129
        dirblocks, split_dirblocks = self.paths_to_dirblocks(paths)
 
2130
        for path in paths:
 
2131
            self.assertBisect(dirblocks, split_dirblocks, path, cache=cache)
 
2132
 
 
2133
 
2067
2134
class TestDirstateValidation(TestCaseWithDirState):
2068
2135
 
2069
2136
    def test_validate_correct_dirstate(self):
2119
2186
            state._validate)
2120
2187
        self.assertContainsRe(str(e),
2121
2188
            'file a-id is absent in row')
2122