/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to brzlib/tests/test__dirstate_helpers.py

  • Committer: Jelmer Vernooij
  • Date: 2017-05-21 12:41:27 UTC
  • mto: This revision was merged to the branch mainline in revision 6623.
  • Revision ID: jelmer@jelmer.uk-20170521124127-iv8etg0vwymyai6y
s/bzr/brz/ in apport config.

Show diffs side-by-side

added added

removed removed

Lines of Context:
20
20
import os
21
21
import time
22
22
 
23
 
from .. import (
 
23
from brzlib import (
 
24
    dirstate,
 
25
    errors,
24
26
    osutils,
25
27
    tests,
26
 
    )
27
 
from ..bzr import (
28
 
    dirstate,
29
28
    _dirstate_helpers_py,
30
29
    )
31
 
from . import (
 
30
from brzlib.tests import (
32
31
    test_dirstate,
33
32
    )
34
 
from .test_osutils import dir_reader_scenarios
35
 
from .scenarios import (
 
33
from brzlib.tests.test_osutils import dir_reader_scenarios
 
34
from brzlib.tests.scenarios import (
36
35
    load_tests_apply_scenarios,
37
36
    multiply_scenarios,
38
37
    )
39
 
from . import (
 
38
from brzlib.tests import (
40
39
    features,
41
40
    )
42
41
 
45
44
 
46
45
 
47
46
compiled_dirstate_helpers_feature = features.ModuleAvailableFeature(
48
 
    'breezy.bzr._dirstate_helpers_pyx')
 
47
    'brzlib._dirstate_helpers_pyx')
49
48
 
50
49
 
51
50
# FIXME: we should also parametrize against SHA1Provider !
52
51
 
53
52
ue_scenarios = [('dirstate_Python',
54
 
                 {'update_entry': dirstate.py_update_entry})]
 
53
    {'update_entry': dirstate.py_update_entry})]
55
54
if compiled_dirstate_helpers_feature.available():
56
55
    update_entry = compiled_dirstate_helpers_feature.module.update_entry
57
56
    ue_scenarios.append(('dirstate_Pyrex', {'update_entry': update_entry}))
58
57
 
59
58
pe_scenarios = [('dirstate_Python',
60
 
                 {'_process_entry': dirstate.ProcessEntryPython})]
 
59
    {'_process_entry': dirstate.ProcessEntryPython})]
61
60
if compiled_dirstate_helpers_feature.available():
62
61
    process_entry = compiled_dirstate_helpers_feature.module.ProcessEntryC
63
62
    pe_scenarios.append(('dirstate_Pyrex', {'_process_entry': process_entry}))
65
64
helper_scenarios = [('dirstate_Python', {'helpers': _dirstate_helpers_py})]
66
65
if compiled_dirstate_helpers_feature.available():
67
66
    helper_scenarios.append(('dirstate_Pyrex',
68
 
                             {'helpers': compiled_dirstate_helpers_feature.module}))
 
67
        {'helpers': compiled_dirstate_helpers_feature.module}))
69
68
 
70
69
 
71
70
class TestBisectPathMixin(object):
120
119
                            bisect_split_idx, bisect_path_idx, path)
121
120
                         )
122
121
        if exists:
123
 
            self.assertEqual(path, paths[bisect_path_idx + offset])
 
122
            self.assertEqual(path, paths[bisect_path_idx+offset])
124
123
 
125
124
    def split_for_dirblocks(self, paths):
126
125
        dir_split_paths = []
127
126
        for path in paths:
128
127
            dirname, basename = os.path.split(path)
129
 
            dir_split_paths.append((dirname.split(b'/'), basename))
 
128
            dir_split_paths.append((dirname.split('/'), basename))
130
129
        dir_split_paths.sort()
131
130
        return dir_split_paths
132
131
 
133
132
    def test_simple(self):
134
133
        """In the simple case it works just like bisect_left"""
135
 
        paths = [b'', b'a', b'b', b'c', b'd']
 
134
        paths = ['', 'a', 'b', 'c', 'd']
136
135
        split_paths = self.split_for_dirblocks(paths)
137
136
        for path in paths:
138
137
            self.assertBisect(paths, split_paths, path, exists=True)
139
 
        self.assertBisect(paths, split_paths, b'_', exists=False)
140
 
        self.assertBisect(paths, split_paths, b'aa', exists=False)
141
 
        self.assertBisect(paths, split_paths, b'bb', exists=False)
142
 
        self.assertBisect(paths, split_paths, b'cc', exists=False)
143
 
        self.assertBisect(paths, split_paths, b'dd', exists=False)
144
 
        self.assertBisect(paths, split_paths, b'a/a', exists=False)
145
 
        self.assertBisect(paths, split_paths, b'b/b', exists=False)
146
 
        self.assertBisect(paths, split_paths, b'c/c', exists=False)
147
 
        self.assertBisect(paths, split_paths, b'd/d', exists=False)
 
138
        self.assertBisect(paths, split_paths, '_', exists=False)
 
139
        self.assertBisect(paths, split_paths, 'aa', exists=False)
 
140
        self.assertBisect(paths, split_paths, 'bb', exists=False)
 
141
        self.assertBisect(paths, split_paths, 'cc', exists=False)
 
142
        self.assertBisect(paths, split_paths, 'dd', exists=False)
 
143
        self.assertBisect(paths, split_paths, 'a/a', exists=False)
 
144
        self.assertBisect(paths, split_paths, 'b/b', exists=False)
 
145
        self.assertBisect(paths, split_paths, 'c/c', exists=False)
 
146
        self.assertBisect(paths, split_paths, 'd/d', exists=False)
148
147
 
149
148
    def test_involved(self):
150
149
        """This is where bisect_path_* diverges slightly."""
181
180
        # children are mentioned.
182
181
        # So all the root-directory paths, then all the
183
182
        # first sub directory, etc.
184
 
        paths = [  # content of '/'
185
 
            b'', b'a', b'a-a', b'a-z', b'a=a', b'a=z',
 
183
        paths = [# content of '/'
 
184
                 '', 'a', 'a-a', 'a-z', 'a=a', 'a=z',
186
185
                 # content of 'a/'
187
 
                 b'a/a', b'a/a-a', b'a/a-z',
188
 
                 b'a/a=a', b'a/a=z',
189
 
                 b'a/z', b'a/z-a', b'a/z-z',
190
 
                 b'a/z=a', b'a/z=z',
 
186
                 'a/a', 'a/a-a', 'a/a-z',
 
187
                 'a/a=a', 'a/a=z',
 
188
                 'a/z', 'a/z-a', 'a/z-z',
 
189
                 'a/z=a', 'a/z=z',
191
190
                 # content of 'a/a/'
192
 
                 b'a/a/a', b'a/a/z',
 
191
                 'a/a/a', 'a/a/z',
193
192
                 # content of 'a/a-a'
194
 
                 b'a/a-a/a',
 
193
                 'a/a-a/a',
195
194
                 # content of 'a/a-z'
196
 
                 b'a/a-z/z',
 
195
                 'a/a-z/z',
197
196
                 # content of 'a/a=a'
198
 
                 b'a/a=a/a',
 
197
                 'a/a=a/a',
199
198
                 # content of 'a/a=z'
200
 
                 b'a/a=z/z',
 
199
                 'a/a=z/z',
201
200
                 # content of 'a/z/'
202
 
                 b'a/z/a', b'a/z/z',
 
201
                 'a/z/a', 'a/z/z',
203
202
                 # content of 'a-a'
204
 
                 b'a-a/a',
 
203
                 'a-a/a',
205
204
                 # content of 'a-z'
206
 
                 b'a-z/z',
 
205
                 'a-z/z',
207
206
                 # content of 'a=a'
208
 
                 b'a=a/a',
 
207
                 'a=a/a',
209
208
                 # content of 'a=z'
210
 
                 b'a=z/z',
211
 
            ]
 
209
                 'a=z/z',
 
210
                ]
212
211
        split_paths = self.split_for_dirblocks(paths)
213
212
        sorted_paths = []
214
213
        for dir_parts, basename in split_paths:
215
 
            if dir_parts == [b'']:
 
214
            if dir_parts == ['']:
216
215
                sorted_paths.append(basename)
217
216
            else:
218
 
                sorted_paths.append(b'/'.join(dir_parts + [basename]))
 
217
                sorted_paths.append('/'.join(dir_parts + [basename]))
219
218
 
220
219
        self.assertEqual(sorted_paths, paths)
221
220
 
227
226
    """Run all Bisect Path tests against _bisect_path_left."""
228
227
 
229
228
    def get_bisect_path(self):
230
 
        from breezy.bzr._dirstate_helpers_py import _bisect_path_left
 
229
        from brzlib._dirstate_helpers_py import _bisect_path_left
231
230
        return _bisect_path_left
232
231
 
233
232
    def get_bisect(self):
240
239
    _test_needs_features = [compiled_dirstate_helpers_feature]
241
240
 
242
241
    def get_bisect_path(self):
243
 
        from breezy.bzr._dirstate_helpers_pyx import _bisect_path_left
 
242
        from brzlib._dirstate_helpers_pyx import _bisect_path_left
244
243
        return _bisect_path_left
245
244
 
246
245
 
248
247
    """Run all Bisect Path tests against _bisect_path_right"""
249
248
 
250
249
    def get_bisect_path(self):
251
 
        from breezy.bzr._dirstate_helpers_py import _bisect_path_right
 
250
        from brzlib._dirstate_helpers_py import _bisect_path_right
252
251
        return _bisect_path_right
253
252
 
254
253
    def get_bisect(self):
261
260
    _test_needs_features = [compiled_dirstate_helpers_feature]
262
261
 
263
262
    def get_bisect_path(self):
264
 
        from breezy.bzr._dirstate_helpers_pyx import _bisect_path_right
 
263
        from brzlib._dirstate_helpers_pyx import _bisect_path_right
265
264
        return _bisect_path_right
266
265
 
267
266
 
279
278
 
280
279
    def get_bisect_dirblock(self):
281
280
        """Return an implementation of bisect_dirblock"""
282
 
        from breezy.bzr._dirstate_helpers_py import bisect_dirblock
 
281
        from brzlib._dirstate_helpers_py import bisect_dirblock
283
282
        return bisect_dirblock
284
283
 
285
284
    def assertBisect(self, dirblocks, split_dirblocks, path, *args, **kwargs):
294
293
        bisect_dirblock = self.get_bisect_dirblock()
