120
121
bisect_split_idx, bisect_path_idx, path)
123
self.assertEqual(path, paths[bisect_path_idx + offset])
124
self.assertEqual(path, paths[bisect_path_idx+offset])
125
126
def split_for_dirblocks(self, paths):
126
127
dir_split_paths = []
127
128
for path in paths:
128
129
dirname, basename = os.path.split(path)
129
dir_split_paths.append((dirname.split(b'/'), basename))
130
dir_split_paths.append((dirname.split('/'), basename))
130
131
dir_split_paths.sort()
131
132
return dir_split_paths
133
134
def test_simple(self):
134
135
"""In the simple case it works just like bisect_left"""
135
paths = [b'', b'a', b'b', b'c', b'd']
136
paths = ['', 'a', 'b', 'c', 'd']
136
137
split_paths = self.split_for_dirblocks(paths)
137
138
for path in paths:
138
139
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)
140
self.assertBisect(paths, split_paths, '_', exists=False)
141
self.assertBisect(paths, split_paths, 'aa', exists=False)
142
self.assertBisect(paths, split_paths, 'bb', exists=False)
143
self.assertBisect(paths, split_paths, 'cc', exists=False)
144
self.assertBisect(paths, split_paths, 'dd', exists=False)
145
self.assertBisect(paths, split_paths, 'a/a', exists=False)
146
self.assertBisect(paths, split_paths, 'b/b', exists=False)
147
self.assertBisect(paths, split_paths, 'c/c', exists=False)
148
self.assertBisect(paths, split_paths, 'd/d', exists=False)
149
150
def test_involved(self):
150
151
"""This is where bisect_path_* diverges slightly."""
309
310
Also, ensure that the paths are in proper sorted order.
311
312
dirblocks = [(path, []) for path in paths]
312
split_dirblocks = [(path.split(b'/'), []) for path in paths]
313
split_dirblocks = [(path.split('/'), []) for path in paths]
313
314
self.assertEqual(sorted(split_dirblocks), split_dirblocks)
314
315
return dirblocks, split_dirblocks
316
317
def test_simple(self):
317
318
"""In the simple case it works just like bisect_left"""
318
paths = [b'', b'a', b'b', b'c', b'd']
319
paths = ['', 'a', 'b', 'c', 'd']
319
320
dirblocks, split_dirblocks = self.paths_to_dirblocks(paths)
320
321
for path in paths:
321
322
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')
323
self.assertBisect(dirblocks, split_dirblocks, '_')
324
self.assertBisect(dirblocks, split_dirblocks, 'aa')
325
self.assertBisect(dirblocks, split_dirblocks, 'bb')
326
self.assertBisect(dirblocks, split_dirblocks, 'cc')
327
self.assertBisect(dirblocks, split_dirblocks, 'dd')
328
self.assertBisect(dirblocks, split_dirblocks, 'a/a')
329
self.assertBisect(dirblocks, split_dirblocks, 'b/b')
330
self.assertBisect(dirblocks, split_dirblocks, 'c/c')
331
self.assertBisect(dirblocks, split_dirblocks, 'd/d')
332
333
def test_involved(self):
333
334
"""This is where bisect_left diverges slightly."""
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',
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',
336
'a/a', 'a/a/a', 'a/a/z', 'a/a-a', 'a/a-z',
337
'a/z', 'a/z/a', 'a/z/z', 'a/z-a', 'a/z-z',
339
'z', 'z/a/a', 'z/a/z', 'z/a-a', 'z/a-z',
340
'z/z', 'z/z/a', 'z/z/z', 'z/z-a', 'z/z-z',
342
343
dirblocks, split_dirblocks = self.paths_to_dirblocks(paths)
343
344
for path in paths:
344
345
self.assertBisect(dirblocks, split_dirblocks, path)
346
347
def test_involved_cached(self):
347
348
"""This is where bisect_left diverges slightly."""
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',
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',
350
'a/a', 'a/a/a', 'a/a/z', 'a/a-a', 'a/a-z',
351
'a/z', 'a/z/a', 'a/z/z', 'a/z-a', 'a/z-z',
353
'z', 'z/a/a', 'z/a/z', 'z/a-a', 'z/a-z',
354
'z/z', 'z/z/a', 'z/z/z', 'z/z-a', 'z/z-z',
357
358
dirblocks, split_dirblocks = self.paths_to_dirblocks(paths)
358
359
for path in paths:
400
401
:param str1: string to compare
401
402
:param str2: string to compare
403
lt_by_dirs = self.get_lt_by_dirs()
404
cmp_by_dirs = self.get_cmp_by_dirs()
404
405
if expected == 0:
405
406
self.assertEqual(str1, str2)
406
self.assertFalse(lt_by_dirs(str1, str2))
407
self.assertFalse(lt_by_dirs(str2, str1))
407
self.assertEqual(0, cmp_by_dirs(str1, str2))
408
self.assertEqual(0, cmp_by_dirs(str2, str1))
408
409
elif expected > 0:
409
self.assertFalse(lt_by_dirs(str1, str2))
410
self.assertTrue(lt_by_dirs(str2, str1))
410
self.assertPositive(cmp_by_dirs(str1, str2))
411
self.assertNegative(cmp_by_dirs(str2, str1))
412
self.assertTrue(lt_by_dirs(str1, str2))
413
self.assertFalse(lt_by_dirs(str2, str1))
413
self.assertNegative(cmp_by_dirs(str1, str2))
414
self.assertPositive(cmp_by_dirs(str2, str1))
415
416
def test_cmp_empty(self):
416
417
"""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'')
418
self.assertCmpByDirs(0, '', '')
419
self.assertCmpByDirs(1, 'a', '')
420
self.assertCmpByDirs(1, 'ab', '')
421
self.assertCmpByDirs(1, 'abc', '')
422
self.assertCmpByDirs(1, 'abcd', '')
423
self.assertCmpByDirs(1, 'abcde', '')
424
self.assertCmpByDirs(1, 'abcdef', '')
425
self.assertCmpByDirs(1, 'abcdefg', '')
426
self.assertCmpByDirs(1, 'abcdefgh', '')
427
self.assertCmpByDirs(1, 'abcdefghi', '')
428
self.assertCmpByDirs(1, 'test/ing/a/path/', '')
429
430
def test_cmp_same_str(self):
430
431
"""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')
432
self.assertCmpByDirs(0, 'a', 'a')
433
self.assertCmpByDirs(0, 'ab', 'ab')
434
self.assertCmpByDirs(0, 'abc', 'abc')
435
self.assertCmpByDirs(0, 'abcd', 'abcd')
436
self.assertCmpByDirs(0, 'abcde', 'abcde')
437
self.assertCmpByDirs(0, 'abcdef', 'abcdef')
438
self.assertCmpByDirs(0, 'abcdefg', 'abcdefg')
439
self.assertCmpByDirs(0, 'abcdefgh', 'abcdefgh')
440
self.assertCmpByDirs(0, 'abcdefghi', 'abcdefghi')
441
self.assertCmpByDirs(0, 'testing a long string', 'testing a long string')
442
self.assertCmpByDirs(0, 'x'*10000, 'x'*10000)
443
self.assertCmpByDirs(0, 'a/b', 'a/b')
444
self.assertCmpByDirs(0, 'a/b/c', 'a/b/c')
445
self.assertCmpByDirs(0, 'a/b/c/d', 'a/b/c/d')
446
self.assertCmpByDirs(0, 'a/b/c/d/e', 'a/b/c/d/e')
448
448
def test_simple_paths(self):
449
449
"""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')
450
self.assertCmpByDirs(-1, 'a', 'b')
451
self.assertCmpByDirs(-1, 'aa', 'ab')
452
self.assertCmpByDirs(-1, 'ab', 'bb')
453
self.assertCmpByDirs(-1, 'aaa', 'aab')
454
self.assertCmpByDirs(-1, 'aab', 'abb')
455
self.assertCmpByDirs(-1, 'abb', 'bbb')
456
self.assertCmpByDirs(-1, 'aaaa', 'aaab')
457
self.assertCmpByDirs(-1, 'aaab', 'aabb')
458
self.assertCmpByDirs(-1, 'aabb', 'abbb')
459
self.assertCmpByDirs(-1, 'abbb', 'bbbb')
460
self.assertCmpByDirs(-1, 'aaaaa', 'aaaab')
461
self.assertCmpByDirs(-1, 'a/a', 'a/b')
462
self.assertCmpByDirs(-1, 'a/b', 'b/b')
463
self.assertCmpByDirs(-1, 'a/a/a', 'a/a/b')
464
self.assertCmpByDirs(-1, 'a/a/b', 'a/b/b')
465
self.assertCmpByDirs(-1, 'a/b/b', 'b/b/b')
466
self.assertCmpByDirs(-1, 'a/a/a/a', 'a/a/a/b')
467
self.assertCmpByDirs(-1, 'a/a/a/b', 'a/a/b/b')
468
self.assertCmpByDirs(-1, 'a/a/b/b', 'a/b/b/b')
469
self.assertCmpByDirs(-1, 'a/b/b/b', 'b/b/b/b')
470
self.assertCmpByDirs(-1, 'a/a/a/a/a', 'a/a/a/a/b')
472
472
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')
473
self.assertCmpByDirs(1, 'ab/cd/ef', 'ab/cc/ef')
474
self.assertCmpByDirs(1, 'ab/cd/ef', 'ab/c/ef')
475
self.assertCmpByDirs(-1, 'ab/cd/ef', 'ab/cd-ef')
476
self.assertCmpByDirs(-1, 'ab/cd', 'ab/cd-')
477
self.assertCmpByDirs(-1, 'ab/cd', 'ab-cd')
479
479
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')
480
cmp_by_dirs = self.get_cmp_by_dirs()
481
self.assertRaises(TypeError, cmp_by_dirs, u'Unicode', 'str')
482
self.assertRaises(TypeError, cmp_by_dirs, 'str', u'Unicode')
483
self.assertRaises(TypeError, cmp_by_dirs, u'Unicode', u'Unicode')
485
485
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'
493
class TestCompiledLtByDirs(TestLtByDirs):
494
"""Test the pyrex implementation of lt_by_dirs"""
486
self.assertCmpByDirs(-1, '\xc2\xb5', '\xc3\xa5') # u'\xb5', u'\xe5'
487
self.assertCmpByDirs(-1, 'a', '\xc3\xa5') # u'a', u'\xe5'
488
self.assertCmpByDirs(-1, 'b', '\xc2\xb5') # u'b', u'\xb5'
489
self.assertCmpByDirs(-1, 'a/b', 'a/\xc3\xa5') # u'a/b', u'a/\xe5'
490
self.assertCmpByDirs(-1, 'b/a', 'b/\xc2\xb5') # u'b/a', u'b/\xb5'
493
class TestCompiledCmpByDirs(TestCmpByDirs):
494
"""Test the pyrex implementation of cmp_by_dirs"""
496
496
_test_needs_features = [compiled_dirstate_helpers_feature]
498
def get_lt_by_dirs(self):
499
from .._dirstate_helpers_pyx import lt_by_dirs
503
class TestLtPathByDirblock(tests.TestCase):
504
"""Test an implementation of _lt_path_by_dirblock()
506
_lt_path_by_dirblock() compares two paths using the sort order used by
498
def get_cmp_by_dirs(self):
499
from breezy._dirstate_helpers_pyx import cmp_by_dirs
503
class TestCmpPathByDirblock(tests.TestCase):
504
"""Test an implementation of _cmp_path_by_dirblock()
506
_cmp_path_by_dirblock() compares two paths using the sort order used by
507
507
DirState. All paths in the same directory are sorted together.
509
Child test cases can override ``get_lt_path_by_dirblock`` to test a specific
509
Child test cases can override ``get_cmp_path_by_dirblock`` to test a specific
513
def get_lt_path_by_dirblock(self):
514
"""Get a specific implementation of _lt_path_by_dirblock."""
515
from .._dirstate_helpers_py import _lt_path_by_dirblock
516
return _lt_path_by_dirblock
513
def get_cmp_path_by_dirblock(self):
514
"""Get a specific implementation of _cmp_path_by_dirblock."""
515
from breezy._dirstate_helpers_py import _cmp_path_by_dirblock
516
return _cmp_path_by_dirblock
518
def assertLtPathByDirblock(self, paths):
518
def assertCmpPathByDirblock(self, paths):
519
519
"""Compare all paths and make sure they evaluate to the correct order.
521
521
This does N^2 comparisons. It is assumed that ``paths`` is properly
526
526
# First, make sure the paths being passed in are correct
528
528
dirname, basename = os.path.split(p)
529
return dirname.split(b'/'), basename
529
return dirname.split('/'), basename
530
530
self.assertEqual(sorted(paths, key=_key), paths)
532
lt_path_by_dirblock = self.get_lt_path_by_dirblock()
532
cmp_path_by_dirblock = self.get_cmp_path_by_dirblock()
533
533
for idx1, path1 in enumerate(paths):
534
534
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))
535
cmp_val = cmp_path_by_dirblock(path1, path2)
537
self.assertTrue(cmp_val < 0,
538
'%s did not state that %r came before %r, cmp=%s'
539
% (cmp_path_by_dirblock.__name__,
540
path1, path2, cmp_val))
542
self.assertTrue(cmp_val > 0,
543
'%s did not state that %r came after %r, cmp=%s'
544
% (cmp_path_by_dirblock.__name__,
545
path1, path2, cmp_val))
547
self.assertTrue(cmp_val == 0,
548
'%s did not state that %r == %r, cmp=%s'
549
% (cmp_path_by_dirblock.__name__,
550
path1, path2, cmp_val))
541
552
def test_cmp_simple_paths(self):
542
553
"""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'])
554
self.assertCmpPathByDirblock(['', 'a', 'ab', 'abc', 'a/b/c', 'b/d/e'])
555
self.assertCmpPathByDirblock(['kl', 'ab/cd', 'ab/ef', 'gh/ij'])
547
557
def test_tricky_paths(self):
548
self.assertLtPathByDirblock([
558
self.assertCmpPathByDirblock([
550
b'', b'a', b'a-a', b'a=a', b'b',
560
'', 'a', 'a-a', 'a=a', 'b',
551
561
# Contents of 'a'
552
b'a/a', b'a/a-a', b'a/a=a', b'a/b',
562
'a/a', 'a/a-a', 'a/a=a', 'a/b',
553
563
# Contents of 'a/a'
554
b'a/a/a', b'a/a/a-a', b'a/a/a=a',
564
'a/a/a', 'a/a/a-a', 'a/a/a=a',
555
565
# Contents of 'a/a/a'
556
b'a/a/a/a', b'a/a/a/b',
566
'a/a/a/a', 'a/a/a/b',
557
567
# Contents of 'a/a/a-a',
558
b'a/a/a-a/a', b'a/a/a-a/b',
568
'a/a/a-a/a', 'a/a/a-a/b',
559
569
# Contents of 'a/a/a=a',
560
b'a/a/a=a/a', b'a/a/a=a/b',
570
'a/a/a=a/a', 'a/a/a=a/b',
561
571
# Contents of 'a/a-a'
563
573
# Contents of 'a/a-a/a'
564
b'a/a-a/a/a', b'a/a-a/a/b',
574
'a/a-a/a/a', 'a/a-a/a/b',
565
575
# Contents of 'a/a=a'
567
577
# Contents of 'a/b'
569
579
# Contents of 'a-a',
571
581
# Contents of 'a=a',
573
583
# Contents of 'b',
576
self.assertLtPathByDirblock([
578
b'', b'a', b'a-a', b'a-z', b'a=a', b'a=z',
586
self.assertCmpPathByDirblock([
588
'', 'a', 'a-a', 'a-z', 'a=a', 'a=z',
579
589
# content of 'a/'
580
b'a/a', b'a/a-a', b'a/a-z',
582
b'a/z', b'a/z-a', b'a/z-z',
590
'a/a', 'a/a-a', 'a/a-z',
592
'a/z', 'a/z-a', 'a/z-z',
584
594
# content of 'a/a/'
586
596
# content of 'a/a-a'
588
598
# content of 'a/a-z'
590
600
# content of 'a/a=a'
592
602
# content of 'a/a=z'
594
604
# content of 'a/z/'
596
606
# content of 'a-a'
598
608
# content of 'a-z'
600
610
# content of 'a=a'
602
612
# content of 'a=z'
606
616
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')
617
cmp_path_by_dirblock = self.get_cmp_path_by_dirblock()
618
self.assertRaises(TypeError, cmp_path_by_dirblock, u'Uni', 'str')
619
self.assertRaises(TypeError, cmp_path_by_dirblock, 'str', u'Uni')
620
self.assertRaises(TypeError, cmp_path_by_dirblock, u'Uni', u'Uni')
621
self.assertRaises(TypeError, cmp_path_by_dirblock, u'x/Uni', 'x/str')
622
self.assertRaises(TypeError, cmp_path_by_dirblock, 'x/str', u'x/Uni')
623
self.assertRaises(TypeError, cmp_path_by_dirblock, u'x/Uni', u'x/Uni')
615
625
def test_nonascii(self):
616
self.assertLtPathByDirblock([
626
self.assertCmpPathByDirblock([
618
b'', b'a', b'\xc2\xb5', b'\xc3\xa5',
628
'', 'a', '\xc2\xb5', '\xc3\xa5',
620
b'a/a', b'a/\xc2\xb5', b'a/\xc3\xa5',
630
'a/a', 'a/\xc2\xb5', 'a/\xc3\xa5',
621
631
# content of 'a/a'
622
b'a/a/a', b'a/a/\xc2\xb5', b'a/a/\xc3\xa5',
632
'a/a/a', 'a/a/\xc2\xb5', 'a/a/\xc3\xa5',
623
633
# content of 'a/\xc2\xb5'
624
b'a/\xc2\xb5/a', b'a/\xc2\xb5/\xc2\xb5', b'a/\xc2\xb5/\xc3\xa5',
634
'a/\xc2\xb5/a', 'a/\xc2\xb5/\xc2\xb5', 'a/\xc2\xb5/\xc3\xa5',
625
635
# content of 'a/\xc3\xa5'
626
b'a/\xc3\xa5/a', b'a/\xc3\xa5/\xc2\xb5', b'a/\xc3\xa5/\xc3\xa5',
636
'a/\xc3\xa5/a', 'a/\xc3\xa5/\xc2\xb5', 'a/\xc3\xa5/\xc3\xa5',
627
637
# content of '\xc2\xb5'
628
b'\xc2\xb5/a', b'\xc2\xb5/\xc2\xb5', b'\xc2\xb5/\xc3\xa5',
638
'\xc2\xb5/a', '\xc2\xb5/\xc2\xb5', '\xc2\xb5/\xc3\xa5',
629
639
# content of '\xc2\xe5'
630
b'\xc3\xa5/a', b'\xc3\xa5/\xc2\xb5', b'\xc3\xa5/\xc3\xa5',
640
'\xc3\xa5/a', '\xc3\xa5/\xc2\xb5', '\xc3\xa5/\xc3\xa5',
634
class TestCompiledLtPathByDirblock(TestLtPathByDirblock):
635
"""Test the pyrex implementation of _lt_path_by_dirblock"""
644
class TestCompiledCmpPathByDirblock(TestCmpPathByDirblock):
645
"""Test the pyrex implementation of _cmp_path_by_dirblock"""
637
647
_test_needs_features = [compiled_dirstate_helpers_feature]
639
def get_lt_path_by_dirblock(self):
640
from .._dirstate_helpers_pyx import _lt_path_by_dirblock
641
return _lt_path_by_dirblock
649
def get_cmp_by_dirs(self):
650
from breezy._dirstate_helpers_pyx import _cmp_path_by_dirblock
651
return _cmp_path_by_dirblock
644
654
class TestMemRChr(tests.TestCase):
647
657
_test_needs_features = [compiled_dirstate_helpers_feature]
649
659
def assertMemRChr(self, expected, s, c):
650
from .._dirstate_helpers_pyx import _py_memrchr
660
from breezy._dirstate_helpers_pyx import _py_memrchr
651
661
self.assertEqual(expected, _py_memrchr(s, c))
653
663
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')
664
self.assertMemRChr(None, '', 'a')
665
self.assertMemRChr(None, '', 'c')
666
self.assertMemRChr(None, 'abcdefghijklm', 'q')
667
self.assertMemRChr(None, 'aaaaaaaaaaaaaaaaaaaaaaa', 'b')
659
669
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')
670
self.assertMemRChr(0, 'abcdefghijklm', 'a')
671
self.assertMemRChr(1, 'abcdefghijklm', 'b')
672
self.assertMemRChr(2, 'abcdefghijklm', 'c')
673
self.assertMemRChr(10, 'abcdefghijklm', 'k')
674
self.assertMemRChr(11, 'abcdefghijklm', 'l')
675
self.assertMemRChr(12, 'abcdefghijklm', 'm')
667
677
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')
678
self.assertMemRChr(10, 'abcdefjklmabcdefghijklm', 'a')
679
self.assertMemRChr(11, 'abcdefjklmabcdefghijklm', 'b')
680
self.assertMemRChr(12, 'abcdefjklmabcdefghijklm', 'c')
681
self.assertMemRChr(20, 'abcdefjklmabcdefghijklm', 'k')
682
self.assertMemRChr(21, 'abcdefjklmabcdefghijklm', 'l')
683
self.assertMemRChr(22, 'abcdefjklmabcdefghijklm', 'm')
684
self.assertMemRChr(22, 'aaaaaaaaaaaaaaaaaaaaaaa', 'a')
676
686
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')
687
self.assertMemRChr(10, 'abc\0\0\0jklmabc\0\0\0ghijklm', 'a')
688
self.assertMemRChr(11, 'abc\0\0\0jklmabc\0\0\0ghijklm', 'b')
689
self.assertMemRChr(12, 'abc\0\0\0jklmabc\0\0\0ghijklm', 'c')
690
self.assertMemRChr(20, 'abc\0\0\0jklmabc\0\0\0ghijklm', 'k')
691
self.assertMemRChr(21, 'abc\0\0\0jklmabc\0\0\0ghijklm', 'l')
692
self.assertMemRChr(22, 'abc\0\0\0jklmabc\0\0\0ghijklm', 'm')
693
self.assertMemRChr(22, 'aaa\0\0\0aaaaaaa\0\0\0aaaaaaa', 'a')
694
self.assertMemRChr(9, '\0\0\0\0\0\0\0\0\0\0', '\0')
687
697
class TestReadDirblocks(test_dirstate.TestCaseWithDirState):
752
762
def test_bisect_dirblock(self):
753
763
if compiled_dirstate_helpers_feature.available():
754
from .._dirstate_helpers_pyx import bisect_dirblock
764
from breezy._dirstate_helpers_pyx import bisect_dirblock
756
from .._dirstate_helpers_py import bisect_dirblock
766
from breezy._dirstate_helpers_py import bisect_dirblock
757
767
self.assertIs(bisect_dirblock, dirstate.bisect_dirblock)
759
769
def test__bisect_path_left(self):
760
770
if compiled_dirstate_helpers_feature.available():
761
from .._dirstate_helpers_pyx import _bisect_path_left
771
from breezy._dirstate_helpers_pyx import _bisect_path_left
763
from .._dirstate_helpers_py import _bisect_path_left
773
from breezy._dirstate_helpers_py import _bisect_path_left
764
774
self.assertIs(_bisect_path_left, dirstate._bisect_path_left)
766
776
def test__bisect_path_right(self):
767
777
if compiled_dirstate_helpers_feature.available():
768
from .._dirstate_helpers_pyx import _bisect_path_right
778
from breezy._dirstate_helpers_pyx import _bisect_path_right
770
from .._dirstate_helpers_py import _bisect_path_right
780
from breezy._dirstate_helpers_py import _bisect_path_right
771
781
self.assertIs(_bisect_path_right, dirstate._bisect_path_right)
773
def test_lt_by_dirs(self):
783
def test_cmp_by_dirs(self):
774
784
if compiled_dirstate_helpers_feature.available():
775
from .._dirstate_helpers_pyx import lt_by_dirs
785
from breezy._dirstate_helpers_pyx import cmp_by_dirs
777
from .._dirstate_helpers_py import lt_by_dirs
778
self.assertIs(lt_by_dirs, dirstate.lt_by_dirs)
787
from breezy._dirstate_helpers_py import cmp_by_dirs
788
self.assertIs(cmp_by_dirs, dirstate.cmp_by_dirs)
780
790
def test__read_dirblocks(self):
781
791
if compiled_dirstate_helpers_feature.available():
782
from .._dirstate_helpers_pyx import _read_dirblocks
792
from breezy._dirstate_helpers_pyx import _read_dirblocks
784
from .._dirstate_helpers_py import _read_dirblocks
794
from breezy._dirstate_helpers_py import _read_dirblocks
785
795
self.assertIs(_read_dirblocks, dirstate._read_dirblocks)
787
797
def test_update_entry(self):
788
798
if compiled_dirstate_helpers_feature.available():
789
from .._dirstate_helpers_pyx import update_entry
799
from breezy._dirstate_helpers_pyx import update_entry
791
from ..dirstate import update_entry
801
from breezy.dirstate import update_entry
792
802
self.assertIs(update_entry, dirstate.update_entry)
794
804
def test_process_entry(self):
795
805
if compiled_dirstate_helpers_feature.available():
796
from .._dirstate_helpers_pyx import ProcessEntryC
806
from breezy._dirstate_helpers_pyx import ProcessEntryC
797
807
self.assertIs(ProcessEntryC, dirstate._process_entry)
799
from ..dirstate import ProcessEntryPython
809
from breezy.dirstate import ProcessEntryPython
800
810
self.assertIs(ProcessEntryPython, dirstate._process_entry)
977
987
# Because the stat_value looks new, we should re-read the target
978
988
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)],
989
link_or_sha1 = self.update_entry(state, entry, abspath='a',
990
stat_value=stat_value)
991
self.assertEqual('target', link_or_sha1)
992
self.assertEqual([('read_link', 'a', '')], state._log)
993
self.assertEqual([('l', '', 6, False, dirstate.DirState.NULLSTAT)],
986
state.adjust_time(+20) # Skip into the future, all files look old
996
state.adjust_time(+20) # Skip into the future, all files look old
987
997
del state._log[:]
988
link_or_sha1 = self.update_entry(state, entry, abspath=b'a',
989
stat_value=stat_value)
998
link_or_sha1 = self.update_entry(state, entry, abspath='a',
999
stat_value=stat_value)
990
1000
# The symlink stayed a symlink. So while it is new enough to cache, we
991
1001
# don't bother setting the flag, because it is not really worth saving
992
1002
# (when we stat the symlink, we'll have paged in the target.)
993
1003
self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
994
1004
state._dirblock_state)
995
self.assertEqual(b'target', link_or_sha1)
1005
self.assertEqual('target', link_or_sha1)
996
1006
# 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)],
1007
self.assertEqual([('read_link', 'a', '')], state._log)
1008
self.assertEqual([('l', 'target', 6, False, packed_stat)],
1001
1011
del state._log[:]
1002
1012
# Another call won't re-read the link
1003
1013
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)],
1014
link_or_sha1 = self.update_entry(state, entry, abspath='a',
1015
stat_value=stat_value)
1016
self.assertEqual('target', link_or_sha1)
1017
self.assertEqual([('l', 'target', 6, False, packed_stat)],
1010
1020
def do_update_entry(self, state, entry, abspath):