~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test__dirstate_helpers.py

  • Committer: John Arbash Meinel
  • Date: 2007-07-10 14:51:23 UTC
  • mto: This revision was merged to the branch mainline in revision 2643.
  • Revision ID: john@arbash-meinel.com-20070710145123-jv3wcj10qdvkgmt8
Move code around to refactor according to our pyrex extension design.
This creates a _dirstate_helpers_py.py next to _dirstate_helpers_c.pyx
Rather than having a 'bzrlib.compiled.*' directory.

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
 
17
17
"""Tests for the compiled dirstate helpers."""
18
18
 
 
19
import bisect
 
20
 
19
21
from bzrlib import (
20
22
    tests,
21
23
    )
22
 
try:
23
 
    from bzrlib.compiled import dirstate_helpers
24
 
except ImportError:
25
 
    have_dirstate_helpers = False
26
 
else:
27
 
    have_dirstate_helpers = True
28
 
from bzrlib.tests import test_dirstate
29
24
 
30
25
 
31
26
class _CompiledDirstateHelpersFeature(tests.Feature):
32
27
    def _probe(self):
33
 
        return have_dirstate_helpers
 
28
        try:
 
29
            import bzrlib._dirstate_helpers_c
 
30
        except ImportError:
 
31
            return False
 
32
        return True
34
33
 
35
34
    def feature_name(self):
36
 
        return 'bzrlib.compiled.dirstate_helpers'
 
35
        return 'bzrlib._dirstate_helpers_c'
37
36
 
38
37
CompiledDirstateHelpersFeature = _CompiledDirstateHelpersFeature()
39
38
 
40
39
 
41
 
class TestCCmpByDirs(test_dirstate.TestCmpByDirs):
 
40
class TestCmpByDirs(tests.TestCase):
 
41
 
 
42
    def get_cmp_by_dirs(self):
 
43
        """Get a specific implementation of cmp_by_dirs."""
 
44
        from bzrlib._dirstate_helpers_py import cmp_by_dirs_py
 
45
        return cmp_by_dirs_py
 
46
 
 
47
    def assertPositive(self, val):
 
48
        """Assert that val is greater than 0."""
 
49
        self.assertTrue(val > 0, 'expected a positive value, but got %s' % val)
 
50
 
 
51
    def assertNegative(self, val):
 
52
        """Assert that val is less than 0."""
 
53
        self.assertTrue(val < 0, 'expected a negative value, but got %s' % val)
 
54
 
 
55
    def assertCmpByDirs(self, expected, str1, str2):
 
56
        """Compare the two strings, in both directions.
 
57
 
 
58
        :param expected: The expected comparison value. -1 means str1 comes
 
59
            first, 0 means they are equal, 1 means str2 comes first
 
60
        :param str1: string to compare
 
61
        :param str2: string to compare
 
62
        """
 
63
        cmp_by_dirs = self.get_cmp_by_dirs()
 
64
        if expected == 0:
 
65
            self.assertEqual(str1, str2)
 
66
            self.assertEqual(0, cmp_by_dirs(str1, str2))
 
67
            self.assertEqual(0, cmp_by_dirs(str2, str1))
 
68
        elif expected > 0:
 
69
            self.assertPositive(cmp_by_dirs(str1, str2))
 
70
            self.assertNegative(cmp_by_dirs(str2, str1))
 
71
        else:
 
72
            self.assertNegative(cmp_by_dirs(str1, str2))
 
73
            self.assertPositive(cmp_by_dirs(str2, str1))
 
74
 
 
75
    def test_cmp_empty(self):
 
76
        """Compare against the empty string."""
 
77
        self.assertCmpByDirs(0, '', '')
 
78
        self.assertCmpByDirs(1, 'a', '')
 
79
        self.assertCmpByDirs(1, 'ab', '')
 
80
        self.assertCmpByDirs(1, 'abc', '')
 
81
        self.assertCmpByDirs(1, 'abcd', '')
 
82
        self.assertCmpByDirs(1, 'abcde', '')
 
83
        self.assertCmpByDirs(1, 'abcdef', '')
 
84
        self.assertCmpByDirs(1, 'abcdefg', '')
 
85
        self.assertCmpByDirs(1, 'abcdefgh', '')
 
86
        self.assertCmpByDirs(1, 'abcdefghi', '')
 
87
        self.assertCmpByDirs(1, 'test/ing/a/path/', '')
 
88
 
 
89
    def test_cmp_same_str(self):
 
90
        """Compare the same string"""
 
91
        self.assertCmpByDirs(0, 'a', 'a')
 
92
        self.assertCmpByDirs(0, 'ab', 'ab')
 
93
        self.assertCmpByDirs(0, 'abc', 'abc')
 
94
        self.assertCmpByDirs(0, 'abcd', 'abcd')
 
95
        self.assertCmpByDirs(0, 'abcde', 'abcde')
 
96
        self.assertCmpByDirs(0, 'abcdef', 'abcdef')
 