295
294
        self.assertIsInstance(dirblocks, list)
296
295
        bisect_split_idx = bisect_dirblock(dirblocks, path, *args, **kwargs)
297
 
        split_dirblock = (path.split(b'/'), [])
 
296
        split_dirblock = (path.split('/'), [])
298
297
        bisect_left_idx = bisect.bisect_left(split_dirblocks, split_dirblock,
299
298
                                             *args)
300
299
        self.assertEqual(bisect_left_idx, bisect_split_idx,
309
308
        Also, ensure that the paths are in proper sorted order.
310
309
        """
311
310
        dirblocks = [(path, []) for path in paths]
312
 
        split_dirblocks = [(path.split(b'/'), []) for path in paths]
 
311
        split_dirblocks = [(path.split('/'), []) for path in paths]
313
312
        self.assertEqual(sorted(split_dirblocks), split_dirblocks)
314
313
        return dirblocks, split_dirblocks
315
314
 
316
315
    def test_simple(self):
317
316
        """In the simple case it works just like bisect_left"""
318
 
        paths = [b'', b'a', b'b', b'c', b'd']
 
317
        paths = ['', 'a', 'b', 'c', 'd']
319
318
        dirblocks, split_dirblocks = self.paths_to_dirblocks(paths)
320
319
        for path in paths:
321
320
            self.assertBisect(dirblocks, split_dirblocks, path)
322
 
        self.assertBisect(dirblocks, split_dirblocks, b'_')
323
 
        self.assertBisect(dirblocks, split_dirblocks, b'aa')
324
 
        self.assertBisect(dirblocks, split_dirblocks, b'bb')
325
 
        self.assertBisect(dirblocks, split_dirblocks, b'cc')
326
 
        self.assertBisect(dirblocks, split_dirblocks, b'dd')
327
 
        self.assertBisect(dirblocks, split_dirblocks, b'a/a')
328
 
        self.assertBisect(dirblocks, split_dirblocks, b'b/b')
329
 
        self.assertBisect(dirblocks, split_dirblocks, b'c/c')
330
 
        self.assertBisect(dirblocks, split_dirblocks, b'd/d')
 
321
        self.assertBisect(dirblocks, split_dirblocks, '_')
 
322
        self.assertBisect(dirblocks, split_dirblocks, 'aa')
 
323
        self.assertBisect(dirblocks, split_dirblocks, 'bb')
 
324
        self.assertBisect(dirblocks, split_dirblocks, 'cc')
 
325
        self.assertBisect(dirblocks, split_dirblocks, 'dd')
 
326
        self.assertBisect(dirblocks, split_dirblocks, 'a/a')
 
327
        self.assertBisect(dirblocks, split_dirblocks, 'b/b')
 
328
        self.assertBisect(dirblocks, split_dirblocks, 'c/c')
 
329
        self.assertBisect(dirblocks, split_dirblocks, 'd/d')
331
330
 
332
331
    def test_involved(self):
333
332
        """This is where bisect_left diverges slightly."""
334
 
        paths = [b'', b'a',
335
 
                 b'a/a', b'a/a/a', b'a/a/z', b'a/a-a', b'a/a-z',
336
 
                 b'a/z', b'a/z/a', b'a/z/z', b'a/z-a', b'a/z-z',
337
 
                 b'a-a', b'a-z',
338
 
                 b'z', b'z/a/a', b'z/a/z', b'z/a-a', b'z/a-z',
339
 
                 b'z/z', b'z/z/a', b'z/z/z', b'z/z-a', b'z/z-z',
340
 
                 b'z-a', b'z-z',
341
 
                 ]
 
333
        paths = ['', 'a',
 
334
                 'a/a', 'a/a/a', 'a/a/z', 'a/a-a', 'a/a-z',
 
335
                 'a/z', 'a/z/a', 'a/z/z', 'a/z-a', 'a/z-z',
 
336
                 'a-a', 'a-z',
 
337
                 'z', 'z/a/a', 'z/a/z', 'z/a-a', 'z/a-z',
 
338
                 'z/z', 'z/z/a', 'z/z/z', 'z/z-a', 'z/z-z',
 
339
                 'z-a', 'z-z',
 
340
                ]
342
341
        dirblocks, split_dirblocks = self.paths_to_dirblocks(paths)
343
342
        for path in paths:
344
343
            self.assertBisect(dirblocks, split_dirblocks, path)
345
344
 
346
345
    def test_involved_cached(self):
347
346
        """This is where bisect_left diverges slightly."""
348
 
        paths = [b'', b'a',
349
 
                 b'a/a', b'a/a/a', b'a/a/z', b'a/a-a', b'a/a-z',
350
 
                 b'a/z', b'a/z/a', b'a/z/z', b'a/z-a', b'a/z-z',
351
 
                 b'a-a', b'a-z',
352
 
                 b'z', b'z/a/a', b'z/a/z', b'z/a-a', b'z/a-z',
353
 
                 b'z/z', b'z/z/a', b'z/z/z', b'z/z-a', b'z/z-z',
354
 
                 b'z-a', b'z-z',
355
 
                 ]
 
347
        paths = ['', 'a',
 
348
                 'a/a', 'a/a/a', 'a/a/z', 'a/a-a', 'a/a-z',
 
349
                 'a/z', 'a/z/a', 'a/z/z', 'a/z-a', 'a/z-z',
 
350
                 'a-a', 'a-z',
 
351
                 'z', 'z/a/a', 'z/a/z', 'z/a-a', 'z/a-z',
 
352
                 'z/z', 'z/z/a', 'z/z/z', 'z/z-a', 'z/z-z',
 
353
                 'z-a', 'z-z',
 
354
                ]
356
355
        cache = {}
357
356
        dirblocks, split_dirblocks = self.paths_to_dirblocks(paths)
358
357
        for path in paths:
373
372
    _test_needs_features = [compiled_dirstate_helpers_feature]
374
373
 
375
374
    def get_bisect_dirblock(self):
376
 
        from breezy.bzr._dirstate_helpers_pyx import bisect_dirblock
 
375
        from brzlib._dirstate_helpers_pyx import bisect_dirblock
377
376
        return bisect_dirblock
378
377
 
379
378
 
380
 
class TestLtByDirs(tests.TestCase):
381
 
    """Test an implementation of lt_by_dirs()
 
379
class TestCmpByDirs(tests.TestCase):
 
380
    """Test an implementation of cmp_by_dirs()
382
381
 
383
 
    lt_by_dirs() compares 2 paths by their directory sections, rather than as
 
382
    cmp_by_dirs() compares 2 paths by their directory sections, rather than as
384
383
    plain strings.
385
384
 
386
 
    Child test cases can override ``get_lt_by_dirs`` to test a specific
 
385
    Child test cases can override ``get_cmp_by_dirs`` to test a specific
387
386
    implementation.
388
387
    """
389
388
 
390
 
    def get_lt_by_dirs(self):
391
 
        """Get a specific implementation of lt_by_dirs."""
392
 
        from ..bzr._dirstate_helpers_py import lt_by_dirs
393
 
        return lt_by_dirs
 
389
    def get_cmp_by_dirs(self):
 
390
        """Get a specific implementation of cmp_by_dirs."""
 
391
        from brzlib._dirstate_helpers_py import cmp_by_dirs
 
392
        return cmp_by_dirs
394
393
 
395
394
    def assertCmpByDirs(self, expected, str1, str2):
396
395
        """Compare the two strings, in both directions.
400
399
        :param str1: string to compare
401
400
        :param str2: string to compare
402
401
        """
403
 
        lt_by_dirs = self.get_lt_by_dirs()
 
402
        cmp_by_dirs = self.get_cmp_by_dirs()
404
403
        if expected == 0:
405
404
            self.assertEqual(str1, str2)
406
 
            self.assertFalse(lt_by_dirs(str1, str2))
407
 
            self.assertFalse(lt_by_dirs(str2, str1))
 
405
            self.assertEqual(0, cmp_by_dirs(str1, str2))
 
406
            self.assertEqual(0, cmp_by_dirs(str2, str1))
408
407
        elif expected > 0:
409
 
            self.assertFalse(lt_by_dirs(str1, str2))
410
 
            self.assertTrue(lt_by_dirs(str2, str1))
 
408
            self.assertPositive(cmp_by_dirs(str1, str2))
 
409
            self.assertNegative(cmp_by_dirs(str2, str1))
411
410
        else:
412
 
            self.assertTrue(lt_by_dirs(str1, str2))
413
 
            self.assertFalse(lt_by_dirs(str2, str1))
 
411
            self.assertNegative(cmp_by_dirs(str1, str2))
 
412
            self.assertPositive(cmp_by_dirs(str2, str1))
414
413
 
415
414
    def test_cmp_empty(self):
416
415
        """Compare against the empty string."""
417
 
        self.assertCmpByDirs(0, b'', b'')
418
 
        self.assertCmpByDirs(1, b'a', b'')
419
 
        self.assertCmpByDirs(1, b'ab', b'')
420
 
        self.assertCmpByDirs(1, b'abc', b'')
421
 
        self.assertCmpByDirs(1, b'abcd', b'')
422
 
        self.assertCmpByDirs(1, b'abcde', b'')
423
 
        self.assertCmpByDirs(1, b'abcdef', b'')
424
 
        self.assertCmpByDirs(1, b'abcdefg', b'')
425
 
        self.assertCmpByDirs(1, b'abcdefgh', b'')
426
 
        self.assertCmpByDirs(1, b'abcdefghi', b'')
427
 
        self.assertCmpByDirs(1, b'test/ing/a/path/', b'')
 
416
        self.assertCmpByDirs(0, '', '')
 
417
        self.assertCmpByDirs(1, 'a', '')
 
418
        self.assertCmpByDirs(1, 'ab', '')
 
419
        self.assertCmpByDirs(1, 'abc', '')
 
420
        self.assertCmpByDirs(1, 'abcd', '')
 
421
        self.assertCmpByDirs(1, 'abcde', '')
 
422
        self.assertCmpByDirs(1, 'abcdef', '')
 
423
        self.assertCmpByDirs(1, 'abcdefg', '')
 
424
        self.assertCmpByDirs(1, 'abcdefgh', '')
 
425
        self.assertCmpByDirs(1, 'abcdefghi', '')
 
426
        self.assertCmpByDirs(1, 'test/ing/a/path/', '')
428
427
 
429
428
    def test_cmp_same_str(self):
430
429
        """Compare the same string"""
431
 
        self.assertCmpByDirs(0, b'a', b'a')
432
 
        self.assertCmpByDirs(0, b'ab', b'ab')
433
 
        self.assertCmpByDirs(0, b'abc', b'abc')
434
 
        self.assertCmpByDirs(0, b'abcd', b'abcd')
435
 
        self.assertCmpByDirs(0, b'abcde', b'abcde')
436
 
        self.assertCmpByDirs(0, b'abcdef', b'abcdef')
437
 
        self.assertCmpByDirs(0, b'abcdefg', b'abcdefg')
438
 
        self.assertCmpByDirs(0, b'abcdefgh', b'abcdefgh')
439
 
        self.assertCmpByDirs(0, b'abcdefghi', b'abcdefghi')
440
 
        self.assertCmpByDirs(0, b'testing a long string',
441
 
                             b'testing a long string')
442
 
        self.assertCmpByDirs(0, b'x' * 10000, b'x' * 10000)
443
 
        self.assertCmpByDirs(0, b'a/b', b'a/b')
444
 
        self.assertCmpByDirs(0, b'a/b/c', b'a/b/c')
445
 
        self.assertCmpByDirs(0, b'a/b/c/d', b'a/b/c/d')
446
 
        self.assertCmpByDirs(0, b'a/b/c/d/e', b'a/b/c/d/e')
 
430
        self.assertCmpByDirs(0, 'a', 'a')
 
431
        self.assertCmpByDirs(0, 'ab', 'ab')
 
432
        self.assertCmpByDirs(0, 'abc', 'abc')
 
433
        self.assertCmpByDirs(0, 'abcd', 'abcd')
 
434
        self.assertCmpByDirs(0, 'abcde', 'abcde')
 
435
        self.assertCmpByDirs(0, 'abcdef', 'abcdef')
 
436
        self.assertCmpByDirs(0, 'abcdefg', 'abcdefg')
 
437
        self.assertCmpByDirs(0, 'abcdefgh', 'abcdefgh')
 
438
        self.assertCmpByDirs(0, 'abcdefghi', 'abcdefghi')
 
439
        self.assertCmpByDirs(0, 'testing a long string', 'testing a long string')
 
440
        self.assertCmpByDirs(0, 'x'*10000, 'x'*10000)
 
441
        self.assertCmpByDirs(0, 'a/b', 'a/b')
 
442
        self.assertCmpByDirs(0, 'a/b/c', 'a/b/c')
 
443
        self.assertCmpByDirs(0, 'a/b/c/d', 'a/b/c/d')
 
444
        self.assertCmpByDirs(0, 'a/b/c/d/e', 'a/b/c/d/e')
447
445
 
448
446
    def test_simple_paths(self):
449
447
        """Compare strings that act like normal string comparison"""
450
 
        self.assertCmpByDirs(-1, b'a', b'b')
451
 
        self.assertCmpByDirs(-1, b'aa', b'ab')
452
 
        self.assertCmpByDirs(-1, b'ab', b'bb')
453
 
        self.assertCmpByDirs(-1, b'aaa', b'aab')
454
 
        self.assertCmpByDirs(-1, b'aab', b'abb')
455
 
        self.assertCmpByDirs(-1, b'abb', b'bbb')
456
 
        self.assertCmpByDirs(-1, b'aaaa', b'aaab')
457
 
        self.assertCmpByDirs(-1, b'aaab', b'aabb')
458
 
        self.assertCmpByDirs(-1, b'aabb', b'abbb')
459
 
        self.assertCmpByDirs(-1, b'abbb', b'bbbb')
460
 
        self.assertCmpByDirs(-1, b'aaaaa', b'aaaab')
461
 
        self.assertCmpByDirs(-1, b'a/a', b'a/b')
462
 
        self.assertCmpByDirs(-1, b'a/b', b'b/b')
463
 
        self.assertCmpByDirs(-1, b'a/a/a', b'a/a/b')
464
 
        self.assertCmpByDirs(-1, b'a/a/b', b'a/b/b')
465
 
        self.assertCmpByDirs(-1, b'a/b/b', b'b/b/b')
466
 
        self.assertCmpByDirs(-1, b'a/a/a/a', b'a/a/a/b')
467
 
        self.assertCmpByDirs(-1, b'a/a/a/b', b'a/a/b/b')
468
 
        self.assertCmpByDirs(-1, b'a/a/b/b', b'a/b/b/b')
469
 
        self.assertCmpByDirs(-1, b'a/b/b/b', b'b/b/b/b')
470
 
        self.assertCmpByDirs(-1, b'a/a/a/a/a', b'a/a/a/a/b')
 
448
        self.assertCmpByDirs(-1, 'a', 'b')
 
449
        self.assertCmpByDirs(-1, 'aa', 'ab')
 
450
        self.assertCmpByDirs(-1, 'ab', 'bb')
 
451
        self.assertCmpByDirs(-1, 'aaa', 'aab')
 
452
        self.assertCmpByDirs(-1, 'aab', 'abb')
 
453
        self.assertCmpByDirs(-1, 'abb', 'bbb')
 
454
        self.assertCmpByDirs(-1, 'aaaa', 'aaab')
 
455
        self.assertCmpByDirs(-1, 'aaab', 'aabb')
 
456
        self.assertCmpByDirs(-1, 'aabb', 'abbb')
 
457
        self.assertCmpByDirs(-1, 'abbb', 'bbbb')
 
458
        self.assertCmpByDirs(-1, 'aaaaa', 'aaaab')
 
459
        self.assertCmpByDirs(-1, 'a/a', 'a/b')
 
460
        self.assertCmpByDirs(-1, 'a/b', 'b/b')
 
461
        self.assertCmpByDirs(-1, 'a/a/a', 'a/a/b')
 
462
        self.assertCmpByDirs(-1, 'a/a/b', 'a/b/b')
 
463
        self.assertCmpByDirs(-1, 'a/b/b', 'b/b/b')
 
464
        self.assertCmpByDirs(-1, 'a/a/a/a', 'a/a/a/b')
 
465
        self.assertCmpByDirs(-1, 'a/a/a/b', 'a/a/b/b')
 
466
        self.assertCmpByDirs(-1, 'a/a/b/b', 'a/b/b/b')
 
467
        self.assertCmpByDirs(-1, 'a/b/b/b', 'b/b/b/b')
 
468
        self.assertCmpByDirs(-1, 'a/a/a/a/a', 'a/a/a/a/b')
471
469
 
472
470
    def test_tricky_paths(self):
473
 
        self.assertCmpByDirs(1, b'ab/cd/ef', b'ab/cc/ef')
474
 
        self.assertCmpByDirs(1, b'ab/cd/ef', b'ab/c/ef')
475
 
        self.assertCmpByDirs(-1, b'ab/cd/ef', b'ab/cd-ef')
476
 
        self.assertCmpByDirs(-1, b'ab/cd', b'ab/cd-')
477
 
        self.assertCmpByDirs(-1, b'ab/cd', b'ab-cd')
 
471
        self.assertCmpByDirs(1, 'ab/cd/ef', 'ab/cc/ef')
 
472
        self.assertCmpByDirs(1, 'ab/cd/ef', 'ab/c/ef')
 
473
        self.assertCmpByDirs(-1, 'ab/cd/ef', 'ab/cd-ef')
 
474
        self.assertCmpByDirs(-1, 'ab/cd', 'ab/cd-')
 
475
        self.assertCmpByDirs(-1, 'ab/cd', 'ab-cd')
478
476
 
479
477
    def test_cmp_unicode_not_allowed(self):
480
 
        lt_by_dirs = self.get_lt_by_dirs()
481
 
        self.assertRaises(TypeError, lt_by_dirs, u'Unicode', b'str')
482
 
        self.assertRaises(TypeError, lt_by_dirs, b'str', u'Unicode')
483
 
        self.assertRaises(TypeError, lt_by_dirs, u'Unicode', u'Unicode')
 
478
        cmp_by_dirs = self.get_cmp_by_dirs()
 
479
        self.assertRaises(TypeError, cmp_by_dirs, u'Unicode', 'str')
 
480
        self.assertRaises(TypeError, cmp_by_dirs, 'str', u'Unicode')
 
481
        self.assertRaises(TypeError, cmp_by_dirs, u'Unicode', u'Unicode')
484
482
 
485
483
    def test_cmp_non_ascii(self):
486
 
        self.assertCmpByDirs(-1, b'\xc2\xb5', b'\xc3\xa5')  # u'\xb5', u'\xe5'
487
 
        self.assertCmpByDirs(-1, b'a', b'\xc3\xa5')  # u'a', u'\xe5'
488
 
        self.assertCmpByDirs(-1, b'b', b'\xc2\xb5')  # u'b', u'\xb5'
489
 
        self.assertCmpByDirs(-1, b'a/b', b'a/\xc3\xa5')  # u'a/b', u'a/\xe5'
490
 
        self.assertCmpByDirs(-1, b'b/a', b'b/\xc2\xb5')  # u'b/a', u'b/\xb5'
491
 
 
492
 
 
493
 
class TestCompiledLtByDirs(TestLtByDirs):
494
 
    """Test the pyrex implementation of lt_by_dirs"""
 
484
        self.assertCmpByDirs(-1, '\xc2\xb5', '\xc3\xa5') # u'\xb5', u'\xe5'
 
485
        self.assertCmpByDirs(-1, 'a', '\xc3\xa5') # u'a', u'\xe5'
 
486
        self.assertCmpByDirs(-1, 'b', '\xc2\xb5') # u'b', u'\xb5'
 
487
        self.assertCmpByDirs(-1, 'a/b', 'a/\xc3\xa5') # u'a/b', u'a/\xe5'
 
488
        self.assertCmpByDirs(-1, 'b/a', 'b/\xc2\xb5') # u'b/a', u'b/\xb5'
 
489
 
 
490
 
 
491
class TestCompiledCmpByDirs(TestCmpByDirs):
 
492
    """Test the pyrex implementation of cmp_by_dirs"""
495
493
 
496
494
    _test_needs_features = [compiled_dirstate_helpers_feature]
497
495
 
498
 
    def get_lt_by_dirs(self):
499
 
        from ..bzr._dirstate_helpers_pyx import lt_by_dirs
500
 
        return lt_by_dirs
501
 
 
502
 
 
503
 
class TestLtPathByDirblock(tests.TestCase):
504
 
    """Test an implementation of _lt_path_by_dirblock()
505
 
 
506
 
    _lt_path_by_dirblock() compares two paths using the sort order used by
 
496
    def get_cmp_by_dirs(self):
 
497
        from brzlib._dirstate_helpers_pyx import cmp_by_dirs
 
498
        return cmp_by_dirs
 
499
 
 
500
 
 
501
class TestCmpPathByDirblock(tests.TestCase):
 
502
    """Test an implementation of _cmp_path_by_dirblock()
 
503
 
 
504
    _cmp_path_by_dirblock() compares two paths using the sort order used by
507
505
    DirState. All paths in the same directory are sorted together.
508
506
 
509
 
    Child test cases can override ``get_lt_path_by_dirblock`` to test a specific
 
507
    Child test cases can override ``get_cmp_path_by_dirblock`` to test a specific
510
508
    implementation.
511
509
    """
512
510
 
513
 
    def get_lt_path_by_dirblock(self):
514
 
        """Get a specific implementation of _lt_path_by_dirblock."""
515
 
        from ..bzr._dirstate_helpers_py import _lt_path_by_dirblock
516
 
        return _lt_path_by_dirblock
 
511
    def get_cmp_path_by_dirblock(self):
 
512
        """Get a specific implementation of _cmp_path_by_dirblock."""
 
513
        from brzlib._dirstate_helpers_py import _cmp_path_by_dirblock
 
514
        return _cmp_path_by_dirblock
517
515
 
518
 
    def assertLtPathByDirblock(self, paths):
 
516
    def assertCmpPathByDirblock(self, paths):
519
517
        """Compare all paths and make sure they evaluate to the correct order.
520
518
 
521
519
        This does N^2 comparisons. It is assumed that ``paths`` is properly
526
524
        # First, make sure the paths being passed in are correct
527
525
        def _key(p):
528
526
            dirname, basename = os.path.split(p)
529
 
            return dirname.split(b'/'), basename
 
527
            return dirname.split('/'), basename
530
528
        self.assertEqual(sorted(paths, key=_key), paths)
531
529
 
532
 
        lt_path_by_dirblock = self.get_lt_path_by_dirblock()
 
530
        cmp_path_by_dirblock = self.get_cmp_path_by_dirblock()
533
531
        for idx1, path1 in enumerate(paths):
534
532
            for idx2, path2 in enumerate(paths):
535
 
                lt_result = lt_path_by_dirblock(path1, path2)
536
 
                self.assertEqual(idx1 < idx2, lt_result,
537
 
                                 '%s did not state that %r < %r, lt=%s'
538
 
                                 % (lt_path_by_dirblock.__name__,
539
 
                                    path1, path2, lt_result))
 
533
                cmp_val = cmp_path_by_dirblock(path1, path2)
 
534
                if idx1 < idx2:
 
535
                    self.assertTrue(cmp_val < 0,
 
536
                        '%s did not state that %r came before %r, cmp=%s'
 
537
                        % (cmp_path_by_dirblock.__name__,
 
538
                           path1, path2, cmp_val))
 
539
                elif idx1 > idx2:
 
540
                    self.assertTrue(cmp_val > 0,
 
541
                        '%s did not state that %r came after %r, cmp=%s'
 
542
                        % (cmp_path_by_dirblock.__name__,
 
543
                           path1, path2, cmp_val))
 
544
                else: # idx1 == idx2
 
545
                    self.assertTrue(cmp_val == 0,
 
546
                        '%s did not state that %r == %r, cmp=%s'
 
547
                        % (cmp_path_by_dirblock.__name__,
 
548
                           path1, path2, cmp_val))
540
549
 
541
550
    def test_cmp_simple_paths(self):
542
551
        """Compare against the empty string."""
543
 
        self.assertLtPathByDirblock(
544
 
            [b'', b'a', b'ab', b'abc', b'a/b/c', b'b/d/e'])
545
 
        self.assertLtPathByDirblock([b'kl', b'ab/cd', b'ab/ef', b'gh/ij'])
 
552
        self.assertCmpPathByDirblock(['', 'a', 'ab', 'abc', 'a/b/c', 'b/d/e'])
 
553
        self.assertCmpPathByDirblock(['kl', 'ab/cd', 'ab/ef', 'gh/ij'])
546
554
 
547
555
    def test_tricky_paths(self):
548
 
        self.assertLtPathByDirblock([
 
556
        self.assertCmpPathByDirblock([
549
557
            # Contents of ''
550
 
            b'', b'a', b'a-a', b'a=a', b'b',
 
558
            '', 'a', 'a-a', 'a=a', 'b',
551
559
            # Contents of 'a'
552
 
            b'a/a', b'a/a-a', b'a/a=a', b'a/b',
 
560
            'a/a', 'a/a-a', 'a/a=a', 'a/b',
553
561
            # Contents of 'a/a'
554
 
            b'a/a/a', b'a/a/a-a', b'a/a/a=a',
 
562
            'a/a/a', 'a/a/a-a', 'a/a/a=a',
555
563
            # Contents of 'a/a/a'
556
 
            b'a/a/a/a', b'a/a/a/b',
 
564
            'a/a/a/a', 'a/a/a/b',
557
565
            # Contents of 'a/a/a-a',
558
 
            b'a/a/a-a/a', b'a/a/a-a/b',
 
566
            'a/a/a-a/a', 'a/a/a-a/b',
559
567
            # Contents of 'a/a/a=a',
560
 
            b'a/a/a=a/a', b'a/a/a=a/b',
 
568
            'a/a/a=a/a', 'a/a/a=a/b',
561
569
            # Contents of 'a/a-a'
562
 
            b'a/a-a/a',
 
570
            'a/a-a/a',
563
571
            # Contents of 'a/a-a/a'
564
 
            b'a/a-a/a/a', b'a/a-a/a/b',
 
572
            'a/a-a/a/a', 'a/a-a/a/b',
565
573
            # Contents of 'a/a=a'
566
 
            b'a/a=a/a',
 
574
            'a/a=a/a',
567
575
            # Contents of 'a/b'
568
 
            b'a/b/a', b'a/b/b',
 
576
            'a/b/a', 'a/b/b',
569
577
            # Contents of 'a-a',
570
 
            b'a-a/a', b'a-a/b',
 
578
            'a-a/a', 'a-a/b',
571
579
            # Contents of 'a=a',
572
 
            b'a=a/a', b'a=a/b',
 
580
            'a=a/a', 'a=a/b',
573
581
            # Contents of 'b',
574
 
            b'b/a', b'b/b',
 
582
            'b/a', 'b/b',
575
583
            ])
576
 
        self.assertLtPathByDirblock([
577
 
            # content of '/'
578
 
            b'', b'a', b'a-a', b'a-z', b'a=a', b'a=z',
 
584
        self.assertCmpPathByDirblock([
 
585
                 # content of '/'
 
586
                 '', 'a', 'a-a', 'a-z', 'a=a', 'a=z',
579
587
                 # content of 'a/'
580
 
                 b'a/a', b'a/a-a', b'a/a-z',
581
 
                 b'a/a=a', b'a/a=z',
582
 
                 b'a/z', b'a/z-a', b'a/z-z',
583
 
                 b'a/z=a', b'a/z=z',
 
588
                 'a/a', 'a/a-a', 'a/a-z',
 
589
                 'a/a=a', 'a/a=z',
 
590
                 'a/z', 'a/z-a', 'a/z-z',
 
591
                 'a/z=a', 'a/z=z',
584
592
                 # content of 'a/a/'
585
 
                 b'a/a/a', b'a/a/z',
 
593
                 'a/a/a', 'a/a/z',
586
594
                 # content of 'a/a-a'
587
 
                 b'a/a-a/a',
 
595
                 'a/a-a/a',
588
596
                 # content of 'a/a-z'
589
 
                 b'a/a-z/z',
 
597
                 'a/a-z/z',
590
598
                 # content of 'a/a=a'
591
 
                 b'a/a=a/a',
 
599
                 'a/a=a/a',
592
600
                 # content of 'a/a=z'
593
 
                 b'a/a=z/z',
 
601
                 'a/a=z/z',
594
602
                 # content of 'a/z/'
595
 
                 b'a/z/a', b'a/z/z',
 
603
                 'a/z/a', 'a/z/z',
596
604
                 # content of 'a-a'
597
 
                 b'a-a/a',
 
605
                 'a-a/a',
598
606
                 # content of 'a-z'
599
 
                 b'a-z/z',
 
607
                 'a-z/z',
600
608
                 # content of 'a=a'
601
 
                 b'a=a/a',
 
609
                 'a=a/a',
602
610
                 # content of 'a=z'
603
 
                 b'a=z/z',
604
 
            ])
 
611
                 'a=z/z',
 
612
                ])
605
613
 
606
614
    def test_unicode_not_allowed(self):
607
 
        lt_path_by_dirblock = self.get_lt_path_by_dirblock()
608
 
        self.assertRaises(TypeError, lt_path_by_dirblock, u'Uni', 'str')
609
 
        self.assertRaises(TypeError, lt_path_by_dirblock, 'str', u'Uni')
610
 
        self.assertRaises(TypeError, lt_path_by_dirblock, u'Uni', u'Uni')
611
 
        self.assertRaises(TypeError, lt_path_by_dirblock, u'x/Uni', 'x/str')
612
 
        self.assertRaises(TypeError, lt_path_by_dirblock, 'x/str', u'x/Uni')
613
 
        self.assertRaises(TypeError, lt_path_by_dirblock, u'x/Uni', u'x/Uni')
 
615
        cmp_path_by_dirblock = self.get_cmp_path_by_dirblock()
 
616
        self.assertRaises(TypeError, cmp_path_by_dirblock, u'Uni', 'str')
 
617
        self.assertRaises(TypeError, cmp_path_by_dirblock, 'str', u'Uni')
 
618
        self.assertRaises(TypeError, cmp_path_by_dirblock, u'Uni', u'Uni')
 
619
        self.assertRaises(TypeError, cmp_path_by_dirblock, u'x/Uni', 'x/str')
 
620
        self.assertRaises(TypeError, cmp_path_by_dirblock, 'x/str', u'x/Uni')
 
621
        self.assertRaises(TypeError, cmp_path_by_dirblock, u'x/Uni', u'x/Uni')
614
622
 
615
623
    def test_nonascii(self):
616
 
        self.assertLtPathByDirblock([
 
624
        self.assertCmpPathByDirblock([
617
625
            # content of '/'
618
 
            b'', b'a', b'\xc2\xb5', b'\xc3\xa5',
 
626
            '', 'a', '\xc2\xb5', '\xc3\xa5',
619
627
            # content of 'a'
620
 
            b'a/a', b'a/\xc2\xb5', b'a/\xc3\xa5',
 
628
            'a/a', 'a/\xc2\xb5', 'a/\xc3\xa5',
621
629
            # content of 'a/a'
622
 
            b'a/a/a', b'a/a/\xc2\xb5', b'a/a/\xc3\xa5',
 
630
            'a/a/a', 'a/a/\xc2\xb5', 'a/a/\xc3\xa5',
623
631
            # content of 'a/\xc2\xb5'
624
 
            b'a/\xc2\xb5/a', b'a/\xc2\xb5/\xc2\xb5', b'a/\xc2\xb5/\xc3\xa5',
 
632
            'a/\xc2\xb5/a', 'a/\xc2\xb5/\xc2\xb5', 'a/\xc2\xb5/\xc3\xa5',
625
633
            # content of 'a/\xc3\xa5'
626
 
            b'a/\xc3\xa5/a', b'a/\xc3\xa5/\xc2\xb5', b'a/\xc3\xa5/\xc3\xa5',
 
634
            'a/\xc3\xa5/a', 'a/\xc3\xa5/\xc2\xb5', 'a/\xc3\xa5/\xc3\xa5',
627
635
            # content of '\xc2\xb5'
628
 
            b'\xc2\xb5/a', b'\xc2\xb5/\xc2\xb5', b'\xc2\xb5/\xc3\xa5',
 
636
            '\xc2\xb5/a', '\xc2\xb5/\xc2\xb5', '\xc2\xb5/\xc3\xa5',
629
637
            # content of '\xc2\xe5'
630
 
            b'\xc3\xa5/a', b'\xc3\xa5/\xc2\xb5', b'\xc3\xa5/\xc3\xa5',
 
638
            '\xc3\xa5/a', '\xc3\xa5/\xc2\xb5', '\xc3\xa5/\xc3\xa5',
631
639
            ])
632
640
 
633
641
 
634
 
class TestCompiledLtPathByDirblock(TestLtPathByDirblock):
635
 
    """Test the pyrex implementation of _lt_path_by_dirblock"""
 
642
class TestCompiledCmpPathByDirblock(TestCmpPathByDirblock):
 
643
    """Test the pyrex implementation of _cmp_path_by_dirblock"""
636
644
 
637
645
    _test_needs_features = [compiled_dirstate_helpers_feature]
638
646
 
639
 
    def get_lt_path_by_dirblock(self):
640
 
        from ..bzr._dirstate_helpers_pyx import _lt_path_by_dirblock
641
 
        return _lt_path_by_dirblock
 
647
    def get_cmp_by_dirs(self):
 
648
        from brzlib._dirstate_helpers_pyx import _cmp_path_by_dirblock
 
649
        return _cmp_path_by_dirblock
642
650
 
643
651
 
644
652
class TestMemRChr(tests.TestCase):
647
655
    _test_needs_features = [compiled_dirstate_helpers_feature]
648
656
 
649
657
    def assertMemRChr(self, expected, s, c):
650
 
        from breezy.bzr._dirstate_helpers_pyx import _py_memrchr
 
658
        from brzlib._dirstate_helpers_pyx import _py_memrchr
651
659
        self.assertEqual(expected, _py_memrchr(s, c))
652
660
 
653
661
    def test_missing(self):
654
 
        self.assertMemRChr(None, b'', b'a')
655
 
        self.assertMemRChr(None, b'', b'c')
656
 
        self.assertMemRChr(None, b'abcdefghijklm', b'q')
657
 
        self.assertMemRChr(None, b'aaaaaaaaaaaaaaaaaaaaaaa', b'b')
 
662
        self.assertMemRChr(None, '', 'a')
 
663
        self.assertMemRChr(None, '', 'c')
 
664
        self.assertMemRChr(None, 'abcdefghijklm', 'q')
 
665
        self.assertMemRChr(None, 'aaaaaaaaaaaaaaaaaaaaaaa', 'b')
658
666
 
659
667
    def test_single_entry(self):
660
 
        self.assertMemRChr(0, b'abcdefghijklm', b'a')
661
 
        self.assertMemRChr(1, b'abcdefghijklm', b'b')
662
 
        self.assertMemRChr(2, b'abcdefghijklm', b'c')
663
 
        self.assertMemRChr(10, b'abcdefghijklm', b'k')
664
 
        self.assertMemRChr(11, b'abcdefghijklm', b'l')
665
 
        self.assertMemRChr(12, b'abcdefghijklm', b'm')
 
668
        self.assertMemRChr(0, 'abcdefghijklm', 'a')
 
669
        self.assertMemRChr(1, 'abcdefghijklm', 'b')
 
670
        self.assertMemRChr(2, 'abcdefghijklm', 'c')
 
671
        self.assertMemRChr(10, 'abcdefghijklm', 'k')
 
672
        self.assertMemRChr(11, 'abcdefghijklm', 'l')
 
673
        self.assertMemRChr(12, 'abcdefghijklm', 'm')
666
674
 
667
675
    def test_multiple(self):
668
 
        self.assertMemRChr(10, b'abcdefjklmabcdefghijklm', b'a')
669
 
        self.assertMemRChr(11, b'abcdefjklmabcdefghijklm', b'b')
670
 
        self.assertMemRChr(12, b'abcdefjklmabcdefghijklm', b'c')
671
 
        self.assertMemRChr(20, b'abcdefjklmabcdefghijklm', b'k')
672
 
        self.assertMemRChr(21, b'abcdefjklmabcdefghijklm', b'l')
673
 
        self.assertMemRChr(22, b'abcdefjklmabcdefghijklm', b'm')
674
 
        self.assertMemRChr(22, b'aaaaaaaaaaaaaaaaaaaaaaa', b'a')
 
676
        self.assertMemRChr(10, 'abcdefjklmabcdefghijklm', 'a')
 
677
        self.assertMemRChr(11, 'abcdefjklmabcdefghijklm', 'b')
 
678
        self.assertMemRChr(12, 'abcdefjklmabcdefghijklm', 'c')
 
679
        self.assertMemRChr(20, 'abcdefjklmabcdefghijklm', 'k')
 
680
        self.assertMemRChr(21, 'abcdefjklmabcdefghijklm', 'l')
 
681
        self.assertMemRChr(22, 'abcdefjklmabcdefghijklm', 'm')
 
682
        self.assertMemRChr(22, 'aaaaaaaaaaaaaaaaaaaaaaa', 'a')
675
683
 
676
684
    def test_with_nulls(self):
677
 
        self.assertMemRChr(10, b'abc\0\0\0jklmabc\0\0\0ghijklm', b'a')
678
 
        self.assertMemRChr(11, b'abc\0\0\0jklmabc\0\0\0ghijklm', b'b')
679
 
        self.assertMemRChr(12, b'abc\0\0\0jklmabc\0\0\0ghijklm', b'c')
680
 
        self.assertMemRChr(20, b'abc\0\0\0jklmabc\0\0\0ghijklm', b'k')
681
 
        self.assertMemRChr(21, b'abc\0\0\0jklmabc\0\0\0ghijklm', b'l')
682
 
        self.assertMemRChr(22, b'abc\0\0\0jklmabc\0\0\0ghijklm', b'm')
683
 
        self.assertMemRChr(22, b'aaa\0\0\0aaaaaaa\0\0\0aaaaaaa', b'a')
684
 
        self.assertMemRChr(9, b'\0\0\0\0\0\0\0\0\0\0', b'\0')
 
685
        self.assertMemRChr(10, 'abc\0\0\0jklmabc\0\0\0ghijklm', 'a')
 
686
        self.assertMemRChr(11, 'abc\0\0\0jklmabc\0\0\0ghijklm', 'b')
 
687
        self.assertMemRChr(12, 'abc\0\0\0jklmabc\0\0\0ghijklm', 'c')
 
688
        self.assertMemRChr(20, 'abc\0\0\0jklmabc\0\0\0ghijklm', 'k')
 
689
        self.assertMemRChr(21, 'abc\0\0\0jklmabc\0\0\0ghijklm', 'l')
 
690
        self.assertMemRChr(22, 'abc\0\0\0jklmabc\0\0\0ghijklm', 'm')
 
691
        self.assertMemRChr(22, 'aaa\0\0\0aaaaaaa\0\0\0aaaaaaa', 'a')
 
692
        self.assertMemRChr(9, '\0\0\0\0\0\0\0\0\0\0', '\0')
685
693
 
686
694
 
687
695
class TestReadDirblocks(test_dirstate.TestCaseWithDirState):
697
705
    # inherits scenarios from test_dirstate
698
706
 
699
707
    def get_read_dirblocks(self):
700
 
        from breezy.bzr._dirstate_helpers_py import _read_dirblocks
 
708
        from brzlib._dirstate_helpers_py import _read_dirblocks
701
709
        return _read_dirblocks
702
710
 
703
711
    def test_smoketest(self):
721
729
        f = open('dirstate', 'ab')
722
730
        try:
723
731
            # Add bogus trailing garbage
724
 
            f.write(b'bogus\n')
 
732
            f.write('bogus\n')
725
733
        finally:
726
734
            f.close()
727
735
            state.lock_read()
728
 
        e = self.assertRaises(dirstate.DirstateCorrupt,
 
736
        e = self.assertRaises(errors.DirstateCorrupt,
729
737
                              state._read_dirblocks_if_needed)
730
738
        # Make sure we mention the bogus characters in the error
731
739
        self.assertContainsRe(str(e), 'bogus')
737
745
    _test_needs_features = [compiled_dirstate_helpers_feature]
738
746
 
739
747
    def get_read_dirblocks(self):
740
 
        from breezy.bzr._dirstate_helpers_pyx import _read_dirblocks
 
748
        from brzlib._dirstate_helpers_pyx import _read_dirblocks
741
749
        return _read_dirblocks
742
750
 
743
751
 
751
759
 
752
760
    def test_bisect_dirblock(self):
753
761
        if compiled_dirstate_helpers_feature.available():
754
 
            from breezy.bzr._dirstate_helpers_pyx import bisect_dirblock
 
762
            from brzlib._dirstate_helpers_pyx import bisect_dirblock
755
763
        else:
756
 
            from breezy.bzr._dirstate_helpers_py import bisect_dirblock
 
764
            from brzlib._dirstate_helpers_py import bisect_dirblock
757
765
        self.assertIs(bisect_dirblock, dirstate.bisect_dirblock)
758
766
 
759
767
    def test__bisect_path_left(self):
760
768
        if compiled_dirstate_helpers_feature.available():
761
 
            from breezy.bzr._dirstate_helpers_pyx import _bisect_path_left
 
769
            from brzlib._dirstate_helpers_pyx import _bisect_path_left
762
770
        else:
763
 
            from breezy.bzr._dirstate_helpers_py import _bisect_path_left
 
771
            from brzlib._dirstate_helpers_py import _bisect_path_left
764
772
        self.assertIs(_bisect_path_left, dirstate._bisect_path_left)
765
773
 
766
774
    def test__bisect_path_right(self):
767
775
        if compiled_dirstate_helpers_feature.available():
768
 
            from breezy.bzr._dirstate_helpers_pyx import _bisect_path_right
 
776
            from brzlib._dirstate_helpers_pyx import _bisect_path_right
769
777
        else:
770
 
            from breezy.bzr._dirstate_helpers_py import _bisect_path_right
 
778
            from brzlib._dirstate_helpers_py import _bisect_path_right
771
779
        self.assertIs(_bisect_path_right, dirstate._bisect_path_right)
772
780
 
773
 
    def test_lt_by_dirs(self):
 
781
    def test_cmp_by_dirs(self):
774
782
        if compiled_dirstate_helpers_feature.available():
775
 
            from ..bzr._dirstate_helpers_pyx import lt_by_dirs
 
783
            from brzlib._dirstate_helpers_pyx import cmp_by_dirs
776
784
        else:
777
 
            from ..bzr._dirstate_helpers_py import lt_by_dirs
778
 
        self.assertIs(lt_by_dirs, dirstate.lt_by_dirs)
 
785
            from brzlib._dirstate_helpers_py import cmp_by_dirs
 
786
        self.assertIs(cmp_by_dirs, dirstate.cmp_by_dirs)
779
787
 
780
788
    def test__read_dirblocks(self):
781
789
        if compiled_dirstate_helpers_feature.available():
782
 
            from breezy.bzr._dirstate_helpers_pyx import _read_dirblocks
 
790
            from brzlib._dirstate_helpers_pyx import _read_dirblocks
783
791
        else:
784
 
            from breezy.bzr._dirstate_helpers_py import _read_dirblocks
 
792
            from brzlib._dirstate_helpers_py import _read_dirblocks
785
793
        self.assertIs(_read_dirblocks, dirstate._read_dirblocks)
786
794
 
787
795
    def test_update_entry(self):
788
796
        if compiled_dirstate_helpers_feature.available():
789
 
            from breezy.bzr._dirstate_helpers_pyx import update_entry
 
797
            from brzlib._dirstate_helpers_pyx import update_entry
790
798
        else:
791
 
            from breezy.bzr.dirstate import update_entry
 
799
            from brzlib.dirstate import update_entry
792
800
        self.assertIs(update_entry, dirstate.update_entry)
793
801
 
794
802
    def test_process_entry(self):
795
803
        if compiled_dirstate_helpers_feature.available():
796
 
            from breezy.bzr._dirstate_helpers_pyx import ProcessEntryC
 
804
            from brzlib._dirstate_helpers_pyx import ProcessEntryC
797
805
            self.assertIs(ProcessEntryC, dirstate._process_entry)
798
806
        else:
799
 
            from breezy.bzr.dirstate import ProcessEntryPython
 
807
            from brzlib.dirstate import ProcessEntryPython
800
808
            self.assertIs(ProcessEntryPython, dirstate._process_entry)
801
809
 
802
810
 
817
825
        """Create a DirState tracking a single object named 'a'"""
818
826
        state = test_dirstate.InstrumentedDirState.initialize('dirstate')
819
827
        self.addCleanup(state.unlock)
820
 
        state.add('a', b'a-id', 'file', None, b'')
821
 
        entry = state._get_entry(0, path_utf8=b'a')
 
828
        state.add('a', 'a-id', 'file', None, '')
 
829
        entry = state._get_entry(0, path_utf8='a')
822
830
        return state, entry
823
831
 
824
832
    def test_observed_sha1_cachable(self):
830
838
        statvalue.st_mtime = statvalue.st_ctime = atime
831
839
        self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
832
840
                         state._dirblock_state)
833
 
        state._observed_sha1(entry, b"foo", statvalue)
834
 
        self.assertEqual(b'foo', entry[1][0][1])
 
841
        state._observed_sha1(entry, "foo", statvalue)
 
842
        self.assertEqual('foo', entry[1][0][1])
835
843
        packed_stat = dirstate.pack_stat(statvalue)
836
844
        self.assertEqual(packed_stat, entry[1][0][4])
837
845
        self.assertEqual(dirstate.DirState.IN_MEMORY_HASH_MODIFIED,
858
866
        tree.lock_write()
859
867
        empty_revid = tree.commit('empty')
860
868
        self.build_tree(['tree/a'])
861
 
        tree.add(['a'], [b'a-id'])
 
869
        tree.add(['a'], ['a-id'])
862
870
        with_a_id = tree.commit('with_a')
863
871
        self.addCleanup(tree.unlock)
864
872
        state.set_parent_trees(
865
873
            [(empty_revid, tree.branch.repository.revision_tree(empty_revid))],
866
874
            [])
867
 
        entry = state._get_entry(0, path_utf8=b'a')
 
875
        entry = state._get_entry(0, path_utf8='a')
868
876
        self.build_tree(['a'])
869
877
        # Add one where we don't provide the stat or sha already
870
 
        self.assertEqual((b'', b'a', b'a-id'), entry[0])
871
 
        self.assertEqual((b'f', b'', 0, False, dirstate.DirState.NULLSTAT),
 
878
        self.assertEqual(('', 'a', 'a-id'), entry[0])
 
879
        self.assertEqual(('f', '', 0, False, dirstate.DirState.NULLSTAT),
872
880
                         entry[1][0])
873
881
        # Flush the buffers to disk
874
882
        state.save()
877
885
 
878
886
        stat_value = os.lstat('a')
879
887
        packed_stat = dirstate.pack_stat(stat_value)
880
 
        link_or_sha1 = self.update_entry(state, entry, abspath=b'a',
881
 
                                         stat_value=stat_value)
 
888
        link_or_sha1 = self.update_entry(state, entry, abspath='a',
 
889
                                          stat_value=stat_value)
882
890
        self.assertEqual(None, link_or_sha1)
883
891
 
884
892
        # The dirblock entry should not have computed or cached the file's
885
893
        # sha1, but it did update the files' st_size. However, this is not
886
894
        # worth writing a dirstate file for, so we leave the state UNMODIFIED
887
 
        self.assertEqual((b'f', b'', 14, False, dirstate.DirState.NULLSTAT),
 
895
        self.assertEqual(('f', '', 14, False, dirstate.DirState.NULLSTAT),
888
896
                         entry[1][0])
889
897
        self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
890
898
                         state._dirblock_state)
900
908
        state.adjust_time(-10)
901
909
        del state._log[:]
902
910
 
903
 
        link_or_sha1 = self.update_entry(state, entry, abspath=b'a',
904
 
                                         stat_value=stat_value)
 
911
        link_or_sha1 = self.update_entry(state, entry, abspath='a',
 
912
                                          stat_value=stat_value)
905
913
        self.assertEqual([('is_exec', mode, False)], state._log)
906
914
        self.assertEqual(None, link_or_sha1)
907
915
        self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
908
916
                         state._dirblock_state)
909
 
        self.assertEqual((b'f', b'', 14, False, dirstate.DirState.NULLSTAT),
 
917
        self.assertEqual(('f', '', 14, False, dirstate.DirState.NULLSTAT),
910
918
                         entry[1][0])
911
919
        state.save()
912
920
 
914
922
        # won't calculate the sha or cache it.
915
923
        state.adjust_time(+20)
916
924
        del state._log[:]
917
 
        link_or_sha1 = dirstate.update_entry(state, entry, abspath=b'a',
918
 
                                             stat_value=stat_value)
 
925
        link_or_sha1 = dirstate.update_entry(state, entry, abspath='a',
 
926
                                          stat_value=stat_value)
919
927
        self.assertEqual(None, link_or_sha1)
920
928
        self.assertEqual([('is_exec', mode, False)], state._log)
921
 
        self.assertEqual((b'f', b'', 14, False, dirstate.DirState.NULLSTAT),
 
929
        self.assertEqual(('f', '', 14, False, dirstate.DirState.NULLSTAT),
922
930
                         entry[1][0])
923
931
        self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
924
932
                         state._dirblock_state)
929
937
        state.set_parent_trees(
930
938
            [(with_a_id, tree.branch.repository.revision_tree(with_a_id))],
931
939
            [])
932
 
        entry = state._get_entry(0, path_utf8=b'a')
 
940
        entry = state._get_entry(0, path_utf8='a')
933
941
 
934
 
        link_or_sha1 = self.update_entry(state, entry, abspath=b'a',
935
 
                                         stat_value=stat_value)
936
 
        self.assertEqual(b'b50e5406bb5e153ebbeb20268fcf37c87e1ecfb6',
 
942
        link_or_sha1 = self.update_entry(state, entry, abspath='a',
 
943
                                          stat_value=stat_value)
 
944
        self.assertEqual('b50e5406bb5e153ebbeb20268fcf37c87e1ecfb6',
937
945
                         link_or_sha1)
938
 
        self.assertEqual([('is_exec', mode, False), ('sha1', b'a')],
939
 
                         state._log)
940
 
        self.assertEqual((b'f', link_or_sha1, 14, False, packed_stat),
 
946
        self.assertEqual([('is_exec', mode, False), ('sha1', 'a')],
 
947
                          state._log)
 
948
        self.assertEqual(('f', link_or_sha1, 14, False, packed_stat),
941
949
                         entry[1][0])
942
950
 
943
951
        # Subsequent calls will just return the cached value
944
952
        del state._log[:]
945
 
        link_or_sha1 = self.update_entry(state, entry, abspath=b'a',
946
 
                                         stat_value=stat_value)
947
 
        self.assertEqual(b'b50e5406bb5e153ebbeb20268fcf37c87e1ecfb6',
 
953
        link_or_sha1 = self.update_entry(state, entry, abspath='a',
 
954
                                          stat_value=stat_value)
 
955
        self.assertEqual('b50e5406bb5e153ebbeb20268fcf37c87e1ecfb6',
948
956
                         link_or_sha1)
949
957
        self.assertEqual([], state._log)
950
 
        self.assertEqual((b'f', link_or_sha1, 14, False, packed_stat),
 
958
        self.assertEqual(('f', link_or_sha1, 14, False, packed_stat),
951
959
                         entry[1][0])
952
960
 
953
961
    def test_update_entry_symlink(self):
959
967
                         state._dirblock_state)
960
968
        os.symlink('target', 'a')
961
969
 
962
 
        state.adjust_time(-10)  # Make the symlink look new
 
970
        state.adjust_time(-10) # Make the symlink look new
963
971
        stat_value = os.lstat('a')
964
972
        packed_stat = dirstate.pack_stat(stat_value)
965
 
        link_or_sha1 = self.update_entry(state, entry, abspath=b'a',
966
 
                                         stat_value=stat_value)
967
 
        self.assertEqual(b'target', link_or_sha1)
968
 
        self.assertEqual([('read_link', b'a', b'')], state._log)
 
973
        link_or_sha1 = self.update_entry(state, entry, abspath='a',
 
974
                                          stat_value=stat_value)
 
975
        self.assertEqual('target', link_or_sha1)
 
976
        self.assertEqual([('read_link', 'a', '')], state._log)
969
977
        # Dirblock is not updated (the link is too new)
970
 
        self.assertEqual([(b'l', b'', 6, False, dirstate.DirState.NULLSTAT)],
 
978
        self.assertEqual([('l', '', 6, False, dirstate.DirState.NULLSTAT)],
971
979
                         entry[1])
972
980
        # The file entry turned into a symlink, that is considered
973
981
        # HASH modified worthy.
976
984
 
977
985
        # Because the stat_value looks new, we should re-read the target
978
986
        del state._log[:]
979
 
        link_or_sha1 = self.update_entry(state, entry, abspath=b'a',
980
 
                                         stat_value=stat_value)
981
 
        self.assertEqual(b'target', link_or_sha1)
982
 
        self.assertEqual([('read_link', b'a', b'')], state._log)
983
 
        self.assertEqual([(b'l', b'', 6, False, dirstate.DirState.NULLSTAT)],
 
987
        link_or_sha1 = self.update_entry(state, entry, abspath='a',
 
988
                                          stat_value=stat_value)
 
989
        self.assertEqual('target', link_or_sha1)
 
990
        self.assertEqual([('read_link', 'a', '')], state._log)
 
991
        self.assertEqual([('l', '', 6, False, dirstate.DirState.NULLSTAT)],
984
992
                         entry[1])
985
993
        state.save()
986
 
        state.adjust_time(+20)  # Skip into the future, all files look old
 
994
        state.adjust_time(+20) # Skip into the future, all files look old
987
995
        del state._log[:]
988
 
        link_or_sha1 = self.update_entry(state, entry, abspath=b'a',
989
 
                                         stat_value=stat_value)
 
996
        link_or_sha1 = self.update_entry(state, entry, abspath='a',
 
997
                                          stat_value=stat_value)
990
998
        # The symlink stayed a symlink. So while it is new enough to cache, we
991
999
        # don't bother setting the flag, because it is not really worth saving
992
1000
        # (when we stat the symlink, we'll have paged in the target.)
993
1001
        self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
994
1002
                         state._dirblock_state)
995
 
        self.assertEqual(b'target', link_or_sha1)
 
1003
        self.assertEqual('target', link_or_sha1)
996
1004
        # We need to re-read the link because only now can we cache it
997
 
        self.assertEqual([('read_link', b'a', b'')], state._log)
998
 
        self.assertEqual([(b'l', b'target', 6, False, packed_stat)],
 
1005
        self.assertEqual([('read_link', 'a', '')], state._log)
 
1006
        self.assertEqual([('l', 'target', 6, False, packed_stat)],
999
1007
                         entry[1])
1000
1008
 
1001
1009
        del state._log[:]
1002
1010
        # Another call won't re-read the link
1003
1011
        self.assertEqual([], state._log)
1004
 
        link_or_sha1 = self.update_entry(state, entry, abspath=b'a',
1005
 
                                         stat_value=stat_value)
1006
 
        self.assertEqual(b'target', link_or_sha1)
1007
 
        self.assertEqual([(b'l', b'target', 6, False, packed_stat)],
 
1012
        link_or_sha1 = self.update_entry(state, entry, abspath='a',
 
1013
                                          stat_value=stat_value)
 
1014
        self.assertEqual('target', link_or_sha1)
 
1015
        self.assertEqual([('l', 'target', 6, False, packed_stat)],
1008
1016
                         entry[1])
1009
1017
 
1010
1018
    def do_update_entry(self, state, entry, abspath):
1014
1022
    def test_update_entry_dir(self):
1015
1023
        state, entry = self.get_state_with_a()
1016
1024
        self.build_tree(['a/'])
1017
 
        self.assertIs(None, self.do_update_entry(state, entry, b'a'))
 
1025
        self.assertIs(None, self.do_update_entry(state, entry, 'a'))
1018
1026
 
1019
1027
    def test_update_entry_dir_unchanged(self):
1020
1028
        state, entry = self.get_state_with_a()
1021
1029
        self.build_tree(['a/'])
1022
1030
        state.adjust_time(+20)
1023
 
        self.assertIs(None, self.do_update_entry(state, entry, b'a'))
 
1031
        self.assertIs(None, self.do_update_entry(state, entry, 'a'))
1024
1032
        # a/ used to be a file, but is now a directory, worth saving
1025
1033
        self.assertEqual(dirstate.DirState.IN_MEMORY_MODIFIED,
1026
1034
                         state._dirblock_state)
1028
1036
        self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
1029
1037
                         state._dirblock_state)
1030
1038
        # No changes to a/ means not worth saving.
1031
 
        self.assertIs(None, self.do_update_entry(state, entry, b'a'))
 
1039
        self.assertIs(None, self.do_update_entry(state, entry, 'a'))
1032
1040
        self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
1033
1041
                         state._dirblock_state)
1034
1042
        # Change the last-modified time for the directory
1039
1047
            # It looks like Win32 + FAT doesn't allow to change times on a dir.
1040
1048
            raise tests.TestSkipped("can't update mtime of a dir on FAT")
1041
1049
        saved_packed_stat = entry[1][0][-1]
1042
 
        self.assertIs(None, self.do_update_entry(state, entry, b'a'))
 
1050
        self.assertIs(None, self.do_update_entry(state, entry, 'a'))
1043
1051
        # We *do* go ahead and update the information in the dirblocks, but we
1044
1052
        # don't bother setting IN_MEMORY_MODIFIED because it is trivial to
1045
1053
        # recompute.
1052
1060
        tree = self.make_branch_and_tree('tree')
1053
1061
        tree.lock_write()
1054
1062
        self.build_tree(['tree/a'])
1055
 
        tree.add(['a'], [b'a-id'])
 
1063
        tree.add(['a'], ['a-id'])
1056
1064
        with_a_id = tree.commit('witha')
1057
1065
        self.addCleanup(tree.unlock)
1058
1066
        state.set_parent_trees(
1059
1067
            [(with_a_id, tree.branch.repository.revision_tree(with_a_id))],
1060
1068
            [])
1061
 
        entry = state._get_entry(0, path_utf8=b'a')
 
1069
        entry = state._get_entry(0, path_utf8='a')
1062
1070
        self.build_tree(['a'])
1063
 
        sha1sum = b'b50e5406bb5e153ebbeb20268fcf37c87e1ecfb6'
 
1071
        sha1sum = 'b50e5406bb5e153ebbeb20268fcf37c87e1ecfb6'
1064
1072
        state.adjust_time(+20)
1065
 
        self.assertEqual(sha1sum, self.do_update_entry(state, entry, b'a'))
 
1073
        self.assertEqual(sha1sum, self.do_update_entry(state, entry, 'a'))
1066
1074
        self.assertEqual(dirstate.DirState.IN_MEMORY_MODIFIED,
1067
1075
                         state._dirblock_state)
1068
1076
        state.save()
1069
1077
        self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
1070
1078
                         state._dirblock_state)
1071
 
        self.assertEqual(sha1sum, self.do_update_entry(state, entry, b'a'))
 
1079
        self.assertEqual(sha1sum, self.do_update_entry(state, entry, 'a'))
1072
1080
        self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
1073
1081
                         state._dirblock_state)
1074
1082
 
1075
1083
    def test_update_entry_tree_reference(self):
1076
1084
        state = test_dirstate.InstrumentedDirState.initialize('dirstate')
1077
1085
        self.addCleanup(state.unlock)
1078
 
        state.add('r', b'r-id', 'tree-reference', None, b'')
 
1086
        state.add('r', 'r-id', 'tree-reference', None, '')
1079
1087
        self.build_tree(['r/'])
1080
 
        entry = state._get_entry(0, path_utf8=b'r')
 
1088
        entry = state._get_entry(0, path_utf8='r')
1081
1089
        self.do_update_entry(state, entry, 'r')
1082
 
        entry = state._get_entry(0, path_utf8=b'r')
1083
 
        self.assertEqual(b't', entry[1][0][0])
 
1090
        entry = state._get_entry(0, path_utf8='r')
 
1091
        self.assertEqual('t', entry[1][0][0])
1084
1092
 
1085
1093
    def create_and_test_file(self, state, entry):
1086
1094
        """Create a file at 'a' and verify the state finds it during update.
1094
1102
 
1095
1103
        link_or_sha1 = self.do_update_entry(state, entry, abspath='a')
1096
1104
        self.assertEqual(None, link_or_sha1)
1097
 
        self.assertEqual([(b'f', b'', 14, False, dirstate.DirState.NULLSTAT)],
 
1105
        self.assertEqual([('f', '', 14, False, dirstate.DirState.NULLSTAT)],
1098
1106
                         entry[1])
1099
1107
        return packed_stat
1100
1108
 
1108
1116
        stat_value = os.lstat('a')
1109
1117
        packed_stat = dirstate.pack_stat(stat_value)
1110
1118
 
1111
 
        link_or_sha1 = self.do_update_entry(state, entry, abspath=b'a')
 
1119
        link_or_sha1 = self.do_update_entry(state, entry, abspath='a')
1112
1120
        self.assertIs(None, link_or_sha1)
1113
 
        self.assertEqual([(b'd', b'', 0, False, packed_stat)], entry[1])
 
1121
        self.assertEqual([('d', '', 0, False, packed_stat)], entry[1])
1114
1122
 
1115
1123
        return packed_stat
1116
1124
 
1130
1138
        stat_value = os.lstat('a')
1131
1139
        packed_stat = dirstate.pack_stat(stat_value)
1132
1140
 
1133
 
        link_or_sha1 = self.do_update_entry(state, entry, abspath=b'a')
1134
 
        self.assertEqual(b'path/to/foo', link_or_sha1)
1135
 
        self.assertEqual([(b'l', b'path/to/foo', 11, False, packed_stat)],
 
1141
        link_or_sha1 = self.do_update_entry(state, entry, abspath='a')
 
1142
        self.assertEqual('path/to/foo', link_or_sha1)
 
1143
        self.assertEqual([('l', 'path/to/foo', 11, False, packed_stat)],
1136
1144
                         entry[1])
1137
1145
        return packed_stat
1138
1146
 
1200
1208
        state, entry = self.get_state_with_a()
1201
1209
        self.build_tree(['a'])
1202
1210
 
1203
 
        # Make sure we are using the version of _is_executable that doesn't
1204
 
        # check the filesystem mode.
1205
 
        state._use_filesystem_for_exec = False
 
1211
        # Make sure we are using the win32 implementation of _is_executable
 
1212
        state._is_executable = state._is_executable_win32
1206
1213
 
1207
1214
        # The file on disk is not executable, but we are marking it as though
1208
 
        # it is. With _use_filesystem_for_exec disabled we ignore what is on
1209
 
        # disk.
1210
 
        entry[1][0] = (b'f', b'', 0, True, dirstate.DirState.NULLSTAT)
 
1215
        # it is. With _is_executable_win32 we ignore what is on disk.
 
1216
        entry[1][0] = ('f', '', 0, True, dirstate.DirState.NULLSTAT)
1211
1217
 
1212
1218
        stat_value = os.lstat('a')
1213
1219
        packed_stat = dirstate.pack_stat(stat_value)
1214
1220
 
1215
 
        state.adjust_time(-10)  # Make sure everything is new
1216
 
        self.update_entry(state, entry, abspath=b'a', stat_value=stat_value)
 
1221
        state.adjust_time(-10) # Make sure everything is new
 
1222
        self.update_entry(state, entry, abspath='a', stat_value=stat_value)
1217
1223
 
1218
1224
        # The row is updated, but the executable bit stays set.
1219
 
        self.assertEqual([(b'f', b'', 14, True, dirstate.DirState.NULLSTAT)],
 
1225
        self.assertEqual([('f', '', 14, True, dirstate.DirState.NULLSTAT)],
1220
1226
                         entry[1])
1221
1227
 
1222
1228
        # Make the disk object look old enough to cache (but it won't cache the
1223
1229
        # sha as it is a new file).
1224
1230
        state.adjust_time(+20)
1225
 
        digest = b'b50e5406bb5e153ebbeb20268fcf37c87e1ecfb6'
1226
 
        self.update_entry(state, entry, abspath=b'a', stat_value=stat_value)
1227
 
        self.assertEqual([(b'f', b'', 14, True, dirstate.DirState.NULLSTAT)],
1228
 
                         entry[1])
 
1231
        digest = 'b50e5406bb5e153ebbeb20268fcf37c87e1ecfb6'
 
1232
        self.update_entry(state, entry, abspath='a', stat_value=stat_value)
 
1233
        self.assertEqual([('f', '', 14, True, dirstate.DirState.NULLSTAT)],
 
1234
            entry[1])
1229
1235
 
1230
1236
    def _prepare_tree(self):
1231
1237
        # Create a tree
1232
 
        text = b'Hello World\n'
 
1238
        text = 'Hello World\n'
1233
1239
        tree = self.make_branch_and_tree('tree')
1234
1240
        self.build_tree_contents([('tree/a file', text)])
1235
 
        tree.add('a file', b'a-file-id')
 
1241
        tree.add('a file', 'a-file-id')
1236
1242
        # Note: dirstate does not sha prior to the first commit
1237
1243
        # so commit now in order for the test to work
1238
1244
        tree.commit('first')
1241
1247
    def test_sha1provider_sha1_used(self):
1242
1248
        tree, text = self._prepare_tree()
1243
1249
        state = dirstate.DirState.from_tree(tree, 'dirstate',
1244
 
                                            UppercaseSHA1Provider())
 
1250
            UppercaseSHA1Provider())
1245
1251
        self.addCleanup(state.unlock)
1246
 
        expected_sha = osutils.sha_string(text.upper() + b"foo")
1247
 
        entry = state._get_entry(0, path_utf8=b'a file')
1248
 
        self.assertNotEqual((None, None), entry)
 
1252
        expected_sha = osutils.sha_string(text.upper() + "foo")
 
1253
        entry = state._get_entry(0, path_utf8='a file')
1249
1254
        state._sha_cutoff_time()
1250
1255
        state._cutoff_time += 10
1251
1256
        sha1 = self.update_entry(state, entry, 'tree/a file',
1260
1265
        state._sha1_provider = UppercaseSHA1Provider()
1261
1266
        # If we used the standard provider, it would look like nothing has
1262
1267
        # changed
1263
 
        file_ids_changed = [change.file_id for change
 
1268
        file_ids_changed = [change[0] for change
1264
1269
                            in tree.iter_changes(tree.basis_tree())]
1265
 
        self.assertEqual([b'a-file-id'], file_ids_changed)
 
1270
        self.assertEqual(['a-file-id'], file_ids_changed)
1266
1271
 
1267
1272
 
1268
1273
class UppercaseSHA1Provider(dirstate.SHA1Provider):
1272
1277
        return self.stat_and_sha1(abspath)[1]
1273
1278
 
1274
1279
    def stat_and_sha1(self, abspath):
1275
 
        with open(abspath, 'rb') as file_obj:
 
1280
        file_obj = file(abspath, 'rb')
 
1281
        try:
1276
1282
            statvalue = os.fstat(file_obj.fileno())
1277
 
            text = b''.join(file_obj.readlines())
1278
 
            sha1 = osutils.sha_string(text.upper() + b"foo")
 
1283
            text = ''.join(file_obj.readlines())
 
1284
            sha1 = osutils.sha_string(text.upper() + "foo")
 
1285
        finally:
 
1286
            file_obj.close()
1279
1287
        return statvalue, sha1
1280
1288
 
1281
1289
 
1291
1299
        self.overrideAttr(dirstate, '_process_entry', self._process_entry)
1292
1300
 
1293
1301
    def assertChangedFileIds(self, expected, tree):
1294
 
        with tree.lock_read():
1295
 
            file_ids = [info.file_id for info
 
1302
        tree.lock_read()
 
1303
        try:
 
1304
            file_ids = [info[0] for info
1296
1305
                        in tree.iter_changes(tree.basis_tree())]
 
1306
        finally:
 
1307
            tree.unlock()
1297
1308
        self.assertEqual(sorted(expected), sorted(file_ids))
1298
1309
 
1299
1310
    def test_exceptions_raised(self):
1308
1319
        tree.lock_read()
1309
1320
        self.addCleanup(tree.unlock)
1310
1321
        basis_tree = tree.basis_tree()
1311
 
 
1312
1322
        def is_inside_raises(*args, **kwargs):
1313
1323
            raise RuntimeError('stop this')
1314
 
        self.overrideAttr(dirstate, 'is_inside', is_inside_raises)
1315
 
        try:
1316
 
            from breezy.bzr import _dirstate_helpers_pyx
1317
 
        except ImportError:
1318
 
            pass
1319
 
        else:
1320
 
            self.overrideAttr(_dirstate_helpers_pyx,
1321
 
                              'is_inside', is_inside_raises)
1322
1324
        self.overrideAttr(osutils, 'is_inside', is_inside_raises)
1323
1325
        self.assertListRaises(RuntimeError, tree.iter_changes, basis_tree)
1324
1326
 
1325
1327
    def test_simple_changes(self):
1326
1328
        tree = self.make_branch_and_tree('tree')
1327
1329
        self.build_tree(['tree/file'])
1328
 
        tree.add(['file'], [b'file-id'])
1329
 
        self.assertChangedFileIds([tree.path2id(''), b'file-id'], tree)
 
1330
        tree.add(['file'], ['file-id'])
 
1331
        self.assertChangedFileIds([tree.get_root_id(), 'file-id'], tree)
1330
1332
        tree.commit('one')
1331
1333
        self.assertChangedFileIds([], tree)
1332
1334
 
1333
1335
    def test_sha1provider_stat_and_sha1_used(self):
1334
1336
        tree = self.make_branch_and_tree('tree')
1335
1337
        self.build_tree(['tree/file'])
1336
 
        tree.add(['file'], [b'file-id'])
 
1338
        tree.add(['file'], ['file-id'])
1337
1339
        tree.commit('one')
1338
1340
        tree.lock_write()
1339
1341
        self.addCleanup(tree.unlock)
1340
1342
        state = tree._current_dirstate()
1341
1343
        state._sha1_provider = UppercaseSHA1Provider()
1342
 
        self.assertChangedFileIds([b'file-id'], tree)
 
1344
        self.assertChangedFileIds(['file-id'], tree)
1343
1345
 
1344
1346
 
1345
1347
class TestPackStat(tests.TestCase):
1355
1357
        return _dirstate_helpers_py._unpack_stat(packed_string)[stat_field]
1356
1358
 
1357
1359
    def test_result(self):
1358
 
        self.assertEqual(b"AAAQAAAAABAAAAARAAAAAgAAAAEAAIHk",
1359
 
                         self.pack((33252, 1, 2, 0, 0, 0, 4096, 15.5, 16.5, 17.5)))
 
1360
        self.assertEqual("AAAQAAAAABAAAAARAAAAAgAAAAEAAIHk",
 
1361
            self.pack((33252, 1, 2, 0, 0, 0, 4096, 15.5, 16.5, 17.5)))
1360
1362
 
1361
1363
    def test_giant_inode(self):
1362
1364
        packed = self.pack((33252, 0xF80000ABC, 0, 0, 0, 0, 0, 0, 0, 0))