23
23
from bzrlib import (
28
29
from bzrlib.tests import (
31
from bzrlib.tests import test_dirstate
35
from bzrlib import _dirstate_helpers_pyx
36
has_dirstate_helpers_pyx = True
38
has_dirstate_helpers_pyx = False
34
41
class _CompiledDirstateHelpersFeature(tests.Feature):
37
import bzrlib._dirstate_helpers_c
43
return has_dirstate_helpers_pyx
42
45
def feature_name(self):
43
return 'bzrlib._dirstate_helpers_c'
46
return 'bzrlib._dirstate_helpers_pyx'
45
47
CompiledDirstateHelpersFeature = _CompiledDirstateHelpersFeature()
50
def load_tests(basic_tests, module, loader):
51
# FIXME: we should also parametrize against SHA1Provider !
52
suite = loader.suiteClass()
53
remaining_tests = basic_tests
55
dir_reader_scenarios = test_osutils.dir_reader_scenarios()
57
ue_scenarios = [('dirstate_Python',
58
{'update_entry': dirstate.py_update_entry})]
59
if has_dirstate_helpers_pyx:
60
pyrex_scenario = ('dirstate_Pyrex',
61
{'update_entry': _dirstate_helpers_pyx.update_entry})
62
ue_scenarios.append(pyrex_scenario)
63
process_entry_tests, remaining_tests = tests.split_suite_by_condition(
64
remaining_tests, tests.condition_isinstance(TestUpdateEntry))
65
tests.multiply_tests(process_entry_tests,
66
tests.multiply_scenarios(dir_reader_scenarios,
70
pe_scenarios = [('dirstate_Python',
71
{'_process_entry': dirstate.ProcessEntryPython})]
72
if has_dirstate_helpers_pyx:
75
{'_process_entry': _dirstate_helpers_pyx.ProcessEntryC})
76
pe_scenarios.append(pyrex_scenario)
77
process_entry_tests, remaining_tests = tests.split_suite_by_condition(
78
remaining_tests, tests.condition_isinstance(TestProcessEntry))
79
tests.multiply_tests(process_entry_tests,
80
tests.multiply_scenarios(dir_reader_scenarios,
84
dir_reader_tests, remaining_tests = tests.split_suite_by_condition(
85
remaining_tests, tests.condition_isinstance(
86
test_dirstate.TestCaseWithDirState))
87
tests.multiply_tests(dir_reader_tests, dir_reader_scenarios, suite)
88
suite.addTest(remaining_tests)
48
93
class TestBisectPathMixin(object):
49
94
"""Test that _bisect_path_*() returns the expected values.
203
248
class TestBisectPathLeft(tests.TestCase, TestBisectPathMixin):
204
"""Run all Bisect Path tests against _bisect_path_left_py."""
249
"""Run all Bisect Path tests against _bisect_path_left."""
206
251
def get_bisect_path(self):
207
from bzrlib._dirstate_helpers_py import _bisect_path_left_py
208
return _bisect_path_left_py
252
from bzrlib._dirstate_helpers_py import _bisect_path_left
253
return _bisect_path_left
210
255
def get_bisect(self):
211
256
return bisect.bisect_left, 0
214
259
class TestCompiledBisectPathLeft(TestBisectPathLeft):
215
"""Run all Bisect Path tests against _bisect_path_right_c"""
260
"""Run all Bisect Path tests against _bisect_path_lect"""
217
262
_test_needs_features = [CompiledDirstateHelpersFeature]
219
264
def get_bisect_path(self):
220
from bzrlib._dirstate_helpers_c import _bisect_path_left_c
221
return _bisect_path_left_c
265
from bzrlib._dirstate_helpers_pyx import _bisect_path_left
266
return _bisect_path_left
224
269
class TestBisectPathRight(tests.TestCase, TestBisectPathMixin):
225
"""Run all Bisect Path tests against _bisect_path_right_py"""
270
"""Run all Bisect Path tests against _bisect_path_right"""
227
272
def get_bisect_path(self):
228
from bzrlib._dirstate_helpers_py import _bisect_path_right_py
229
return _bisect_path_right_py
273
from bzrlib._dirstate_helpers_py import _bisect_path_right
274
return _bisect_path_right
231
276
def get_bisect(self):
232
277
return bisect.bisect_right, -1
235
280
class TestCompiledBisectPathRight(TestBisectPathRight):
236
"""Run all Bisect Path tests against _bisect_path_right_c"""
281
"""Run all Bisect Path tests against _bisect_path_right"""
238
283
_test_needs_features = [CompiledDirstateHelpersFeature]
240
285
def get_bisect_path(self):
241
from bzrlib._dirstate_helpers_c import _bisect_path_right_c
242
return _bisect_path_right_c
286
from bzrlib._dirstate_helpers_pyx import _bisect_path_right
287
return _bisect_path_right
245
290
class TestBisectDirblock(tests.TestCase):
717
762
_test_needs_features = [CompiledDirstateHelpersFeature]
719
764
def get_read_dirblocks(self):
720
from bzrlib._dirstate_helpers_c import _read_dirblocks_c
721
return _read_dirblocks_c
765
from bzrlib._dirstate_helpers_pyx import _read_dirblocks
766
return _read_dirblocks
724
769
class TestUsingCompiledIfAvailable(tests.TestCase):
725
770
"""Check that any compiled functions that are available are the default.
727
772
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
773
_dirstate_helpers_pyx is actually available, but the compiled functions are
732
777
def test_bisect_dirblock(self):
733
778
if CompiledDirstateHelpersFeature.available():
734
from bzrlib._dirstate_helpers_c import bisect_dirblock_c
735
self.assertIs(bisect_dirblock_c, dirstate.bisect_dirblock)
779
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)
781
from bzrlib._dirstate_helpers_py import bisect_dirblock
782
self.assertIs(bisect_dirblock, dirstate.bisect_dirblock)
740
784
def test__bisect_path_left(self):
741
785
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)
786
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)
788
from bzrlib._dirstate_helpers_py import _bisect_path_left
789
self.assertIs(_bisect_path_left, dirstate._bisect_path_left)
748
791
def test__bisect_path_right(self):
749
792
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)
793
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)
795
from bzrlib._dirstate_helpers_py import _bisect_path_right
796
self.assertIs(_bisect_path_right, dirstate._bisect_path_right)
756
798
def test_cmp_by_dirs(self):
757
799
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)
800
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)
802
from bzrlib._dirstate_helpers_py import cmp_by_dirs
803
self.assertIs(cmp_by_dirs, dirstate.cmp_by_dirs)
764
805
def test__read_dirblocks(self):
765
806
if CompiledDirstateHelpersFeature.available():
766
from bzrlib._dirstate_helpers_c import _read_dirblocks_c
767
self.assertIs(_read_dirblocks_c, dirstate._read_dirblocks)
807
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)
809
from bzrlib._dirstate_helpers_py import _read_dirblocks
810
self.assertIs(_read_dirblocks, dirstate._read_dirblocks)
772
812
def test_update_entry(self):
773
813
if CompiledDirstateHelpersFeature.available():
774
from bzrlib._dirstate_helpers_c import update_entry
775
self.assertIs(update_entry, dirstate.update_entry)
814
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)
816
from bzrlib.dirstate import update_entry
817
self.assertIs(update_entry, dirstate.update_entry)
780
819
def test_process_entry(self):
781
820
if CompiledDirstateHelpersFeature.available():
782
from bzrlib._dirstate_helpers_c import ProcessEntryC
821
from bzrlib._dirstate_helpers_pyx import ProcessEntryC
783
822
self.assertIs(ProcessEntryC, dirstate._process_entry)
785
824
from bzrlib.dirstate import ProcessEntryPython
789
828
class TestUpdateEntry(test_dirstate.TestCaseWithDirState):
790
829
"""Test the DirState.update_entry functions"""
835
super(TestUpdateEntry, self).setUp()
836
orig = dirstate.update_entry
838
dirstate.update_entry = orig
839
self.addCleanup(cleanup)
840
dirstate.update_entry = self.update_entry
792
842
def get_state_with_a(self):
793
843
"""Create a DirState tracking a single object named 'a'"""
794
844
state = test_dirstate.InstrumentedDirState.initialize('dirstate')
795
845
self.addCleanup(state.unlock)
796
846
state.add('a', 'a-id', 'file', None, '')
797
847
entry = state._get_entry(0, path_utf8='a')
798
self.set_update_entry()
799
848
return state, entry
801
def set_update_entry(self):
802
self.update_entry = dirstate.py_update_entry
804
850
def test_observed_sha1_cachable(self):
805
851
state, entry = self.get_state_with_a()
806
852
atime = time.time() - 10
1020
1066
self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
1021
1067
state._dirblock_state)
1069
def test_update_entry_tree_reference(self):
1070
state = test_dirstate.InstrumentedDirState.initialize('dirstate')
1071
self.addCleanup(state.unlock)
1072
state.add('r', 'r-id', 'tree-reference', None, '')
1073
self.build_tree(['r/'])
1074
entry = state._get_entry(0, path_utf8='r')
1075
self.do_update_entry(state, entry, 'r')
1076
entry = state._get_entry(0, path_utf8='r')
1077
self.assertEqual('t', entry[1][0][0])
1023
1079
def create_and_test_file(self, state, entry):
1024
1080
"""Create a file at 'a' and verify the state finds it during update.
1154
1211
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).
1214
# Make the disk object look old enough to cache (but it won't cache the
1215
# sha as it is a new file).
1159
1216
state.adjust_time(+20)
1160
1217
digest = 'b50e5406bb5e153ebbeb20268fcf37c87e1ecfb6'
1161
1218
self.update_entry(state, entry, abspath='a', stat_value=stat_value)
1162
1219
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
1222
def _prepare_tree(self):
1224
text = 'Hello World\n'
1225
tree = self.make_branch_and_tree('tree')
1226
self.build_tree_contents([('tree/a file', text)])
1227
tree.add('a file', 'a-file-id')
1228
# Note: dirstate does not sha prior to the first commit
1229
# so commit now in order for the test to work
1230
tree.commit('first')
1233
def test_sha1provider_sha1_used(self):
1234
tree, text = self._prepare_tree()
1235
state = dirstate.DirState.from_tree(tree, 'dirstate',
1236
UppercaseSHA1Provider())
1237
self.addCleanup(state.unlock)
1238
expected_sha = osutils.sha_string(text.upper() + "foo")
1239
entry = state._get_entry(0, path_utf8='a file')
1240
state._sha_cutoff_time()
1241
state._cutoff_time += 10
1242
sha1 = self.update_entry(state, entry, 'tree/a file',
1243
os.lstat('tree/a file'))
1244
self.assertEqual(expected_sha, sha1)
1246
def test_sha1provider_stat_and_sha1_used(self):
1247
tree, text = self._prepare_tree()
1249
self.addCleanup(tree.unlock)
1250
state = tree._current_dirstate()
1251
state._sha1_provider = UppercaseSHA1Provider()
1252
# If we used the standard provider, it would look like nothing has
1254
file_ids_changed = [change[0] for change
1255
in tree.iter_changes(tree.basis_tree())]
1256
self.assertEqual(['a-file-id'], file_ids_changed)
1259
class UppercaseSHA1Provider(dirstate.SHA1Provider):
1260
"""A custom SHA1Provider."""
1262
def sha1(self, abspath):
1263
return self.stat_and_sha1(abspath)[1]
1265
def stat_and_sha1(self, abspath):
1266
file_obj = file(abspath, 'rb')
1268
statvalue = os.fstat(file_obj.fileno())
1269
text = ''.join(file_obj.readlines())
1270
sha1 = osutils.sha_string(text.upper() + "foo")
1273
return statvalue, sha1
1276
class TestProcessEntry(test_dirstate.TestCaseWithDirState):
1279
_process_entry = None
1282
super(TestProcessEntry, self).setUp()
1283
orig = dirstate._process_entry
1285
dirstate._process_entry = orig
1286
self.addCleanup(cleanup)
1287
dirstate._process_entry = self._process_entry
1289
def assertChangedFileIds(self, expected, tree):
1292
file_ids = [info[0] for info
1293
in tree.iter_changes(tree.basis_tree())]
1296
self.assertEqual(sorted(expected), sorted(file_ids))
1298
def test_simple_changes(self):
1299
tree = self.make_branch_and_tree('tree')
1300
self.build_tree(['tree/file'])
1301
tree.add(['file'], ['file-id'])
1302
self.assertChangedFileIds([tree.get_root_id(), 'file-id'], tree)
1304
self.assertChangedFileIds([], tree)
1306
def test_sha1provider_stat_and_sha1_used(self):
1307
tree = self.make_branch_and_tree('tree')
1308
self.build_tree(['tree/file'])
1309
tree.add(['file'], ['file-id'])
1312
self.addCleanup(tree.unlock)
1313
state = tree._current_dirstate()
1314
state._sha1_provider = UppercaseSHA1Provider()
1315
self.assertChangedFileIds(['file-id'], tree)