1
# Copyright (C) 2007 Canonical Ltd
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
# GNU General Public License for more details.
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
"""Tests for the compiled dirstate helpers."""
26
from bzrlib.tests import test_dirstate
29
class _CompiledDirstateHelpersFeature(tests.Feature):
32
import bzrlib._dirstate_helpers_c
37
def feature_name(self):
38
return 'bzrlib._dirstate_helpers_c'
40
CompiledDirstateHelpersFeature = _CompiledDirstateHelpersFeature()
43
class TestBisectPathMixin(object):
44
"""Test that _bisect_path_*() returns the expected values.
46
_bisect_path_* is intended to work like bisect.bisect_*() except it
47
knows it is working on paths that are sorted by ('path', 'to', 'foo')
48
chunks rather than by raw 'path/to/foo'.
50
Test Cases should inherit from this and override ``get_bisect_path`` return
51
their implementation, and ``get_bisect`` to return the matching
52
bisect.bisect_* function.
55
def get_bisect_path(self):
56
"""Return an implementation of _bisect_path_*"""
57
raise NotImplementedError
60
"""Return a version of bisect.bisect_*.
62
Also, for the 'exists' check, return the offset to the real values.
63
For example bisect_left returns the index of an entry, while
64
bisect_right returns the index *after* an entry
66
:return: (bisect_func, offset)
68
raise NotImplementedError
70
def assertBisect(self, paths, split_paths, path, exists=True):
71
"""Assert that bisect_split works like bisect_left on the split paths.
73
:param paths: A list of path names
74
:param split_paths: A list of path names that are already split up by directory
75
('path/to/foo' => ('path', 'to', 'foo'))
76
:param path: The path we are indexing.
77
:param exists: The path should be present, so make sure the
78
final location actually points to the right value.
80
All other arguments will be passed along.
82
bisect_path = self.get_bisect_path()
83
self.assertIsInstance(paths, list)
84
bisect_path_idx = bisect_path(paths, path)
85
split_path = self.split_for_dirblocks([path])[0]
86
bisect_func, offset = self.get_bisect()
87
bisect_split_idx = bisect_func(split_paths, split_path)
88
self.assertEqual(bisect_split_idx, bisect_path_idx,
89
'%s disagreed. %s != %s'
91
% (bisect_path.__name__,
92
bisect_split_idx, bisect_path_idx, path)
95
self.assertEqual(path, paths[bisect_path_idx+offset])
97
def split_for_dirblocks(self, paths):
100
dirname, basename = os.path.split(path)
101
dir_split_paths.append((dirname.split('/'), basename))
102
dir_split_paths.sort()
103
return dir_split_paths
105
def test_simple(self):
106
"""In the simple case it works just like bisect_left"""
107
paths = ['', 'a', 'b', 'c', 'd']
108
split_paths = self.split_for_dirblocks(paths)
110
self.assertBisect(paths, split_paths, path, exists=True)
111
self.assertBisect(paths, split_paths, '_', exists=False)
112
self.assertBisect(paths, split_paths, 'aa', exists=False)
113
self.assertBisect(paths, split_paths, 'bb', exists=False)
114
self.assertBisect(paths, split_paths, 'cc', exists=False)
115
self.assertBisect(paths, split_paths, 'dd', exists=False)
116
self.assertBisect(paths, split_paths, 'a/a', exists=False)
117
self.assertBisect(paths, split_paths, 'b/b', exists=False)
118
self.assertBisect(paths, split_paths, 'c/c', exists=False)
119
self.assertBisect(paths, split_paths, 'd/d', exists=False)
121
def test_involved(self):
122
"""This is where bisect_path_* diverges slightly."""
123
# This is the list of paths and their contents
151
# This is the exact order that is stored by dirstate
152
# All children in a directory are mentioned before an children of
153
# children are mentioned.
154
# So all the root-directory paths, then all the
155
# first sub directory, etc.
156
paths = [# content of '/'
157
'', 'a', 'a-a', 'a-z', 'a=a', 'a=z',
159
'a/a', 'a/a-a', 'a/a-z',
161
'a/z', 'a/z-a', 'a/z-z',
184
split_paths = self.split_for_dirblocks(paths)
186
for dir_parts, basename in split_paths:
187
if dir_parts == ['']:
188
sorted_paths.append(basename)
190
sorted_paths.append('/'.join(dir_parts + [basename]))
192
self.assertEqual(sorted_paths, paths)
195
self.assertBisect(paths, split_paths, path, exists=True)
198
class TestBisectPathLeft(tests.TestCase, TestBisectPathMixin):
199
"""Run all Bisect Path tests against _bisect_path_left_py."""
201
def get_bisect_path(self):
202
from bzrlib._dirstate_helpers_py import _bisect_path_left_py
203
return _bisect_path_left_py
205
def get_bisect(self):
206
return bisect.bisect_left, 0
209
class TestCompiledBisectPathLeft(TestBisectPathLeft):
210
"""Run all Bisect Path tests against _bisect_path_right_c"""
212
_test_needs_features = [CompiledDirstateHelpersFeature]
214
def get_bisect_path(self):
215
from bzrlib._dirstate_helpers_c import _bisect_path_left_c
216
return _bisect_path_left_c
219
class TestBisectPathRight(tests.TestCase, TestBisectPathMixin):
220
"""Run all Bisect Path tests against _bisect_path_right_py"""
222
def get_bisect_path(self):
223
from bzrlib._dirstate_helpers_py import _bisect_path_right_py
224
return _bisect_path_right_py
226
def get_bisect(self):
227
return bisect.bisect_right, -1
230
class TestCompiledBisectPathRight(TestBisectPathRight):
231
"""Run all Bisect Path tests against _bisect_path_right_c"""
233
_test_needs_features = [CompiledDirstateHelpersFeature]
235
def get_bisect_path(self):
236
from bzrlib._dirstate_helpers_c import _bisect_path_right_c
237
return _bisect_path_right_c
240
class TestBisectDirblock(tests.TestCase):
241
"""Test that bisect_dirblock() returns the expected values.
243
bisect_dirblock is intended to work like bisect.bisect_left() except it
244
knows it is working on dirblocks and that dirblocks are sorted by ('path',
245
'to', 'foo') chunks rather than by raw 'path/to/foo'.
247
This test is parameterized by calling get_bisect_dirblock(). Child test
248
cases can override this function to test against a different
252
def get_bisect_dirblock(self):
253
"""Return an implementation of bisect_dirblock"""
254
from bzrlib._dirstate_helpers_py import bisect_dirblock_py
255
return bisect_dirblock_py
257
def assertBisect(self, dirblocks, split_dirblocks, path, *args, **kwargs):
258
"""Assert that bisect_split works like bisect_left on the split paths.
260
:param dirblocks: A list of (path, [info]) pairs.
261
:param split_dirblocks: A list of ((split, path), [info]) pairs.
262
:param path: The path we are indexing.
264
All other arguments will be passed along.
266
bisect_dirblock = self.get_bisect_dirblock()
267
self.assertIsInstance(dirblocks, list)
268
bisect_split_idx = bisect_dirblock(dirblocks, path, *args, **kwargs)
269
split_dirblock = (path.split('/'), [])
270
bisect_left_idx = bisect.bisect_left(split_dirblocks, split_dirblock,
272
self.assertEqual(bisect_left_idx, bisect_split_idx,
273
'bisect_split disagreed. %s != %s'
275
% (bisect_left_idx, bisect_split_idx, path)
278
def paths_to_dirblocks(self, paths):
279
"""Convert a list of paths into dirblock form.
281
Also, ensure that the paths are in proper sorted order.
283
dirblocks = [(path, []) for path in paths]
284
split_dirblocks = [(path.split('/'), []) for path in paths]
285
self.assertEqual(sorted(split_dirblocks), split_dirblocks)
286
return dirblocks, split_dirblocks
288
def test_simple(self):
289
"""In the simple case it works just like bisect_left"""
290
paths = ['', 'a', 'b', 'c', 'd']
291
dirblocks, split_dirblocks = self.paths_to_dirblocks(paths)
293
self.assertBisect(dirblocks, split_dirblocks, path)
294
self.assertBisect(dirblocks, split_dirblocks, '_')
295
self.assertBisect(dirblocks, split_dirblocks, 'aa')
296
self.assertBisect(dirblocks, split_dirblocks, 'bb')
297
self.assertBisect(dirblocks, split_dirblocks, 'cc')
298
self.assertBisect(dirblocks, split_dirblocks, 'dd')
299
self.assertBisect(dirblocks, split_dirblocks, 'a/a')
300
self.assertBisect(dirblocks, split_dirblocks, 'b/b')
301
self.assertBisect(dirblocks, split_dirblocks, 'c/c')
302
self.assertBisect(dirblocks, split_dirblocks, 'd/d')
304
def test_involved(self):
305
"""This is where bisect_left diverges slightly."""
307
'a/a', 'a/a/a', 'a/a/z', 'a/a-a', 'a/a-z',
308
'a/z', 'a/z/a', 'a/z/z', 'a/z-a', 'a/z-z',
310
'z', 'z/a/a', 'z/a/z', 'z/a-a', 'z/a-z',
311
'z/z', 'z/z/a', 'z/z/z', 'z/z-a', 'z/z-z',
314
dirblocks, split_dirblocks = self.paths_to_dirblocks(paths)
316
self.assertBisect(dirblocks, split_dirblocks, path)
318
def test_involved_cached(self):
319
"""This is where bisect_left diverges slightly."""
321
'a/a', 'a/a/a', 'a/a/z', 'a/a-a', 'a/a-z',
322
'a/z', 'a/z/a', 'a/z/z', 'a/z-a', 'a/z-z',
324
'z', 'z/a/a', 'z/a/z', 'z/a-a', 'z/a-z',
325
'z/z', 'z/z/a', 'z/z/z', 'z/z-a', 'z/z-z',
329
dirblocks, split_dirblocks = self.paths_to_dirblocks(paths)
331
self.assertBisect(dirblocks, split_dirblocks, path, cache=cache)
334
class TestCompiledBisectDirblock(TestBisectDirblock):
335
"""Test that bisect_dirblock() returns the expected values.
337
bisect_dirblock is intended to work like bisect.bisect_left() except it
338
knows it is working on dirblocks and that dirblocks are sorted by ('path',
339
'to', 'foo') chunks rather than by raw 'path/to/foo'.
341
This runs all the normal tests that TestBisectDirblock did, but uses the
345
_test_needs_features = [CompiledDirstateHelpersFeature]
347
def get_bisect_dirblock(self):
348
from bzrlib._dirstate_helpers_c import bisect_dirblock_c
349
return bisect_dirblock_c
352
class TestCmpByDirs(tests.TestCase):
353
"""Test an implementation of cmp_by_dirs()
355
cmp_by_dirs() compares 2 paths by their directory sections, rather than as
358
Child test cases can override ``get_cmp_by_dirs`` to test a specific
362
def get_cmp_by_dirs(self):
363
"""Get a specific implementation of cmp_by_dirs."""
364
from bzrlib._dirstate_helpers_py import cmp_by_dirs_py
365
return cmp_by_dirs_py
367
def assertCmpByDirs(self, expected, str1, str2):
368
"""Compare the two strings, in both directions.
370
:param expected: The expected comparison value. -1 means str1 comes
371
first, 0 means they are equal, 1 means str2 comes first
372
:param str1: string to compare
373
:param str2: string to compare
375
cmp_by_dirs = self.get_cmp_by_dirs()
377
self.assertEqual(str1, str2)
378
self.assertEqual(0, cmp_by_dirs(str1, str2))
379
self.assertEqual(0, cmp_by_dirs(str2, str1))
381
self.assertPositive(cmp_by_dirs(str1, str2))
382
self.assertNegative(cmp_by_dirs(str2, str1))
384
self.assertNegative(cmp_by_dirs(str1, str2))
385
self.assertPositive(cmp_by_dirs(str2, str1))
387
def test_cmp_empty(self):
388
"""Compare against the empty string."""
389
self.assertCmpByDirs(0, '', '')
390
self.assertCmpByDirs(1, 'a', '')
391
self.assertCmpByDirs(1, 'ab', '')
392
self.assertCmpByDirs(1, 'abc', '')
393
self.assertCmpByDirs(1, 'abcd', '')
394
self.assertCmpByDirs(1, 'abcde', '')
395
self.assertCmpByDirs(1, 'abcdef', '')
396
self.assertCmpByDirs(1, 'abcdefg', '')
397
self.assertCmpByDirs(1, 'abcdefgh', '')
398
self.assertCmpByDirs(1, 'abcdefghi', '')
399
self.assertCmpByDirs(1, 'test/ing/a/path/', '')
401
def test_cmp_same_str(self):
402
"""Compare the same string"""
403
self.assertCmpByDirs(0, 'a', 'a')
404
self.assertCmpByDirs(0, 'ab', 'ab')
405
self.assertCmpByDirs(0, 'abc', 'abc')
406
self.assertCmpByDirs(0, 'abcd', 'abcd')
407
self.assertCmpByDirs(0, 'abcde', 'abcde')
408
self.assertCmpByDirs(0, 'abcdef', 'abcdef')
409
self.assertCmpByDirs(0, 'abcdefg', 'abcdefg')
410
self.assertCmpByDirs(0, 'abcdefgh', 'abcdefgh')
411
self.assertCmpByDirs(0, 'abcdefghi', 'abcdefghi')
412
self.assertCmpByDirs(0, 'testing a long string', 'testing a long string')
413
self.assertCmpByDirs(0, 'x'*10000, 'x'*10000)
414
self.assertCmpByDirs(0, 'a/b', 'a/b')
415
self.assertCmpByDirs(0, 'a/b/c', 'a/b/c')
416
self.assertCmpByDirs(0, 'a/b/c/d', 'a/b/c/d')
417
self.assertCmpByDirs(0, 'a/b/c/d/e', 'a/b/c/d/e')
419
def test_simple_paths(self):
420
"""Compare strings that act like normal string comparison"""
421
self.assertCmpByDirs(-1, 'a', 'b')
422
self.assertCmpByDirs(-1, 'aa', 'ab')
423
self.assertCmpByDirs(-1, 'ab', 'bb')
424
self.assertCmpByDirs(-1, 'aaa', 'aab')
425
self.assertCmpByDirs(-1, 'aab', 'abb')
426
self.assertCmpByDirs(-1, 'abb', 'bbb')
427
self.assertCmpByDirs(-1, 'aaaa', 'aaab')
428
self.assertCmpByDirs(-1, 'aaab', 'aabb')
429
self.assertCmpByDirs(-1, 'aabb', 'abbb')
430
self.assertCmpByDirs(-1, 'abbb', 'bbbb')
431
self.assertCmpByDirs(-1, 'aaaaa', 'aaaab')
432
self.assertCmpByDirs(-1, 'a/a', 'a/b')
433
self.assertCmpByDirs(-1, 'a/b', 'b/b')
434
self.assertCmpByDirs(-1, 'a/a/a', 'a/a/b')
435
self.assertCmpByDirs(-1, 'a/a/b', 'a/b/b')
436
self.assertCmpByDirs(-1, 'a/b/b', 'b/b/b')
437
self.assertCmpByDirs(-1, 'a/a/a/a', 'a/a/a/b')
438
self.assertCmpByDirs(-1, 'a/a/a/b', 'a/a/b/b')
439
self.assertCmpByDirs(-1, 'a/a/b/b', 'a/b/b/b')
440
self.assertCmpByDirs(-1, 'a/b/b/b', 'b/b/b/b')
441
self.assertCmpByDirs(-1, 'a/a/a/a/a', 'a/a/a/a/b')
443
def test_tricky_paths(self):
444
self.assertCmpByDirs(1, 'ab/cd/ef', 'ab/cc/ef')
445
self.assertCmpByDirs(1, 'ab/cd/ef', 'ab/c/ef')
446
self.assertCmpByDirs(-1, 'ab/cd/ef', 'ab/cd-ef')
447
self.assertCmpByDirs(-1, 'ab/cd', 'ab/cd-')
448
self.assertCmpByDirs(-1, 'ab/cd', 'ab-cd')
450
def test_cmp_unicode_not_allowed(self):
451
cmp_by_dirs = self.get_cmp_by_dirs()
452
self.assertRaises(TypeError, cmp_by_dirs, u'Unicode', 'str')
453
self.assertRaises(TypeError, cmp_by_dirs, 'str', u'Unicode')
454
self.assertRaises(TypeError, cmp_by_dirs, u'Unicode', u'Unicode')
456
def test_cmp_non_ascii(self):
457
self.assertCmpByDirs(-1, '\xc2\xb5', '\xc3\xa5') # u'\xb5', u'\xe5'
458
self.assertCmpByDirs(-1, 'a', '\xc3\xa5') # u'a', u'\xe5'
459
self.assertCmpByDirs(-1, 'b', '\xc2\xb5') # u'b', u'\xb5'
460
self.assertCmpByDirs(-1, 'a/b', 'a/\xc3\xa5') # u'a/b', u'a/\xe5'
461
self.assertCmpByDirs(-1, 'b/a', 'b/\xc2\xb5') # u'b/a', u'b/\xb5'
464
class TestCompiledCmpByDirs(TestCmpByDirs):
465
"""Test the pyrex implementation of cmp_by_dirs"""
467
_test_needs_features = [CompiledDirstateHelpersFeature]
469
def get_cmp_by_dirs(self):
470
from bzrlib._dirstate_helpers_c import cmp_by_dirs_c
474
class TestCmpPathByDirblock(tests.TestCase):
475
"""Test an implementation of _cmp_path_by_dirblock()
477
_cmp_path_by_dirblock() compares two paths using the sort order used by
478
DirState. All paths in the same directory are sorted together.
480
Child test cases can override ``get_cmp_path_by_dirblock`` to test a specific
484
def get_cmp_path_by_dirblock(self):
485
"""Get a specific implementation of _cmp_path_by_dirblock."""
486
from bzrlib._dirstate_helpers_py import _cmp_path_by_dirblock_py
487
return _cmp_path_by_dirblock_py
489
def assertCmpPathByDirblock(self, paths):
490
"""Compare all paths and make sure they evaluate to the correct order.
492
This does N^2 comparisons. It is assumed that ``paths`` is properly
495
:param paths: a sorted list of paths to compare
497
# First, make sure the paths being passed in are correct
499
dirname, basename = os.path.split(p)
500
return dirname.split('/'), basename
501
self.assertEqual(sorted(paths, key=_key), paths)
503
cmp_path_by_dirblock = self.get_cmp_path_by_dirblock()
504
for idx1, path1 in enumerate(paths):
505
for idx2, path2 in enumerate(paths):
506
cmp_val = cmp_path_by_dirblock(path1, path2)
508
self.assertTrue(cmp_val < 0,
509
'%s did not state that %r came before %r, cmp=%s'
510
% (cmp_path_by_dirblock.__name__,
511
path1, path2, cmp_val))
513
self.assertTrue(cmp_val > 0,
514
'%s did not state that %r came after %r, cmp=%s'
515
% (cmp_path_by_dirblock.__name__,
516
path1, path2, cmp_val))
518
self.assertTrue(cmp_val == 0,
519
'%s did not state that %r == %r, cmp=%s'
520
% (cmp_path_by_dirblock.__name__,
521
path1, path2, cmp_val))
523
def test_cmp_simple_paths(self):
524
"""Compare against the empty string."""
525
self.assertCmpPathByDirblock(['', 'a', 'ab', 'abc', 'a/b/c', 'b/d/e'])
526
self.assertCmpPathByDirblock(['kl', 'ab/cd', 'ab/ef', 'gh/ij'])
528
def test_tricky_paths(self):
529
self.assertCmpPathByDirblock([
531
'', 'a', 'a-a', 'a=a', 'b',
533
'a/a', 'a/a-a', 'a/a=a', 'a/b',
535
'a/a/a', 'a/a/a-a', 'a/a/a=a',
536
# Contents of 'a/a/a'
537
'a/a/a/a', 'a/a/a/b',
538
# Contents of 'a/a/a-a',
539
'a/a/a-a/a', 'a/a/a-a/b',
540
# Contents of 'a/a/a=a',
541
'a/a/a=a/a', 'a/a/a=a/b',
542
# Contents of 'a/a-a'
544
# Contents of 'a/a-a/a'
545
'a/a-a/a/a', 'a/a-a/a/b',
546
# Contents of 'a/a=a'
557
self.assertCmpPathByDirblock([
559
'', 'a', 'a-a', 'a-z', 'a=a', 'a=z',
561
'a/a', 'a/a-a', 'a/a-z',
563
'a/z', 'a/z-a', 'a/z-z',
587
def test_unicode_not_allowed(self):
588
cmp_path_by_dirblock = self.get_cmp_path_by_dirblock()
589
self.assertRaises(TypeError, cmp_path_by_dirblock, u'Uni', 'str')
590
self.assertRaises(TypeError, cmp_path_by_dirblock, 'str', u'Uni')
591
self.assertRaises(TypeError, cmp_path_by_dirblock, u'Uni', u'Uni')
592
self.assertRaises(TypeError, cmp_path_by_dirblock, u'x/Uni', 'x/str')
593
self.assertRaises(TypeError, cmp_path_by_dirblock, 'x/str', u'x/Uni')
594
self.assertRaises(TypeError, cmp_path_by_dirblock, u'x/Uni', u'x/Uni')
596
def test_nonascii(self):
597
self.assertCmpPathByDirblock([
599
'', 'a', '\xc2\xb5', '\xc3\xa5',
601
'a/a', 'a/\xc2\xb5', 'a/\xc3\xa5',
603
'a/a/a', 'a/a/\xc2\xb5', 'a/a/\xc3\xa5',
604
# content of 'a/\xc2\xb5'
605
'a/\xc2\xb5/a', 'a/\xc2\xb5/\xc2\xb5', 'a/\xc2\xb5/\xc3\xa5',
606
# content of 'a/\xc3\xa5'
607
'a/\xc3\xa5/a', 'a/\xc3\xa5/\xc2\xb5', 'a/\xc3\xa5/\xc3\xa5',
608
# content of '\xc2\xb5'
609
'\xc2\xb5/a', '\xc2\xb5/\xc2\xb5', '\xc2\xb5/\xc3\xa5',
610
# content of '\xc2\xe5'
611
'\xc3\xa5/a', '\xc3\xa5/\xc2\xb5', '\xc3\xa5/\xc3\xa5',
615
class TestCompiledCmpPathByDirblock(TestCmpPathByDirblock):
616
"""Test the pyrex implementation of _cmp_path_by_dirblock"""
618
_test_needs_features = [CompiledDirstateHelpersFeature]
620
def get_cmp_by_dirs(self):
621
from bzrlib._dirstate_helpers_c import _cmp_path_by_dirblock_c
622
return _cmp_path_by_dirblock_c
625
class TestMemRChr(tests.TestCase):
626
"""Test memrchr functionality"""
628
_test_needs_features = [CompiledDirstateHelpersFeature]
630
def assertMemRChr(self, expected, s, c):
631
from bzrlib._dirstate_helpers_c import _py_memrchr
632
self.assertEqual(expected, _py_memrchr(s, c))
634
def test_missing(self):
635
self.assertMemRChr(None, '', 'a')
636
self.assertMemRChr(None, '', 'c')
637
self.assertMemRChr(None, 'abcdefghijklm', 'q')
638
self.assertMemRChr(None, 'aaaaaaaaaaaaaaaaaaaaaaa', 'b')
640
def test_single_entry(self):
641
self.assertMemRChr(0, 'abcdefghijklm', 'a')
642
self.assertMemRChr(1, 'abcdefghijklm', 'b')
643
self.assertMemRChr(2, 'abcdefghijklm', 'c')
644
self.assertMemRChr(10, 'abcdefghijklm', 'k')
645
self.assertMemRChr(11, 'abcdefghijklm', 'l')
646
self.assertMemRChr(12, 'abcdefghijklm', 'm')
648
def test_multiple(self):
649
self.assertMemRChr(10, 'abcdefjklmabcdefghijklm', 'a')
650
self.assertMemRChr(11, 'abcdefjklmabcdefghijklm', 'b')
651
self.assertMemRChr(12, 'abcdefjklmabcdefghijklm', 'c')
652
self.assertMemRChr(20, 'abcdefjklmabcdefghijklm', 'k')
653
self.assertMemRChr(21, 'abcdefjklmabcdefghijklm', 'l')
654
self.assertMemRChr(22, 'abcdefjklmabcdefghijklm', 'm')
655
self.assertMemRChr(22, 'aaaaaaaaaaaaaaaaaaaaaaa', 'a')
657
def test_with_nulls(self):
658
self.assertMemRChr(10, 'abc\0\0\0jklmabc\0\0\0ghijklm', 'a')
659
self.assertMemRChr(11, 'abc\0\0\0jklmabc\0\0\0ghijklm', 'b')
660
self.assertMemRChr(12, 'abc\0\0\0jklmabc\0\0\0ghijklm', 'c')
661
self.assertMemRChr(20, 'abc\0\0\0jklmabc\0\0\0ghijklm', 'k')
662
self.assertMemRChr(21, 'abc\0\0\0jklmabc\0\0\0ghijklm', 'l')
663
self.assertMemRChr(22, 'abc\0\0\0jklmabc\0\0\0ghijklm', 'm')
664
self.assertMemRChr(22, 'aaa\0\0\0aaaaaaa\0\0\0aaaaaaa', 'a')
665
self.assertMemRChr(9, '\0\0\0\0\0\0\0\0\0\0', '\0')
668
class TestReadDirblocks(test_dirstate.TestCaseWithDirState):
669
"""Test an implementation of _read_dirblocks()
671
_read_dirblocks() reads in all of the dirblock information from the disk
674
Child test cases can override ``get_read_dirblocks`` to test a specific
678
def get_read_dirblocks(self):
679
from bzrlib._dirstate_helpers_py import _read_dirblocks_py
680
return _read_dirblocks_py
682
def test_smoketest(self):
683
"""Make sure that we can create and read back a simple file."""
684
tree, state, expected = self.create_basic_dirstate()
686
state._read_header_if_needed()
687
self.assertEqual(dirstate.DirState.NOT_IN_MEMORY,
688
state._dirblock_state)
689
read_dirblocks = self.get_read_dirblocks()
690
read_dirblocks(state)
691
self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
692
state._dirblock_state)
695
class TestCompiledReadDirblocks(TestReadDirblocks):
696
"""Test the pyrex implementation of _read_dirblocks"""
698
_test_needs_features = [CompiledDirstateHelpersFeature]
700
def get_read_dirblocks(self):
701
from bzrlib._dirstate_helpers_c import _read_dirblocks_c
702
return _read_dirblocks_c
705
class TestUsingCompiledIfAvailable(tests.TestCase):
706
"""Check that any compiled functions that are available are the default.
708
It is possible to have typos, etc in the import line, such that
709
_dirstate_helpers_c is actually available, but the compiled functions are
713
def test_bisect_dirblock(self):
714
if CompiledDirstateHelpersFeature.available():
715
from bzrlib._dirstate_helpers_c import bisect_dirblock_c
716
self.assertIs(bisect_dirblock_c, dirstate.bisect_dirblock)
718
from bzrlib._dirstate_helpers_py import bisect_dirblock_py
719
self.assertIs(bisect_dirblock_py, dirstate.bisect_dirblock)
721
def test__bisect_path_left(self):
722
if CompiledDirstateHelpersFeature.available():
723
from bzrlib._dirstate_helpers_c import _bisect_path_left_c
724
self.assertIs(_bisect_path_left_c, dirstate._bisect_path_left)
726
from bzrlib._dirstate_helpers_py import _bisect_path_left_py
727
self.assertIs(_bisect_path_left_py, dirstate._bisect_path_left)
729
def test__bisect_path_right(self):
730
if CompiledDirstateHelpersFeature.available():
731
from bzrlib._dirstate_helpers_c import _bisect_path_right_c
732
self.assertIs(_bisect_path_right_c, dirstate._bisect_path_right)
734
from bzrlib._dirstate_helpers_py import _bisect_path_right_py
735
self.assertIs(_bisect_path_right_py, dirstate._bisect_path_right)
737
def test_cmp_by_dirs(self):
738
if CompiledDirstateHelpersFeature.available():
739
from bzrlib._dirstate_helpers_c import cmp_by_dirs_c
740
self.assertIs(cmp_by_dirs_c, dirstate.cmp_by_dirs)
742
from bzrlib._dirstate_helpers_py import cmp_by_dirs_py
743
self.assertIs(cmp_by_dirs_py, dirstate.cmp_by_dirs)
745
def test__read_dirblocks(self):
746
if CompiledDirstateHelpersFeature.available():
747
from bzrlib._dirstate_helpers_c import _read_dirblocks_c
748
self.assertIs(_read_dirblocks_c, dirstate._read_dirblocks)
750
from bzrlib._dirstate_helpers_py import _read_dirblocks_py
751
self.assertIs(_read_dirblocks_py, dirstate._read_dirblocks)