97
        self.assertCmpByDirs(0, 'abcdefg', 'abcdefg')
 
98
        self.assertCmpByDirs(0, 'abcdefgh', 'abcdefgh')
 
99
        self.assertCmpByDirs(0, 'abcdefghi', 'abcdefghi')
 
100
        self.assertCmpByDirs(0, 'testing a long string', 'testing a long string')
 
101
        self.assertCmpByDirs(0, 'x'*10000, 'x'*10000)
 
102
        self.assertCmpByDirs(0, 'a/b', 'a/b')
 
103
        self.assertCmpByDirs(0, 'a/b/c', 'a/b/c')
 
104
        self.assertCmpByDirs(0, 'a/b/c/d', 'a/b/c/d')
 
105
        self.assertCmpByDirs(0, 'a/b/c/d/e', 'a/b/c/d/e')
 
106
 
 
107
    def test_simple_paths(self):
 
108
        """Compare strings that act like normal string comparison"""
 
109
        self.assertCmpByDirs(-1, 'a', 'b')
 
110
        self.assertCmpByDirs(-1, 'aa', 'ab')
 
111
        self.assertCmpByDirs(-1, 'ab', 'bb')
 
112
        self.assertCmpByDirs(-1, 'aaa', 'aab')
 
113
        self.assertCmpByDirs(-1, 'aab', 'abb')
 
114
        self.assertCmpByDirs(-1, 'abb', 'bbb')
 
115
        self.assertCmpByDirs(-1, 'aaaa', 'aaab')
 
116
        self.assertCmpByDirs(-1, 'aaab', 'aabb')
 
117
        self.assertCmpByDirs(-1, 'aabb', 'abbb')
 
118
        self.assertCmpByDirs(-1, 'abbb', 'bbbb')
 
119
        self.assertCmpByDirs(-1, 'aaaaa', 'aaaab')
 
120
        self.assertCmpByDirs(-1, 'a/a', 'a/b')
 
121
        self.assertCmpByDirs(-1, 'a/b', 'b/b')
 
122
        self.assertCmpByDirs(-1, 'a/a/a', 'a/a/b')
 
123
        self.assertCmpByDirs(-1, 'a/a/b', 'a/b/b')
 
124
        self.assertCmpByDirs(-1, 'a/b/b', 'b/b/b')
 
125
        self.assertCmpByDirs(-1, 'a/a/a/a', 'a/a/a/b')
 
126
        self.assertCmpByDirs(-1, 'a/a/a/b', 'a/a/b/b')
 
127
        self.assertCmpByDirs(-1, 'a/a/b/b', 'a/b/b/b')
 
128
        self.assertCmpByDirs(-1, 'a/b/b/b', 'b/b/b/b')
 
129
        self.assertCmpByDirs(-1, 'a/a/a/a/a', 'a/a/a/a/b')
 
130
 
 
131
    def test_tricky_paths(self):
 
132
        self.assertCmpByDirs(1, 'ab/cd/ef', 'ab/cc/ef')
 
133
        self.assertCmpByDirs(1, 'ab/cd/ef', 'ab/c/ef')
 
134
        self.assertCmpByDirs(-1, 'ab/cd/ef', 'ab/cd-ef')
 
135
        self.assertCmpByDirs(-1, 'ab/cd', 'ab/cd-')
 
136
        self.assertCmpByDirs(-1, 'ab/cd', 'ab-cd')
 
137
 
 
138
 
 
139
class TestCCmpByDirs(TestCmpByDirs):
42
140
    """Test the C implementation of cmp_by_dirs"""
43
141
 
44
142
    _test_needs_features = [CompiledDirstateHelpersFeature]
45
143
 
46
144
    def get_cmp_by_dirs(self):
47
 
        return dirstate_helpers.cmp_by_dirs_c
48
 
 
49
 
 
50
 
class TestCompiledBisectDirblock(test_dirstate.TestBisectDirblock):
 
145
        from bzrlib._dirstate_helpers_c import cmp_by_dirs_c
 
146
        return cmp_by_dirs_c
 
147
 
 
148
 
 
149
class TestBisectDirblock(tests.TestCase):
 
150
    """Test that bisect_dirblock() returns the expected values.
 
151
 
 
152
    bisect_dirblock is intended to work like bisect.bisect_left() except it
 
153
    knows it is working on dirblocks and that dirblocks are sorted by ('path',
 
154
    'to', 'foo') chunks rather than by raw 'path/to/foo'.
 
155
    """
 
156
 
 
157
    def get_bisect_dirblock(self):
 
158
        """Return an implementation of bisect_dirblock"""
 
159
        from bzrlib._dirstate_helpers_py import bisect_dirblock_py
 
160
        return bisect_dirblock_py
 
161
 
 
162
    def assertBisect(self, dirblocks, split_dirblocks, path, *args, **kwargs):
 
