~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test__dirstate_helpers.py

  • Committer: Martin Pool
  • Date: 2011-03-28 01:28:09 UTC
  • mto: (5425.4.19 220464-stale-locks)
  • mto: This revision was merged to the branch mainline in revision 5970.
  • Revision ID: mbp@canonical.com-20110328012809-frw003r09tcrxkiz
Represent lock held info as an object, not just a dict

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2007-2011 Canonical Ltd
 
1
# Copyright (C) 2007-2010 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
28
28
    )
29
29
from bzrlib.tests import (
30
30
    test_dirstate,
31
 
    )
32
 
from bzrlib.tests.test_osutils import dir_reader_scenarios
33
 
from bzrlib.tests.scenarios import (
34
 
    load_tests_apply_scenarios,
35
 
    multiply_scenarios,
36
 
    )
37
 
 
38
 
 
39
 
load_tests = load_tests_apply_scenarios
 
31
    test_osutils,
 
32
    )
 
33
 
 
34
try:
 
35
    from bzrlib import _dirstate_helpers_pyx
 
36
    has_dirstate_helpers_pyx = True
 
37
except ImportError:
 
38
    has_dirstate_helpers_pyx = False
40
39
 
41
40
 
42
41
compiled_dirstate_helpers_feature = tests.ModuleAvailableFeature(
43
 
    'bzrlib._dirstate_helpers_pyx')
44
 
 
45
 
 
46
 
# FIXME: we should also parametrize against SHA1Provider !
47
 
 
48
 
ue_scenarios = [('dirstate_Python',
49
 
    {'update_entry': dirstate.py_update_entry})]
50
 
if compiled_dirstate_helpers_feature.available():
51
 
    update_entry = compiled_dirstate_helpers_feature.module.update_entry
52
 
    ue_scenarios.append(('dirstate_Pyrex', {'update_entry': update_entry}))
53
 
 
54
 
pe_scenarios = [('dirstate_Python',
55
 
    {'_process_entry': dirstate.ProcessEntryPython})]
56
 
if compiled_dirstate_helpers_feature.available():
57
 
    process_entry = compiled_dirstate_helpers_feature.module.ProcessEntryC
58
 
    pe_scenarios.append(('dirstate_Pyrex', {'_process_entry': process_entry}))
 
42
                                'bzrlib._dirstate_helpers_pyx')
 
43
 
 
44
 
 
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
 
49
 
 
50
    dir_reader_scenarios = test_osutils.dir_reader_scenarios()
 
51
 
 
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,
 
62
                                                  ue_scenarios),
 
63
                         suite)
 
64
 
 
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,
 
75
                                                  pe_scenarios),
 
76
                         suite)
 
77
 
 
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)
 
83
 
 
84
    return suite
59
85
 
60
86
 
61
87
class TestBisectPathMixin(object):
693
719
    implementation.
