120
119
bisect_split_idx, bisect_path_idx, path)
123
self.assertEqual(path, paths[bisect_path_idx + offset])
122
self.assertEqual(path, paths[bisect_path_idx+offset])
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
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)
149
148
def test_involved(self):
150
149
"""This is where bisect_path_* diverges slightly."""
309
308
Also, ensure that the paths are in proper sorted order.
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
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')
332
331
def test_involved(self):
333
332
"""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',
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',
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',
342
341
dirblocks, split_dirblocks = self.paths_to_dirblocks(paths)
343
342
for path in paths:
344
343
self.assertBisect(dirblocks, split_dirblocks, path)
346
345
def test_involved_cached(self):
347
346
"""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',
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',
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',
357
356
dirblocks, split_dirblocks = self.paths_to_dirblocks(paths)
358
357
for path in paths:
400
399
:param str1: string to compare
401
400
:param str2: string to compare
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))
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))
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/', '')
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')
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')
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')
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')
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'
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'
491
class TestCompiledCmpByDirs(TestCmpByDirs):
492
"""Test the pyrex implementation of cmp_by_dirs"""
496
494
_test_needs_features = [compiled_dirstate_helpers_feature]
498
def get_lt_by_dirs(self):
499
from ..bzr._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
496
def get_cmp_by_dirs(self):
497
from brzlib._dirstate_helpers_pyx import cmp_by_dirs
501
class TestCmpPathByDirblock(tests.TestCase):
502
"""Test an implementation of _cmp_path_by_dirblock()
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.
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
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
518
def assertLtPathByDirblock(self, paths):
516
def assertCmpPathByDirblock(self, paths):
519
517
"""Compare all paths and make sure they evaluate to the correct order.
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
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)
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)
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))
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))
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))
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'])
547
555
def test_tricky_paths(self):
548
self.assertLtPathByDirblock([
556
self.assertCmpPathByDirblock([
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'
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'
567
575
# Contents of 'a/b'
569
577
# Contents of 'a-a',
571
579
# Contents of 'a=a',
573
581
# Contents of 'b',
576
self.assertLtPathByDirblock([
578
b'', b'a', b'a-a', b'a-z', b'a=a', b'a=z',
584
self.assertCmpPathByDirblock([
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',
582
b'a/z', b'a/z-a', b'a/z-z',
588
'a/a', 'a/a-a', 'a/a-z',
590
'a/z', 'a/z-a', 'a/z-z',
584
592
# content of 'a/a/'
586
594
# content of 'a/a-a'
588
596
# content of 'a/a-z'
590
598
# content of 'a/a=a'
592
600
# content of 'a/a=z'
594
602
# content of 'a/z/'
596
604
# content of 'a-a'
598
606
# content of 'a-z'
600
608
# content of 'a=a'
602
610
# content of 'a=z'
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')
615
623
def test_nonascii(self):
616
self.assertLtPathByDirblock([
624
self.assertCmpPathByDirblock([
618
b'', b'a', b'\xc2\xb5', b'\xc3\xa5',
626
'', 'a', '\xc2\xb5', '\xc3\xa5',
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',
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"""
637
645
_test_needs_features = [compiled_dirstate_helpers_feature]
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
644
652
class TestMemRChr(tests.TestCase):
647
655
_test_needs_features = [compiled_dirstate_helpers_feature]
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))
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')
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')
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')
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')
687
695
class TestReadDirblocks(test_dirstate.TestCaseWithDirState):
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
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)
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
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)
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
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)
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
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)
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
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)
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
791
from breezy.bzr.dirstate import update_entry
799
from brzlib.dirstate import update_entry
792
800
self.assertIs(update_entry, dirstate.update_entry)
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)
799
from breezy.bzr.dirstate import ProcessEntryPython
807
from brzlib.dirstate import ProcessEntryPython
800
808
self.assertIs(ProcessEntryPython, dirstate._process_entry)
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)],
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)],
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)],
1010
1018
def do_update_entry(self, state, entry, abspath):