23
23
from bzrlib import (
28
29
from bzrlib.tests import (
31
from bzrlib.tests import test_dirstate
34
class _CompiledDirstateHelpersFeature(tests.Feature):
37
import bzrlib._dirstate_helpers_c
42
def feature_name(self):
43
return 'bzrlib._dirstate_helpers_c'
45
CompiledDirstateHelpersFeature = _CompiledDirstateHelpersFeature()
35
from bzrlib import _dirstate_helpers_pyx
36
has_dirstate_helpers_pyx = True
38
has_dirstate_helpers_pyx = False
41
compiled_dirstate_helpers_feature = tests.ModuleAvailableFeature(
42
'bzrlib._dirstate_helpers_pyx')
45
def load_tests(basic_tests, module, loader):
46
# FIXME: we should also parametrize against SHA1Provider !
47
suite = loader.suiteClass()
48
remaining_tests = basic_tests
50
dir_reader_scenarios = test_osutils.dir_reader_scenarios()
52
ue_scenarios = [('dirstate_Python',
53
{'update_entry': dirstate.py_update_entry})]
54
if compiled_dirstate_helpers_feature.available():
55
update_entry = compiled_dirstate_helpers_feature.module.update_entry
56
pyrex_scenario = ('dirstate_Pyrex', {'update_entry': update_entry})
57
ue_scenarios.append(pyrex_scenario)
58
process_entry_tests, remaining_tests = tests.split_suite_by_condition(
59
remaining_tests, tests.condition_isinstance(TestUpdateEntry))
60
tests.multiply_tests(process_entry_tests,
61
tests.multiply_scenarios(dir_reader_scenarios,
65
pe_scenarios = [('dirstate_Python',
66
{'_process_entry': dirstate.ProcessEntryPython})]
67
if compiled_dirstate_helpers_feature.available():
68
process_entry = compiled_dirstate_helpers_feature.module.ProcessEntryC
69
pyrex_scenario = ('dirstate_Pyrex', {'_process_entry': process_entry})
70
pe_scenarios.append(pyrex_scenario)
71
process_entry_tests, remaining_tests = tests.split_suite_by_condition(
72
remaining_tests, tests.condition_isinstance(TestProcessEntry))
73
tests.multiply_tests(process_entry_tests,
74
tests.multiply_scenarios(dir_reader_scenarios,
78
dir_reader_tests, remaining_tests = tests.split_suite_by_condition(
79
remaining_tests, tests.condition_isinstance(
80
test_dirstate.TestCaseWithDirState))
81
tests.multiply_tests(dir_reader_tests, dir_reader_scenarios, suite)
82
suite.addTest(remaining_tests)
48
87
class TestBisectPathMixin(object):
203
242
class TestBisectPathLeft(tests.TestCase, TestBisectPathMixin):
204
"""Run all Bisect Path tests against _bisect_path_left_py."""
243
"""Run all Bisect Path tests against _bisect_path_left."""
206
245
def get_bisect_path(self):
207
from bzrlib._dirstate_helpers_py import _bisect_path_left_py
208
return _bisect_path_left_py
246
from bzrlib._dirstate_helpers_py import _bisect_path_left
247
return _bisect_path_left
210
249
def get_bisect(self):
211
250
return bisect.bisect_left, 0
214
253
class TestCompiledBisectPathLeft(TestBisectPathLeft):
215
"""Run all Bisect Path tests against _bisect_path_right_c"""
254
"""Run all Bisect Path tests against _bisect_path_lect"""
217
_test_needs_features = [CompiledDirstateHelpersFeature]
256
_test_needs_features = [compiled_dirstate_helpers_feature]
219
258
def get_bisect_path(self):
220
from bzrlib._dirstate_helpers_c import _bisect_path_left_c
221
return _bisect_path_left_c
259
from bzrlib._dirstate_helpers_pyx import _bisect_path_left
260
return _bisect_path_left
224
263
class TestBisectPathRight(tests.TestCase, TestBisectPathMixin):
225
"""Run all Bisect Path tests against _bisect_path_right_py"""
264
"""Run all Bisect Path tests against _bisect_path_right"""
227
266
def get_bisect_path(self):
228
from bzrlib._dirstate_helpers_py import _bisect_path_right_py
229
return _bisect_path_right_py
267
from bzrlib._dirstate_helpers_py import _bisect_path_right
268
return _bisect_path_right
231
270
def get_bisect(self):
232
271
return bisect.bisect_right, -1
235
274
class TestCompiledBisectPathRight(TestBisectPathRight):
236
"""Run all Bisect Path tests against _bisect_path_right_c"""
275
"""Run all Bisect Path tests against _bisect_path_right"""
238
_test_needs_features = [CompiledDirstateHelpersFeature]
277
_test_needs_features = [compiled_dirstate_helpers_feature]
240
279
def get_bisect_path(self):
241
from bzrlib._dirstate_helpers_c import _bisect_path_right_c
242
return _bisect_path_right_c
280
from bzrlib._dirstate_helpers_pyx import _bisect_path_right
281
return _bisect_path_right
245
284
class TestBisectDirblock(tests.TestCase):
620
659
class TestCompiledCmpPathByDirblock(TestCmpPathByDirblock):
621
660
"""Test the pyrex implementation of _cmp_path_by_dirblock"""
623
_test_needs_features = [CompiledDirstateHelpersFeature]
662
_test_needs_features = [compiled_dirstate_helpers_feature]
625
664
def get_cmp_by_dirs(self):
626
from bzrlib._dirstate_helpers_c import _cmp_path_by_dirblock_c
627
return _cmp_path_by_dirblock_c
665
from bzrlib._dirstate_helpers_pyx import _cmp_path_by_dirblock
666
return _cmp_path_by_dirblock
630
669
class TestMemRChr(tests.TestCase):
631
670
"""Test memrchr functionality"""
633
_test_needs_features = [CompiledDirstateHelpersFeature]
672
_test_needs_features = [compiled_dirstate_helpers_feature]
635
674
def assertMemRChr(self, expected, s, c):
636
from bzrlib._dirstate_helpers_c import _py_memrchr
675
from bzrlib._dirstate_helpers_pyx import _py_memrchr
637
676
self.assertEqual(expected, _py_memrchr(s, c))
639
678
def test_missing(self):
714
757
class TestCompiledReadDirblocks(TestReadDirblocks):
715
758
"""Test the pyrex implementation of _read_dirblocks"""
717
_test_needs_features = [CompiledDirstateHelpersFeature]
760
_test_needs_features = [compiled_dirstate_helpers_feature]
719
762
def get_read_dirblocks(self):
720
from bzrlib._dirstate_helpers_c import _read_dirblocks_c
721
return _read_dirblocks_c
763
from bzrlib._dirstate_helpers_pyx import _read_dirblocks
764
return _read_dirblocks
724
767
class TestUsingCompiledIfAvailable(tests.TestCase):
725
768
"""Check that any compiled functions that are available are the default.
727
770
It is possible to have typos, etc in the import line, such that
728
_dirstate_helpers_c is actually available, but the compiled functions are
771
_dirstate_helpers_pyx is actually available, but the compiled functions are
732
775
def test_bisect_dirblock(self):
733
if CompiledDirstateHelpersFeature.available():
734
from bzrlib._dirstate_helpers_c import bisect_dirblock_c
735
self.assertIs(bisect_dirblock_c, dirstate.bisect_dirblock)
776
if compiled_dirstate_helpers_feature.available():
777
from bzrlib._dirstate_helpers_pyx import bisect_dirblock
737
from bzrlib._dirstate_helpers_py import bisect_dirblock_py
738
self.assertIs(bisect_dirblock_py, dirstate.bisect_dirblock)
779
from bzrlib._dirstate_helpers_py import bisect_dirblock
780
self.assertIs(bisect_dirblock, dirstate.bisect_dirblock)
740
782
def test__bisect_path_left(self):
741
if CompiledDirstateHelpersFeature.available():
742
from bzrlib._dirstate_helpers_c import _bisect_path_left_c
743
self.assertIs(_bisect_path_left_c, dirstate._bisect_path_left)
783
if compiled_dirstate_helpers_feature.available():
784
from bzrlib._dirstate_helpers_pyx import _bisect_path_left
745
from bzrlib._dirstate_helpers_py import _bisect_path_left_py
746
self.assertIs(_bisect_path_left_py, dirstate._bisect_path_left)
786
from bzrlib._dirstate_helpers_py import _bisect_path_left
787
self.assertIs(_bisect_path_left, dirstate._bisect_path_left)
748
789
def test__bisect_path_right(self):
749
if CompiledDirstateHelpersFeature.available():
750
from bzrlib._dirstate_helpers_c import _bisect_path_right_c
751
self.assertIs(_bisect_path_right_c, dirstate._bisect_path_right)
790
if compiled_dirstate_helpers_feature.available():
791
from bzrlib._dirstate_helpers_pyx import _bisect_path_right
753
from bzrlib._dirstate_helpers_py import _bisect_path_right_py
754
self.assertIs(_bisect_path_right_py, dirstate._bisect_path_right)
793
from bzrlib._dirstate_helpers_py import _bisect_path_right
794
self.assertIs(_bisect_path_right, dirstate._bisect_path_right)
756
796
def test_cmp_by_dirs(self):
757
if CompiledDirstateHelpersFeature.available():
758
from bzrlib._dirstate_helpers_c import cmp_by_dirs_c
759
self.assertIs(cmp_by_dirs_c, dirstate.cmp_by_dirs)
797
if compiled_dirstate_helpers_feature.available():
798
from bzrlib._dirstate_helpers_pyx import cmp_by_dirs
761
from bzrlib._dirstate_helpers_py import cmp_by_dirs_py
762
self.assertIs(cmp_by_dirs_py, dirstate.cmp_by_dirs)
800
from bzrlib._dirstate_helpers_py import cmp_by_dirs
801
self.assertIs(cmp_by_dirs, dirstate.cmp_by_dirs)
764
803
def test__read_dirblocks(self):
765
if CompiledDirstateHelpersFeature.available():
766
from bzrlib._dirstate_helpers_c import _read_dirblocks_c
767
self.assertIs(_read_dirblocks_c, dirstate._read_dirblocks)
804
if compiled_dirstate_helpers_feature.available():
805
from bzrlib._dirstate_helpers_pyx import _read_dirblocks
769
from bzrlib._dirstate_helpers_py import _read_dirblocks_py
770
self.assertIs(_read_dirblocks_py, dirstate._read_dirblocks)
807
from bzrlib._dirstate_helpers_py import _read_dirblocks
808
self.assertIs(_read_dirblocks, dirstate._read_dirblocks)
772
810
def test_update_entry(self):
773
if CompiledDirstateHelpersFeature.available():
774
from bzrlib._dirstate_helpers_c import update_entry
775
self.assertIs(update_entry, dirstate.update_entry)
811
if compiled_dirstate_helpers_feature.available():
812
from bzrlib._dirstate_helpers_pyx import update_entry
777
from bzrlib.dirstate import py_update_entry
778
self.assertIs(py_update_entry, dirstate.py_update_entry)
814
from bzrlib.dirstate import update_entry
815
self.assertIs(update_entry, dirstate.update_entry)
780
817
def test_process_entry(self):
781
if CompiledDirstateHelpersFeature.available():
782
from bzrlib._dirstate_helpers_c import ProcessEntryC
818
if compiled_dirstate_helpers_feature.available():
819
from bzrlib._dirstate_helpers_pyx import ProcessEntryC
783
820
self.assertIs(ProcessEntryC, dirstate._process_entry)
785
822
from bzrlib.dirstate import ProcessEntryPython
789
826
class TestUpdateEntry(test_dirstate.TestCaseWithDirState):
790
827
"""Test the DirState.update_entry functions"""
833
super(TestUpdateEntry, self).setUp()
834
self.overrideAttr(dirstate, 'update_entry', self.update_entry)
792
836
def get_state_with_a(self):
793
837
"""Create a DirState tracking a single object named 'a'"""
794
838
state = test_dirstate.InstrumentedDirState.initialize('dirstate')
795
839
self.addCleanup(state.unlock)
796
840
state.add('a', 'a-id', 'file', None, '')
797
841
entry = state._get_entry(0, path_utf8='a')
798
self.set_update_entry()
799
842
return state, entry
801
def set_update_entry(self):
802
self.update_entry = dirstate.py_update_entry
804
844
def test_observed_sha1_cachable(self):
805
845
state, entry = self.get_state_with_a()
806
846
atime = time.time() - 10
1154
1205
self.assertEqual([('f', '', 14, True, dirstate.DirState.NULLSTAT)],
1157
# Make the disk object look old enough to cache (but it won't cache the sha
1158
# as it is a new file).
1208
# Make the disk object look old enough to cache (but it won't cache the
1209
# sha as it is a new file).
1159
1210
state.adjust_time(+20)
1160
1211
digest = 'b50e5406bb5e153ebbeb20268fcf37c87e1ecfb6'
1161
1212
self.update_entry(state, entry, abspath='a', stat_value=stat_value)
1162
1213
self.assertEqual([('f', '', 14, True, dirstate.DirState.NULLSTAT)],
1166
class TestCompiledUpdateEntry(TestUpdateEntry):
1167
"""Test the pyrex implementation of _read_dirblocks"""
1169
_test_needs_features = [CompiledDirstateHelpersFeature]
1171
def set_update_entry(self):
1172
from bzrlib._dirstate_helpers_c import update_entry
1173
self.update_entry = update_entry
1216
def _prepare_tree(self):
1218
text = 'Hello World\n'
1219
tree = self.make_branch_and_tree('tree')
1220
self.build_tree_contents([('tree/a file', text)])
1221
tree.add('a file', 'a-file-id')
1222
# Note: dirstate does not sha prior to the first commit
1223
# so commit now in order for the test to work
1224
tree.commit('first')
1227
def test_sha1provider_sha1_used(self):
1228
tree, text = self._prepare_tree()
1229
state = dirstate.DirState.from_tree(tree, 'dirstate',
1230
UppercaseSHA1Provider())
1231
self.addCleanup(state.unlock)
1232
expected_sha = osutils.sha_string(text.upper() + "foo")
1233
entry = state._get_entry(0, path_utf8='a file')
1234
state._sha_cutoff_time()
1235
state._cutoff_time += 10
1236
sha1 = self.update_entry(state, entry, 'tree/a file',
1237
os.lstat('tree/a file'))
1238
self.assertEqual(expected_sha, sha1)
1240
def test_sha1provider_stat_and_sha1_used(self):
1241
tree, text = self._prepare_tree()
1243
self.addCleanup(tree.unlock)
1244
state = tree._current_dirstate()
1245
state._sha1_provider = UppercaseSHA1Provider()
1246
# If we used the standard provider, it would look like nothing has
1248
file_ids_changed = [change[0] for change
1249
in tree.iter_changes(tree.basis_tree())]
1250
self.assertEqual(['a-file-id'], file_ids_changed)
1253
class UppercaseSHA1Provider(dirstate.SHA1Provider):
1254
"""A custom SHA1Provider."""
1256
def sha1(self, abspath):
1257
return self.stat_and_sha1(abspath)[1]
1259
def stat_and_sha1(self, abspath):
1260
file_obj = file(abspath, 'rb')
1262
statvalue = os.fstat(file_obj.fileno())
1263
text = ''.join(file_obj.readlines())
1264
sha1 = osutils.sha_string(text.upper() + "foo")
1267
return statvalue, sha1
1270
class TestProcessEntry(test_dirstate.TestCaseWithDirState):
1273
_process_entry = None
1276
super(TestProcessEntry, self).setUp()
1277
self.overrideAttr(dirstate, '_process_entry', self._process_entry)
1279
def assertChangedFileIds(self, expected, tree):
1282
file_ids = [info[0] for info
1283
in tree.iter_changes(tree.basis_tree())]
1286
self.assertEqual(sorted(expected), sorted(file_ids))
1288
def test_exceptions_raised(self):
1289
# This is a direct test of bug #495023, it relies on osutils.is_inside
1290
# getting called in an inner function. Which makes it a bit brittle,
1291
# but at least it does reproduce the bug.
1292
tree = self.make_branch_and_tree('tree')
1293
self.build_tree(['tree/file', 'tree/dir/', 'tree/dir/sub',
1294
'tree/dir2/', 'tree/dir2/sub2'])
1295
tree.add(['file', 'dir', 'dir/sub', 'dir2', 'dir2/sub2'])
1296
tree.commit('first commit')
1298
self.addCleanup(tree.unlock)
1299
basis_tree = tree.basis_tree()
1300
def is_inside_raises(*args, **kwargs):
1301
raise RuntimeError('stop this')
1302
self.overrideAttr(osutils, 'is_inside', is_inside_raises)
1303
self.assertListRaises(RuntimeError, tree.iter_changes, basis_tree)
1305
def test_simple_changes(self):
1306
tree = self.make_branch_and_tree('tree')
1307
self.build_tree(['tree/file'])
1308
tree.add(['file'], ['file-id'])
1309
self.assertChangedFileIds([tree.get_root_id(), 'file-id'], tree)
1311
self.assertChangedFileIds([], tree)
1313
def test_sha1provider_stat_and_sha1_used(self):
1314
tree = self.make_branch_and_tree('tree')
1315
self.build_tree(['tree/file'])
1316
tree.add(['file'], ['file-id'])
1319
self.addCleanup(tree.unlock)
1320
state = tree._current_dirstate()
1321
state._sha1_provider = UppercaseSHA1Provider()
1322
self.assertChangedFileIds(['file-id'], tree)