694
720
    """
695
721
 
696
 
    # inherits scenarios from test_dirstate
697
 
 
698
722
    def get_read_dirblocks(self):
699
723
        from bzrlib._dirstate_helpers_py import _read_dirblocks
700
724
        return _read_dirblocks
802
826
class TestUpdateEntry(test_dirstate.TestCaseWithDirState):
803
827
    """Test the DirState.update_entry functions"""
804
828
 
805
 
    scenarios = multiply_scenarios(
806
 
        dir_reader_scenarios(), ue_scenarios)
807
 
 
808
829
    # Set by load_tests
809
830
    update_entry = None
810
831
 
822
843
 
823
844
    def test_observed_sha1_cachable(self):
824
845
        state, entry = self.get_state_with_a()
825
 
        state.save()
826
846
        atime = time.time() - 10
827
847
        self.build_tree(['a'])
828
 
        statvalue = test_dirstate._FakeStat.from_stat(os.lstat('a'))
829
 
        statvalue.st_mtime = statvalue.st_ctime = atime
830
 
        self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
831
 
                         state._dirblock_state)
 
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)
832
851
        state._observed_sha1(entry, "foo", statvalue)
833
852
        self.assertEqual('foo', entry[1][0][1])
834
853
        packed_stat = dirstate.pack_stat(statvalue)
835
854
        self.assertEqual(packed_stat, entry[1][0][4])
836
 
        self.assertEqual(dirstate.DirState.IN_MEMORY_HASH_MODIFIED,
837
 
                         state._dirblock_state)
838
855
 
839
856
    def test_observed_sha1_not_cachable(self):
840
857
        state, entry = self.get_state_with_a()
841
 
        state.save()
842
858
        oldval = entry[1][0][1]
843
859
        oldstat = entry[1][0][4]
844
860
        self.build_tree(['a'])
845
861
        statvalue = os.lstat('a')
846
 
        self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
847
 
                         state._dirblock_state)
848
862
        state._observed_sha1(entry, "foo", statvalue)
849
863
        self.assertEqual(oldval, entry[1][0][1])
850
864
        self.assertEqual(oldstat, entry[1][0][4])
851
 
        self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
852
 
                         state._dirblock_state)
853
865
 
854
866
    def test_update_entry(self):
855
867
        state, _ = self.get_state_with_a()
880
892
                                          stat_value=stat_value)
881
893
        self.assertEqual(None, link_or_sha1)
882
894
 
883
 
        # The dirblock entry should not have computed or cached the file's
884
 
        # sha1, but it did update the files' st_size. However, this is not
885
 
        # worth writing a dirstate file for, so we leave the state UNMODIFIED
 
895
        # The dirblock entry should not have cached the file's sha1 (too new)
886
896
        self.assertEqual(('f', '', 14, False, dirstate.DirState.NULLSTAT),
887
897
                         entry[1][0])
888
 
        self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
 
898
        self.assertEqual(dirstate.DirState.IN_MEMORY_MODIFIED,
889
899
                         state._dirblock_state)
890
900
        mode = stat_value.st_mode
891
901
        self.assertEqual([('is_exec', mode, False)], state._log)
894
904
        self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
895
905
                         state._dirblock_state)
896
906
 
897
 
        # Roll the clock back so the file is guaranteed to look too new. We
898
 
        # should still not compute the sha1.
 
907
        # If we do it again right away, we don't know if the file has changed
 
908
        # so we will re-read the file. Roll the clock back so the file is
 
909
        # guaranteed to look too new.
899
910
        state.adjust_time(-10)
900
911
        del state._log[:]
901
912
 
903
914
                                          stat_value=stat_value)
904
915
        self.assertEqual([('is_exec', mode, False)], state._log)
905
916
        self.assertEqual(None, link_or_sha1)
906
 
        self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
 
917
        self.assertEqual(dirstate.DirState.IN_MEMORY_MODIFIED,
907
918
                         state._dirblock_state)
908
919
        self.assertEqual(('f', '', 14, False, dirstate.DirState.NULLSTAT),
909
920
                         entry[1][0])
919
930
        self.assertEqual([('is_exec', mode, False)], state._log)
920
931
        self.assertEqual(('f', '', 14, False, dirstate.DirState.NULLSTAT),
921
932
                         entry[1][0])
922
 
        self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
923
 
                         state._dirblock_state)
924
933
 
925
934
        # If the file is no longer new, and the clock has been moved forward
926
935
        # sufficiently, it will cache the sha.
968
977
        # Dirblock is not updated (the link is too new)
969
978
        self.assertEqual([('l', '', 6, False, dirstate.DirState.NULLSTAT)],
970
979
                         entry[1])
971
 
        # The file entry turned into a symlink, that is considered
972
 
        # HASH modified worthy.
973
 
        self.assertEqual(dirstate.DirState.IN_MEMORY_HASH_MODIFIED,
 
980
        self.assertEqual(dirstate.DirState.IN_MEMORY_MODIFIED,
974
981
                         state._dirblock_state)
975
982
 
976
983
        # Because the stat_value looks new, we should re-read the target
977
 
        del state._log[:]
978
984
        link_or_sha1 = self.update_entry(state, entry, abspath='a',
979
985
                                          stat_value=stat_value)
980
986
        self.assertEqual('target', link_or_sha1)
981
 
        self.assertEqual([('read_link', 'a', '')], state._log)
 
987
        self.assertEqual([('read_link', 'a', ''),
 
988
                          ('read_link', 'a', ''),
 
989
                         ], state._log)
982
990
        self.assertEqual([('l', '', 6, False, dirstate.DirState.NULLSTAT)],
983
991
                         entry[1])
984
 
        state.save()
985
992
        state.adjust_time(+20) # Skip into the future, all files look old
986
 
        del state._log[:]
987
993
        link_or_sha1 = self.update_entry(state, entry, abspath='a',
988
994
                                          stat_value=stat_value)
989
 
        # The symlink stayed a symlink. So while it is new enough to cache, we
990
 
        # don't bother setting the flag, because it is not really worth saving
991
 
        # (when we stat the symlink, we'll have paged in the target.)
992
 
        self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
993
 
                         state._dirblock_state)
994
995
        self.assertEqual('target', link_or_sha1)
995
996
        # We need to re-read the link because only now can we cache it
996
 
        self.assertEqual([('read_link', 'a', '')], state._log)
 
997
        self.assertEqual([('read_link', 'a', ''),
 
998
                          ('read_link', 'a', ''),
 
999
                          ('read_link', 'a', ''),
 
1000
                         ], state._log)
997
1001
        self.assertEqual([('l', 'target', 6, False, packed_stat)],
998
1002
                         entry[1])
999
1003
 
1000
 
        del state._log[:]
1001
1004
        # Another call won't re-read the link
1002
 
        self.assertEqual([], state._log)
 
1005
        self.assertEqual([('read_link', 'a', ''),
 
1006
                          ('read_link', 'a', ''),
 
1007
                          ('read_link', 'a', ''),
 
1008
                         ], state._log)
1003
1009
        link_or_sha1 = self.update_entry(state, entry, abspath='a',
1004
1010
                                          stat_value=stat_value)
1005
1011
        self.assertEqual('target', link_or_sha1)
1020
1026
        self.build_tree(['a/'])
1021
1027
        state.adjust_time(+20)
1022
1028
        self.assertIs(None, self.do_update_entry(state, entry, 'a'))
1023
 
        # a/ used to be a file, but is now a directory, worth saving
1024
1029
        self.assertEqual(dirstate.DirState.IN_MEMORY_MODIFIED,
1025
1030
                         state._dirblock_state)
1026
1031
        state.save()
1027
1032
        self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
1028
1033
                         state._dirblock_state)
1029
 
        # No changes to a/ means not worth saving.
1030
 
        self.assertIs(None, self.do_update_entry(state, entry, 'a'))
1031
 
        self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
1032
 
                         state._dirblock_state)
1033
 
        # Change the last-modified time for the directory
1034
 
        t = time.time() - 100.0
1035
 
        try:
1036
 
            os.utime('a', (t, t))
1037
 
        except OSError:
1038
 
            # It looks like Win32 + FAT doesn't allow to change times on a dir.
1039
 
            raise tests.TestSkipped("can't update mtime of a dir on FAT")
1040
 
        saved_packed_stat = entry[1][0][-1]
1041
 
        self.assertIs(None, self.do_update_entry(state, entry, 'a'))
1042
 
        # We *do* go ahead and update the information in the dirblocks, but we
1043
 
        # don't bother setting IN_MEMORY_MODIFIED because it is trivial to
1044
 
        # recompute.
1045
 
        self.assertNotEqual(saved_packed_stat, entry[1][0][-1])
 
1034
        self.assertIs(None, self.do_update_entry(state, entry, 'a'))
1046
1035
        self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
1047
1036
                         state._dirblock_state)
1048
1037
 
1280
1269
 
1281
1270
class TestProcessEntry(test_dirstate.TestCaseWithDirState):
1282
1271
 
1283
 
    scenarios = multiply_scenarios(dir_reader_scenarios(), pe_scenarios)
1284
 
 
1285
1272
    # Set by load_tests
1286
1273
    _process_entry = None
1287
1274