163
        """Assert that bisect_split works like bisect_left on the split paths.
 
164
 
 
165
        :param dirblocks: A list of (path, [info]) pairs.
 
166
        :param split_dirblocks: A list of ((split, path), [info]) pairs.
 
167
        :param path: The path we are indexing.
 
168
 
 
169
        All other arguments will be passed along.
 
170
        """
 
171
        bisect_dirblock = self.get_bisect_dirblock()
 
172
        self.assertIsInstance(dirblocks, list)
 
173
        bisect_split_idx = bisect_dirblock(dirblocks, path, *args, **kwargs)
 
174
        split_dirblock = (path.split('/'), [])
 
175
        bisect_left_idx = bisect.bisect_left(split_dirblocks, split_dirblock,
 
176
                                             *args)
 
177
        self.assertEqual(bisect_left_idx, bisect_split_idx,
 
178
                         'bisect_split disagreed. %s != %s'
 
179
                         ' for key %s'
 
180
                         % (bisect_left_idx, bisect_split_idx, path)
 
181
                         )
 
182
 
 
183
    def paths_to_dirblocks(self, paths):
 
184
        """Convert a list of paths into dirblock form.
 
185
 
 
186
        Also, ensure that the paths are in proper sorted order.
 
187
        """
 
188
        dirblocks = [(path, []) for path in paths]
 
189
        split_dirblocks = [(path.split('/'), []) for path in paths]
 
190
        self.assertEqual(sorted(split_dirblocks), split_dirblocks)
 
191
        return dirblocks, split_dirblocks
 
192
 
 
193
    def test_simple(self):
 
194
        """In the simple case it works just like bisect_left"""
 
195
        paths = ['', 'a', 'b', 'c', 'd']
 
196
        dirblocks, split_dirblocks = self.paths_to_dirblocks(paths)
 
197
        for path in paths:
 
198
            self.assertBisect(dirblocks, split_dirblocks, path)
 
199
        self.assertBisect(dirblocks, split_dirblocks, '_')
 
200
        self.assertBisect(dirblocks, split_dirblocks, 'aa')
 
201
        self.assertBisect(dirblocks, split_dirblocks, 'bb')
 
202
        self.assertBisect(dirblocks, split_dirblocks, 'cc')
 
203
        self.assertBisect(dirblocks, split_dirblocks, 'dd')
 
204
        self.assertBisect(dirblocks, split_dirblocks, 'a/a')
 
205
        self.assertBisect(dirblocks, split_dirblocks, 'b/b')
 
206
        self.assertBisect(dirblocks, split_dirblocks, 'c/c')
 
207
        self.assertBisect(dirblocks, split_dirblocks, 'd/d')
 
208
 
 
209
    def test_involved(self):
 
210
        """This is where bisect_left diverges slightly."""
 
211
        paths = ['', 'a',
 
212
                 'a/a', 'a/a/a', 'a/a/z', 'a/a-a', 'a/a-z',
 
213
                 'a/z', 'a/z/a', 'a/z/z', 'a/z-a', 'a/z-z',
 
214
                 'a-a', 'a-z',
 
215
                 'z', 'z/a/a', 'z/a/z', 'z/a-a', 'z/a-z',
 
216
                 'z/z', 'z/z/a', 'z/z/z', 'z/z-a', 'z/z-z',
 
217
                 'z-a', 'z-z',
 
218
                ]
 
219
        dirblocks, split_dirblocks = self.paths_to_dirblocks(paths)
 
220
        for path in paths:
 
221
            self.assertBisect(dirblocks, split_dirblocks, path)
 
222
 
 
223
    def test_involved_cached(self):
 
224
        """This is where bisect_left diverges slightly."""
 
225
        paths = ['', 'a',
 
226
                 'a/a', 'a/a/a', 'a/a/z', 'a/a-a', 'a/a-z',
 
227
                 'a/z', 'a/z/a', 'a/z/z', 'a/z-a', 'a/z-z',
 
228
                 'a-a', 'a-z',
 
229
                 'z', 'z/a/a', 'z/a/z', 'z/a-a', 'z/a-z',
 
230
                 'z/z', 'z/z/a', 'z/z/z', 'z/z-a', 'z/z-z',
 
231
                 'z-a', 'z-z',
 
232
                ]
 
233
        cache = {}
 
234
        dirblocks, split_dirblocks = self.paths_to_dirblocks(paths)
 
235
        for path in paths:
 
236
            self.assertBisect(dirblocks, split_dirblocks, path, cache=cache)
 
237
 
 
238
 
 
239
class TestCompiledBisectDirblock(TestBisectDirblock):
51
240
    """Test that bisect_dirblock() returns the expected values.
52
241
 
53
242
    bisect_dirblock is intended to work like bisect.bisect_left() except it
61
250
    _test_needs_features = [CompiledDirstateHelpersFeature]
62
251
 
63
252
    def get_bisect_dirblock(self):
64
 
        return dirstate_helpers.bisect_dirblock_c
 
253
        from bzrlib._dirstate_helpers_c import bisect_dirblock_c
 
254
        return bisect_dirblock_c