29
from bzrlib.tests import (
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)
35
from .test_osutils import dir_reader_scenarios
36
from .scenarios import (
37
load_tests_apply_scenarios,
45
load_tests = load_tests_apply_scenarios
48
compiled_dirstate_helpers_feature = features.ModuleAvailableFeature(
49
'breezy._dirstate_helpers_pyx')
52
# FIXME: we should also parametrize against SHA1Provider !
54
ue_scenarios = [('dirstate_Python',
55
{'update_entry': dirstate.py_update_entry})]
56
if compiled_dirstate_helpers_feature.available():
57
update_entry = compiled_dirstate_helpers_feature.module.update_entry
58
ue_scenarios.append(('dirstate_Pyrex', {'update_entry': update_entry}))
60
pe_scenarios = [('dirstate_Python',
61
{'_process_entry': dirstate.ProcessEntryPython})]
62
if compiled_dirstate_helpers_feature.available():
63
process_entry = compiled_dirstate_helpers_feature.module.ProcessEntryC
64
pe_scenarios.append(('dirstate_Pyrex', {'_process_entry': process_entry}))
66
helper_scenarios = [('dirstate_Python', {'helpers': _dirstate_helpers_py})]
67
if compiled_dirstate_helpers_feature.available():
68
helper_scenarios.append(('dirstate_Pyrex',
69
{'helpers': compiled_dirstate_helpers_feature.module}))
87
72
class TestBisectPathMixin(object):
775
762
def test_bisect_dirblock(self):
776
763
if compiled_dirstate_helpers_feature.available():
777
from bzrlib._dirstate_helpers_pyx import bisect_dirblock
764
from breezy._dirstate_helpers_pyx import bisect_dirblock
779
from bzrlib._dirstate_helpers_py import bisect_dirblock
766
from breezy._dirstate_helpers_py import bisect_dirblock
780
767
self.assertIs(bisect_dirblock, dirstate.bisect_dirblock)
782
769
def test__bisect_path_left(self):
783
770
if compiled_dirstate_helpers_feature.available():
784
from bzrlib._dirstate_helpers_pyx import _bisect_path_left
771
from breezy._dirstate_helpers_pyx import _bisect_path_left
786
from bzrlib._dirstate_helpers_py import _bisect_path_left
773
from breezy._dirstate_helpers_py import _bisect_path_left
787
774
self.assertIs(_bisect_path_left, dirstate._bisect_path_left)
789
776
def test__bisect_path_right(self):
790
777
if compiled_dirstate_helpers_feature.available():
791
from bzrlib._dirstate_helpers_pyx import _bisect_path_right
778
from breezy._dirstate_helpers_pyx import _bisect_path_right
793
from bzrlib._dirstate_helpers_py import _bisect_path_right
780
from breezy._dirstate_helpers_py import _bisect_path_right
794
781
self.assertIs(_bisect_path_right, dirstate._bisect_path_right)
796
783
def test_cmp_by_dirs(self):
797
784
if compiled_dirstate_helpers_feature.available():
798
from bzrlib._dirstate_helpers_pyx import cmp_by_dirs
785
from breezy._dirstate_helpers_pyx import cmp_by_dirs
800
from bzrlib._dirstate_helpers_py import cmp_by_dirs
787
from breezy._dirstate_helpers_py import cmp_by_dirs
801
788
self.assertIs(cmp_by_dirs, dirstate.cmp_by_dirs)
803
790
def test__read_dirblocks(self):
804
791
if compiled_dirstate_helpers_feature.available():
805
from bzrlib._dirstate_helpers_pyx import _read_dirblocks
792
from breezy._dirstate_helpers_pyx import _read_dirblocks
807
from bzrlib._dirstate_helpers_py import _read_dirblocks
794
from breezy._dirstate_helpers_py import _read_dirblocks
808
795
self.assertIs(_read_dirblocks, dirstate._read_dirblocks)
810
797
def test_update_entry(self):
811
798
if compiled_dirstate_helpers_feature.available():
812
from bzrlib._dirstate_helpers_pyx import update_entry
799
from breezy._dirstate_helpers_pyx import update_entry
814
from bzrlib.dirstate import update_entry
801
from breezy.dirstate import update_entry
815
802
self.assertIs(update_entry, dirstate.update_entry)
817
804
def test_process_entry(self):
818
805
if compiled_dirstate_helpers_feature.available():
819
from bzrlib._dirstate_helpers_pyx import ProcessEntryC
806
from breezy._dirstate_helpers_pyx import ProcessEntryC
820
807
self.assertIs(ProcessEntryC, dirstate._process_entry)
822
from bzrlib.dirstate import ProcessEntryPython
809
from breezy.dirstate import ProcessEntryPython
823
810
self.assertIs(ProcessEntryPython, dirstate._process_entry)
826
813
class TestUpdateEntry(test_dirstate.TestCaseWithDirState):
827
814
"""Test the DirState.update_entry functions"""
816
scenarios = multiply_scenarios(
817
dir_reader_scenarios(), ue_scenarios)
829
819
# Set by load_tests
830
820
update_entry = None
844
834
def test_observed_sha1_cachable(self):
845
835
state, entry = self.get_state_with_a()
846
837
atime = time.time() - 10
847
838
self.build_tree(['a'])
848
statvalue = os.lstat('a')
849
statvalue = test_dirstate._FakeStat(statvalue.st_size, atime, atime,
850
statvalue.st_dev, statvalue.st_ino, statvalue.st_mode)
839
statvalue = test_dirstate._FakeStat.from_stat(os.lstat('a'))
840
statvalue.st_mtime = statvalue.st_ctime = atime
841
self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
842
state._dirblock_state)
851
843
state._observed_sha1(entry, "foo", statvalue)
852
844
self.assertEqual('foo', entry[1][0][1])
853
845
packed_stat = dirstate.pack_stat(statvalue)
854
846
self.assertEqual(packed_stat, entry[1][0][4])
847
self.assertEqual(dirstate.DirState.IN_MEMORY_HASH_MODIFIED,
848
state._dirblock_state)
856
850
def test_observed_sha1_not_cachable(self):
857
851
state, entry = self.get_state_with_a()
858
853
oldval = entry[1][0][1]
859
854
oldstat = entry[1][0][4]
860
855
self.build_tree(['a'])
861
856
statvalue = os.lstat('a')
857
self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
858
state._dirblock_state)
862
859
state._observed_sha1(entry, "foo", statvalue)
863
860
self.assertEqual(oldval, entry[1][0][1])
864
861
self.assertEqual(oldstat, entry[1][0][4])
862
self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
863
state._dirblock_state)
866
865
def test_update_entry(self):
867
866
state, _ = self.get_state_with_a()
892
891
stat_value=stat_value)
893
892
self.assertEqual(None, link_or_sha1)
895
# The dirblock entry should not have cached the file's sha1 (too new)
894
# The dirblock entry should not have computed or cached the file's
895
# sha1, but it did update the files' st_size. However, this is not
896
# worth writing a dirstate file for, so we leave the state UNMODIFIED
896
897
self.assertEqual(('f', '', 14, False, dirstate.DirState.NULLSTAT),
898
self.assertEqual(dirstate.DirState.IN_MEMORY_MODIFIED,
899
self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
899
900
state._dirblock_state)
900
901
mode = stat_value.st_mode
901
902
self.assertEqual([('is_exec', mode, False)], state._log)
977
979
# Dirblock is not updated (the link is too new)
978
980
self.assertEqual([('l', '', 6, False, dirstate.DirState.NULLSTAT)],
980
self.assertEqual(dirstate.DirState.IN_MEMORY_MODIFIED,
982
# The file entry turned into a symlink, that is considered
983
# HASH modified worthy.
984
self.assertEqual(dirstate.DirState.IN_MEMORY_HASH_MODIFIED,
981
985
state._dirblock_state)
983
987
# Because the stat_value looks new, we should re-read the target
984
989
link_or_sha1 = self.update_entry(state, entry, abspath='a',
985
990
stat_value=stat_value)
986
991
self.assertEqual('target', link_or_sha1)
987
self.assertEqual([('read_link', 'a', ''),
988
('read_link', 'a', ''),
992
self.assertEqual([('read_link', 'a', '')], state._log)
990
993
self.assertEqual([('l', '', 6, False, dirstate.DirState.NULLSTAT)],
992
996
state.adjust_time(+20) # Skip into the future, all files look old
993
998
link_or_sha1 = self.update_entry(state, entry, abspath='a',
994
999
stat_value=stat_value)
1000
# The symlink stayed a symlink. So while it is new enough to cache, we
1001
# don't bother setting the flag, because it is not really worth saving
1002
# (when we stat the symlink, we'll have paged in the target.)
1003
self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
1004
state._dirblock_state)
995
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', 'a', ''),
998
('read_link', 'a', ''),
999
('read_link', 'a', ''),
1007
self.assertEqual([('read_link', 'a', '')], state._log)
1001
1008
self.assertEqual([('l', 'target', 6, False, packed_stat)],
1004
1012
# Another call won't re-read the link
1005
self.assertEqual([('read_link', 'a', ''),
1006
('read_link', 'a', ''),
1007
('read_link', 'a', ''),
1013
self.assertEqual([], state._log)
1009
1014
link_or_sha1 = self.update_entry(state, entry, abspath='a',
1010
1015
stat_value=stat_value)
1011
1016
self.assertEqual('target', link_or_sha1)
1026
1031
self.build_tree(['a/'])
1027
1032
state.adjust_time(+20)
1028
1033
self.assertIs(None, self.do_update_entry(state, entry, 'a'))
1034
# a/ used to be a file, but is now a directory, worth saving
1029
1035
self.assertEqual(dirstate.DirState.IN_MEMORY_MODIFIED,
1030
1036
state._dirblock_state)
1032
1038
self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
1033
1039
state._dirblock_state)
1034
self.assertIs(None, self.do_update_entry(state, entry, 'a'))
1040
# No changes to a/ means not worth saving.
1041
self.assertIs(None, self.do_update_entry(state, entry, 'a'))
1042
self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
1043
state._dirblock_state)
1044
# Change the last-modified time for the directory
1045
t = time.time() - 100.0
1047
os.utime('a', (t, t))
1049
# It looks like Win32 + FAT doesn't allow to change times on a dir.
1050
raise tests.TestSkipped("can't update mtime of a dir on FAT")
1051
saved_packed_stat = entry[1][0][-1]
1052
self.assertIs(None, self.do_update_entry(state, entry, 'a'))
1053
# We *do* go ahead and update the information in the dirblocks, but we
1054
# don't bother setting IN_MEMORY_MODIFIED because it is trivial to
1056
self.assertNotEqual(saved_packed_stat, entry[1][0][-1])
1035
1057
self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
1036
1058
state._dirblock_state)
1321
1345
state._sha1_provider = UppercaseSHA1Provider()
1322
1346
self.assertChangedFileIds(['file-id'], tree)
1349
class TestPackStat(tests.TestCase):
1350
"""Check packed representaton of stat values is robust on all inputs"""
1352
scenarios = helper_scenarios
1354
def pack(self, statlike_tuple):
1355
return self.helpers.pack_stat(os.stat_result(statlike_tuple))
1358
def unpack_field(packed_string, stat_field):
1359
return _dirstate_helpers_py._unpack_stat(packed_string)[stat_field]
1361
def test_result(self):
1362
self.assertEqual("AAAQAAAAABAAAAARAAAAAgAAAAEAAIHk",
1363
self.pack((33252, 1, 2, 0, 0, 0, 4096, 15.5, 16.5, 17.5)))
1365
def test_giant_inode(self):
1366
packed = self.pack((33252, 0xF80000ABC, 0, 0, 0, 0, 0, 0, 0, 0))
1367
self.assertEqual(0x80000ABC, self.unpack_field(packed, "st_ino"))
1369
def test_giant_size(self):
1370
packed = self.pack((33252, 0, 0, 0, 0, 0, (1 << 33) + 4096, 0, 0, 0))
1371
self.assertEqual(4096, self.unpack_field(packed, "st_size"))
1373
def test_fractional_mtime(self):
1374
packed = self.pack((33252, 0, 0, 0, 0, 0, 0, 0, 16.9375, 0))
1375
self.assertEqual(16, self.unpack_field(packed, "st_mtime"))
1377
def test_ancient_mtime(self):
1378
packed = self.pack((33252, 0, 0, 0, 0, 0, 0, 0, -11644473600.0, 0))
1379
self.assertEqual(1240428288, self.unpack_field(packed, "st_mtime"))
1381
def test_distant_mtime(self):
1382
packed = self.pack((33252, 0, 0, 0, 0, 0, 0, 0, 64060588800.0, 0))
1383
self.assertEqual(3931046656, self.unpack_field(packed, "st_mtime"))
1385
def test_fractional_ctime(self):
1386
packed = self.pack((33252, 0, 0, 0, 0, 0, 0, 0, 0, 17.5625))
1387
self.assertEqual(17, self.unpack_field(packed, "st_ctime"))
1389
def test_ancient_ctime(self):
1390
packed = self.pack((33252, 0, 0, 0, 0, 0, 0, 0, 0, -11644473600.0))
1391
self.assertEqual(1240428288, self.unpack_field(packed, "st_ctime"))
1393
def test_distant_ctime(self):
1394
packed = self.pack((33252, 0, 0, 0, 0, 0, 0, 0, 0, 64060588800.0))
1395
self.assertEqual(3931046656, self.unpack_field(packed, "st_ctime"))
1397
def test_negative_dev(self):
1398
packed = self.pack((33252, 0, -0xFFFFFCDE, 0, 0, 0, 0, 0, 0, 0))
1399
self.assertEqual(0x322, self.unpack_field(packed, "st_dev"))