~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test__dirstate_helpers.py

  • Committer: Jelmer Vernooij
  • Date: 2009-05-01 14:29:06 UTC
  • mto: This revision was merged to the branch mainline in revision 4321.
  • Revision ID: jelmer@samba.org-20090501142906-7zj8hcpp9igzuyi4
Add repository argument to 'repository' info hook, per Roberts review.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2007-2011 Canonical Ltd
 
1
# Copyright (C) 2007, 2008 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
27
27
    tests,
28
28
    )
29
29
from bzrlib.tests import (
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
 
from bzrlib.tests import (
38
 
    features,
39
 
    )
40
 
 
41
 
 
42
 
load_tests = load_tests_apply_scenarios
43
 
 
44
 
 
45
 
compiled_dirstate_helpers_feature = features.ModuleAvailableFeature(
46
 
    'bzrlib._dirstate_helpers_pyx')
47
 
 
48
 
 
49
 
# FIXME: we should also parametrize against SHA1Provider !
50
 
 
51
 
ue_scenarios = [('dirstate_Python',
52
 
    {'update_entry': dirstate.py_update_entry})]
53
 
if compiled_dirstate_helpers_feature.available():
54
 
    update_entry = compiled_dirstate_helpers_feature.module.update_entry
55
 
    ue_scenarios.append(('dirstate_Pyrex', {'update_entry': update_entry}))
56
 
 
57
 
pe_scenarios = [('dirstate_Python',
58
 
    {'_process_entry': dirstate.ProcessEntryPython})]
59
 
if compiled_dirstate_helpers_feature.available():
60
 
    process_entry = compiled_dirstate_helpers_feature.module.ProcessEntryC
61
 
    pe_scenarios.append(('dirstate_Pyrex', {'_process_entry': process_entry}))
 
30
        SymlinkFeature,
 
31
        )
 
32
from bzrlib.tests import test_dirstate
 
33
 
 
34
 
 
35
class _CompiledDirstateHelpersFeature(tests.Feature):
 
36
    def _probe(self):
 
37
        try:
 
38
            import bzrlib._dirstate_helpers_c
 
39
        except ImportError:
 
40
            return False
 
41
        return True
 
42
 
 
43
    def feature_name(self):
 
44
        return 'bzrlib._dirstate_helpers_c'
 
45
 
 
46
CompiledDirstateHelpersFeature = _CompiledDirstateHelpersFeature()
62
47
 
63
48
 
64
49
class TestBisectPathMixin(object):
217
202
 
218
203
 
219
204
class TestBisectPathLeft(tests.TestCase, TestBisectPathMixin):
220
 
    """Run all Bisect Path tests against _bisect_path_left."""
 
205
    """Run all Bisect Path tests against _bisect_path_left_py."""
221
206
 
222
207
    def get_bisect_path(self):
223
 
        from bzrlib._dirstate_helpers_py import _bisect_path_left
224
 
        return _bisect_path_left
 
208
        from bzrlib._dirstate_helpers_py import _bisect_path_left_py
 
209
        return _bisect_path_left_py
225
210
 
226
211
    def get_bisect(self):
227
212
        return bisect.bisect_left, 0
228
213
 
229
214
 
230
215
class TestCompiledBisectPathLeft(TestBisectPathLeft):
231
 
    """Run all Bisect Path tests against _bisect_path_lect"""
 
216
    """Run all Bisect Path tests against _bisect_path_right_c"""
232
217
 
233
 
    _test_needs_features = [compiled_dirstate_helpers_feature]
 
218
    _test_needs_features = [CompiledDirstateHelpersFeature]
234
219
 
235
220
    def get_bisect_path(self):
236
 
        from bzrlib._dirstate_helpers_pyx import _bisect_path_left
237
 
        return _bisect_path_left
 
221
        from bzrlib._dirstate_helpers_c import _bisect_path_left_c
 
222
        return _bisect_path_left_c
238
223
 
239
224
 
240
225
class TestBisectPathRight(tests.TestCase, TestBisectPathMixin):
241
 
    """Run all Bisect Path tests against _bisect_path_right"""
 
226
    """Run all Bisect Path tests against _bisect_path_right_py"""
242
227
 
243
228
    def get_bisect_path(self):
244
 
        from bzrlib._dirstate_helpers_py import _bisect_path_right
245
 
        return _bisect_path_right
 
229
        from bzrlib._dirstate_helpers_py import _bisect_path_right_py
 
230
        return _bisect_path_right_py
246
231
 
247
232
    def get_bisect(self):
248
233
        return bisect.bisect_right, -1
249
234
 
250
235
 
251
236
class TestCompiledBisectPathRight(TestBisectPathRight):
252
 
    """Run all Bisect Path tests against _bisect_path_right"""
 
237
    """Run all Bisect Path tests against _bisect_path_right_c"""
253
238
 
254
 
    _test_needs_features = [compiled_dirstate_helpers_feature]
 
239
    _test_needs_features = [CompiledDirstateHelpersFeature]
255
240
 
256
241
    def get_bisect_path(self):
257
 
        from bzrlib._dirstate_helpers_pyx import _bisect_path_right
258
 
        return _bisect_path_right
 
242
        from bzrlib._dirstate_helpers_c import _bisect_path_right_c
 
243
        return _bisect_path_right_c
259
244
 
260
245
 
261
246
class TestBisectDirblock(tests.TestCase):
272
257
 
273
258
    def get_bisect_dirblock(self):
274
259
        """Return an implementation of bisect_dirblock"""
275
 
        from bzrlib._dirstate_helpers_py import bisect_dirblock
276
 
        return bisect_dirblock
 
260
        from bzrlib._dirstate_helpers_py import bisect_dirblock_py
 
261
        return bisect_dirblock_py
277
262
 
278
263
    def assertBisect(self, dirblocks, split_dirblocks, path, *args, **kwargs):
279
264
        """Assert that bisect_split works like bisect_left on the split paths.
363
348
    compiled version.
364
349
    """
365
350
 
366
 
    _test_needs_features = [compiled_dirstate_helpers_feature]
 
351
    _test_needs_features = [CompiledDirstateHelpersFeature]
367
352
 
368
353
    def get_bisect_dirblock(self):
369
 
        from bzrlib._dirstate_helpers_pyx import bisect_dirblock
370
 
        return bisect_dirblock
 
354
        from bzrlib._dirstate_helpers_c import bisect_dirblock_c
 
355
        return bisect_dirblock_c
371
356
 
372
357
 
373
358
class TestCmpByDirs(tests.TestCase):
382
367
 
383
368
    def get_cmp_by_dirs(self):
384
369
        """Get a specific implementation of cmp_by_dirs."""
385
 
        from bzrlib._dirstate_helpers_py import cmp_by_dirs
386
 
        return cmp_by_dirs
 
370
        from bzrlib._dirstate_helpers_py import cmp_by_dirs_py
 
371
        return cmp_by_dirs_py
387
372
 
388
373
    def assertCmpByDirs(self, expected, str1, str2):
389
374
        """Compare the two strings, in both directions.
485
470
class TestCompiledCmpByDirs(TestCmpByDirs):
486
471
    """Test the pyrex implementation of cmp_by_dirs"""
487
472
 
488
 
    _test_needs_features = [compiled_dirstate_helpers_feature]
 
473
    _test_needs_features = [CompiledDirstateHelpersFeature]
489
474
 
490
475
    def get_cmp_by_dirs(self):
491
 
        from bzrlib._dirstate_helpers_pyx import cmp_by_dirs
492
 
        return cmp_by_dirs
 
476
        from bzrlib._dirstate_helpers_c import cmp_by_dirs_c
 
477
        return cmp_by_dirs_c
493
478
 
494
479
 
495
480
class TestCmpPathByDirblock(tests.TestCase):
504
489
 
505
490
    def get_cmp_path_by_dirblock(self):
506
491
        """Get a specific implementation of _cmp_path_by_dirblock."""
507
 
        from bzrlib._dirstate_helpers_py import _cmp_path_by_dirblock
508
 
        return _cmp_path_by_dirblock
 
492
        from bzrlib._dirstate_helpers_py import _cmp_path_by_dirblock_py
 
493
        return _cmp_path_by_dirblock_py
509
494
 
510
495
    def assertCmpPathByDirblock(self, paths):
511
496
        """Compare all paths and make sure they evaluate to the correct order.
636
621
class TestCompiledCmpPathByDirblock(TestCmpPathByDirblock):
637
622
    """Test the pyrex implementation of _cmp_path_by_dirblock"""
638
623
 
639
 
    _test_needs_features = [compiled_dirstate_helpers_feature]
 
624
    _test_needs_features = [CompiledDirstateHelpersFeature]
640
625
 
641
626
    def get_cmp_by_dirs(self):
642
 
        from bzrlib._dirstate_helpers_pyx import _cmp_path_by_dirblock
643
 
        return _cmp_path_by_dirblock
 
627
        from bzrlib._dirstate_helpers_c import _cmp_path_by_dirblock_c
 
628
        return _cmp_path_by_dirblock_c
644
629
 
645
630
 
646
631
class TestMemRChr(tests.TestCase):
647
632
    """Test memrchr functionality"""
648
633
 
649
 
    _test_needs_features = [compiled_dirstate_helpers_feature]
 
634
    _test_needs_features = [CompiledDirstateHelpersFeature]
650
635
 
651
636
    def assertMemRChr(self, expected, s, c):
652
 
        from bzrlib._dirstate_helpers_pyx import _py_memrchr
 
637
        from bzrlib._dirstate_helpers_c import _py_memrchr
653
638
        self.assertEqual(expected, _py_memrchr(s, c))
654
639
 
655
640
    def test_missing(self):
696
681
    implementation.
697
682
    """
698
683
 
699
 
    # inherits scenarios from test_dirstate
700
 
 
701
684
    def get_read_dirblocks(self):
702
 
        from bzrlib._dirstate_helpers_py import _read_dirblocks
703
 
        return _read_dirblocks
 
685
        from bzrlib._dirstate_helpers_py import _read_dirblocks_py
 
686
        return _read_dirblocks_py
704
687
 
705
688
    def test_smoketest(self):
706
689
        """Make sure that we can create and read back a simple file."""
716
699
 
717
700
    def test_trailing_garbage(self):
718
701
        tree, state, expected = self.create_basic_dirstate()
719
 
        # On Unix, we can write extra data as long as we haven't read yet, but
720
 
        # on Win32, if you've opened the file with FILE_SHARE_READ, trying to
721
 
        # open it in append mode will fail.
722
 
        state.unlock()
 
702
        # We can modify the file as long as it hasn't been read yet.
723
703
        f = open('dirstate', 'ab')
724
704
        try:
725
705
            # Add bogus trailing garbage
726
706
            f.write('bogus\n')
727
707
        finally:
728
708
            f.close()
729
 
            state.lock_read()
730
709
        e = self.assertRaises(errors.DirstateCorrupt,
731
710
                              state._read_dirblocks_if_needed)
732
711
        # Make sure we mention the bogus characters in the error
736
715
class TestCompiledReadDirblocks(TestReadDirblocks):
737
716
    """Test the pyrex implementation of _read_dirblocks"""
738
717
 
739
 
    _test_needs_features = [compiled_dirstate_helpers_feature]
 
718
    _test_needs_features = [CompiledDirstateHelpersFeature]
740
719
 
741
720
    def get_read_dirblocks(self):
742
 
        from bzrlib._dirstate_helpers_pyx import _read_dirblocks
743
 
        return _read_dirblocks
 
721
        from bzrlib._dirstate_helpers_c import _read_dirblocks_c
 
722
        return _read_dirblocks_c
744
723
 
745
724
 
746
725
class TestUsingCompiledIfAvailable(tests.TestCase):
747
726
    """Check that any compiled functions that are available are the default.
748
727
 
749
728
    It is possible to have typos, etc in the import line, such that
750
 
    _dirstate_helpers_pyx is actually available, but the compiled functions are
 
729
    _dirstate_helpers_c is actually available, but the compiled functions are
751
730
    not being used.
752
731
    """
753
732
 
754
733
    def test_bisect_dirblock(self):
755
 
        if compiled_dirstate_helpers_feature.available():
756
 
            from bzrlib._dirstate_helpers_pyx import bisect_dirblock
 
734
        if CompiledDirstateHelpersFeature.available():
 
735
            from bzrlib._dirstate_helpers_c import bisect_dirblock_c
 
736
            self.assertIs(bisect_dirblock_c, dirstate.bisect_dirblock)
757
737
        else:
758
 
            from bzrlib._dirstate_helpers_py import bisect_dirblock
759
 
        self.assertIs(bisect_dirblock, dirstate.bisect_dirblock)
 
738
            from bzrlib._dirstate_helpers_py import bisect_dirblock_py
 
739
            self.assertIs(bisect_dirblock_py, dirstate.bisect_dirblock)
760
740
 
761
741
    def test__bisect_path_left(self):
762
 
        if compiled_dirstate_helpers_feature.available():
763
 
            from bzrlib._dirstate_helpers_pyx import _bisect_path_left
 
742
        if CompiledDirstateHelpersFeature.available():
 
743
            from bzrlib._dirstate_helpers_c import _bisect_path_left_c
 
744
            self.assertIs(_bisect_path_left_c, dirstate._bisect_path_left)
764
745
        else:
765
 
            from bzrlib._dirstate_helpers_py import _bisect_path_left
766
 
        self.assertIs(_bisect_path_left, dirstate._bisect_path_left)
 
746
            from bzrlib._dirstate_helpers_py import _bisect_path_left_py
 
747
            self.assertIs(_bisect_path_left_py, dirstate._bisect_path_left)
767
748
 
768
749
    def test__bisect_path_right(self):
769
 
        if compiled_dirstate_helpers_feature.available():
770
 
            from bzrlib._dirstate_helpers_pyx import _bisect_path_right
 
750
        if CompiledDirstateHelpersFeature.available():
 
751
            from bzrlib._dirstate_helpers_c import _bisect_path_right_c
 
752
            self.assertIs(_bisect_path_right_c, dirstate._bisect_path_right)
771
753
        else:
772
 
            from bzrlib._dirstate_helpers_py import _bisect_path_right
773
 
        self.assertIs(_bisect_path_right, dirstate._bisect_path_right)
 
754
            from bzrlib._dirstate_helpers_py import _bisect_path_right_py
 
755
            self.assertIs(_bisect_path_right_py, dirstate._bisect_path_right)
774
756
 
775
757
    def test_cmp_by_dirs(self):
776
 
        if compiled_dirstate_helpers_feature.available():
777
 
            from bzrlib._dirstate_helpers_pyx import cmp_by_dirs
 
758
        if CompiledDirstateHelpersFeature.available():
 
759
            from bzrlib._dirstate_helpers_c import cmp_by_dirs_c
 
760
            self.assertIs(cmp_by_dirs_c, dirstate.cmp_by_dirs)
778
761
        else:
779
 
            from bzrlib._dirstate_helpers_py import cmp_by_dirs
780
 
        self.assertIs(cmp_by_dirs, dirstate.cmp_by_dirs)
 
762
            from bzrlib._dirstate_helpers_py import cmp_by_dirs_py
 
763
            self.assertIs(cmp_by_dirs_py, dirstate.cmp_by_dirs)
781
764
 
782
765
    def test__read_dirblocks(self):
783
 
        if compiled_dirstate_helpers_feature.available():
784
 
            from bzrlib._dirstate_helpers_pyx import _read_dirblocks
 
766
        if CompiledDirstateHelpersFeature.available():
 
767
            from bzrlib._dirstate_helpers_c import _read_dirblocks_c
 
768
            self.assertIs(_read_dirblocks_c, dirstate._read_dirblocks)
785
769
        else:
786
 
            from bzrlib._dirstate_helpers_py import _read_dirblocks
787
 
        self.assertIs(_read_dirblocks, dirstate._read_dirblocks)
 
770
            from bzrlib._dirstate_helpers_py import _read_dirblocks_py
 
771
            self.assertIs(_read_dirblocks_py, dirstate._read_dirblocks)
788
772
 
789
773
    def test_update_entry(self):
790
 
        if compiled_dirstate_helpers_feature.available():
791
 
            from bzrlib._dirstate_helpers_pyx import update_entry
 
774
        if CompiledDirstateHelpersFeature.available():
 
775
            from bzrlib._dirstate_helpers_c import update_entry
 
776
            self.assertIs(update_entry, dirstate.update_entry)
792
777
        else:
793
 
            from bzrlib.dirstate import update_entry
794
 
        self.assertIs(update_entry, dirstate.update_entry)
 
778
            from bzrlib.dirstate import py_update_entry
 
779
            self.assertIs(py_update_entry, dirstate.py_update_entry)
795
780
 
796
781
    def test_process_entry(self):
797
 
        if compiled_dirstate_helpers_feature.available():
798
 
            from bzrlib._dirstate_helpers_pyx import ProcessEntryC
 
782
        if CompiledDirstateHelpersFeature.available():
 
783
            from bzrlib._dirstate_helpers_c import ProcessEntryC
799
784
            self.assertIs(ProcessEntryC, dirstate._process_entry)
800
785
        else:
801
786
            from bzrlib.dirstate import ProcessEntryPython
805
790
class TestUpdateEntry(test_dirstate.TestCaseWithDirState):
806
791
    """Test the DirState.update_entry functions"""
807
792
 
808
 
    scenarios = multiply_scenarios(
809
 
        dir_reader_scenarios(), ue_scenarios)
810
 
 
811
 
    # Set by load_tests
812
 
    update_entry = None
813
 
 
814
 
    def setUp(self):
815
 
        super(TestUpdateEntry, self).setUp()
816
 
        self.overrideAttr(dirstate, 'update_entry', self.update_entry)
817
 
 
818
793
    def get_state_with_a(self):
819
794
        """Create a DirState tracking a single object named 'a'"""
820
795
        state = test_dirstate.InstrumentedDirState.initialize('dirstate')
821
796
        self.addCleanup(state.unlock)
822
797
        state.add('a', 'a-id', 'file', None, '')
823
798
        entry = state._get_entry(0, path_utf8='a')
 
799
        self.set_update_entry()
824
800
        return state, entry
825
801
 
 
802
    def set_update_entry(self):
 
803
        self.update_entry = dirstate.py_update_entry
 
804
 
826
805
    def test_observed_sha1_cachable(self):
827
806
        state, entry = self.get_state_with_a()
828
 
        state.save()
829
807
        atime = time.time() - 10
830
808
        self.build_tree(['a'])
831
 
        statvalue = test_dirstate._FakeStat.from_stat(os.lstat('a'))
832
 
        statvalue.st_mtime = statvalue.st_ctime = atime
833
 
        self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
834
 
                         state._dirblock_state)
 
809
        statvalue = os.lstat('a')
 
810
        statvalue = test_dirstate._FakeStat(statvalue.st_size, atime, atime,
 
811
            statvalue.st_dev, statvalue.st_ino, statvalue.st_mode)
835
812
        state._observed_sha1(entry, "foo", statvalue)
836
813
        self.assertEqual('foo', entry[1][0][1])
837
814
        packed_stat = dirstate.pack_stat(statvalue)
838
815
        self.assertEqual(packed_stat, entry[1][0][4])
839
 
        self.assertEqual(dirstate.DirState.IN_MEMORY_HASH_MODIFIED,
840
 
                         state._dirblock_state)
841
816
 
842
817
    def test_observed_sha1_not_cachable(self):
843
818
        state, entry = self.get_state_with_a()
844
 
        state.save()
845
819
        oldval = entry[1][0][1]
846
820
        oldstat = entry[1][0][4]
847
821
        self.build_tree(['a'])
848
822
        statvalue = os.lstat('a')
849
 
        self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
850
 
                         state._dirblock_state)
851
823
        state._observed_sha1(entry, "foo", statvalue)
852
824
        self.assertEqual(oldval, entry[1][0][1])
853
825
        self.assertEqual(oldstat, entry[1][0][4])
854
 
        self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
855
 
                         state._dirblock_state)
856
826
 
857
827
    def test_update_entry(self):
858
828
        state, _ = self.get_state_with_a()
883
853
                                          stat_value=stat_value)
884
854
        self.assertEqual(None, link_or_sha1)
885
855
 
886
 
        # The dirblock entry should not have computed or cached the file's
887
 
        # sha1, but it did update the files' st_size. However, this is not
888
 
        # worth writing a dirstate file for, so we leave the state UNMODIFIED
 
856
        # The dirblock entry should not have cached the file's sha1 (too new)
889
857
        self.assertEqual(('f', '', 14, False, dirstate.DirState.NULLSTAT),
890
858
                         entry[1][0])
891
 
        self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
 
859
        self.assertEqual(dirstate.DirState.IN_MEMORY_MODIFIED,
892
860
                         state._dirblock_state)
893
861
        mode = stat_value.st_mode
894
862
        self.assertEqual([('is_exec', mode, False)], state._log)
897
865
        self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
898
866
                         state._dirblock_state)
899
867
 
900
 
        # Roll the clock back so the file is guaranteed to look too new. We
901
 
        # should still not compute the sha1.
 
868
        # If we do it again right away, we don't know if the file has changed
 
869
        # so we will re-read the file. Roll the clock back so the file is
 
870
        # guaranteed to look too new.
902
871
        state.adjust_time(-10)
903
872
        del state._log[:]
904
873
 
906
875
                                          stat_value=stat_value)
907
876
        self.assertEqual([('is_exec', mode, False)], state._log)
908
877
        self.assertEqual(None, link_or_sha1)
909
 
        self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
 
878
        self.assertEqual(dirstate.DirState.IN_MEMORY_MODIFIED,
910
879
                         state._dirblock_state)
911
880
        self.assertEqual(('f', '', 14, False, dirstate.DirState.NULLSTAT),
912
881
                         entry[1][0])
922
891
        self.assertEqual([('is_exec', mode, False)], state._log)
923
892
        self.assertEqual(('f', '', 14, False, dirstate.DirState.NULLSTAT),
924
893
                         entry[1][0])
925
 
        self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
926
 
                         state._dirblock_state)
927
894
 
928
895
        # If the file is no longer new, and the clock has been moved forward
929
896
        # sufficiently, it will cache the sha.
954
921
 
955
922
    def test_update_entry_symlink(self):
956
923
        """Update entry should read symlinks."""
957
 
        self.requireFeature(features.SymlinkFeature)
 
924
        self.requireFeature(SymlinkFeature)
958
925
        state, entry = self.get_state_with_a()
959
926
        state.save()
960
927
        self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
971
938
        # Dirblock is not updated (the link is too new)
972
939
        self.assertEqual([('l', '', 6, False, dirstate.DirState.NULLSTAT)],
973
940
                         entry[1])
974
 
        # The file entry turned into a symlink, that is considered
975
 
        # HASH modified worthy.
976
 
        self.assertEqual(dirstate.DirState.IN_MEMORY_HASH_MODIFIED,
 
941
        self.assertEqual(dirstate.DirState.IN_MEMORY_MODIFIED,
977
942
                         state._dirblock_state)
978
943
 
979
944
        # Because the stat_value looks new, we should re-read the target
980
 
        del state._log[:]
981
945
        link_or_sha1 = self.update_entry(state, entry, abspath='a',
982
946
                                          stat_value=stat_value)
983
947
        self.assertEqual('target', link_or_sha1)
984
 
        self.assertEqual([('read_link', 'a', '')], state._log)
 
948
        self.assertEqual([('read_link', 'a', ''),
 
949
                          ('read_link', 'a', ''),
 
950
                         ], state._log)
985
951
        self.assertEqual([('l', '', 6, False, dirstate.DirState.NULLSTAT)],
986
952
                         entry[1])
987
 
        state.save()
988
953
        state.adjust_time(+20) # Skip into the future, all files look old
989
 
        del state._log[:]
990
954
        link_or_sha1 = self.update_entry(state, entry, abspath='a',
991
955
                                          stat_value=stat_value)
992
 
        # The symlink stayed a symlink. So while it is new enough to cache, we
993
 
        # don't bother setting the flag, because it is not really worth saving
994
 
        # (when we stat the symlink, we'll have paged in the target.)
995
 
        self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
996
 
                         state._dirblock_state)
997
956
        self.assertEqual('target', link_or_sha1)
998
957
        # We need to re-read the link because only now can we cache it
999
 
        self.assertEqual([('read_link', 'a', '')], state._log)
 
958
        self.assertEqual([('read_link', 'a', ''),
 
959
                          ('read_link', 'a', ''),
 
960
                          ('read_link', 'a', ''),
 
961
                         ], state._log)
1000
962
        self.assertEqual([('l', 'target', 6, False, packed_stat)],
1001
963
                         entry[1])
1002
964
 
1003
 
        del state._log[:]
1004
965
        # Another call won't re-read the link
1005
 
        self.assertEqual([], state._log)
 
966
        self.assertEqual([('read_link', 'a', ''),
 
967
                          ('read_link', 'a', ''),
 
968
                          ('read_link', 'a', ''),
 
969
                         ], state._log)
1006
970
        link_or_sha1 = self.update_entry(state, entry, abspath='a',
1007
971
                                          stat_value=stat_value)
1008
972
        self.assertEqual('target', link_or_sha1)
1023
987
        self.build_tree(['a/'])
1024
988
        state.adjust_time(+20)
1025
989
        self.assertIs(None, self.do_update_entry(state, entry, 'a'))
1026
 
        # a/ used to be a file, but is now a directory, worth saving
1027
990
        self.assertEqual(dirstate.DirState.IN_MEMORY_MODIFIED,
1028
991
                         state._dirblock_state)
1029
992
        state.save()
1030
993
        self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
1031
994
                         state._dirblock_state)
1032
 
        # No changes to a/ means not worth saving.
1033
 
        self.assertIs(None, self.do_update_entry(state, entry, 'a'))
1034
 
        self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
1035
 
                         state._dirblock_state)
1036
 
        # Change the last-modified time for the directory
1037
 
        t = time.time() - 100.0
1038
 
        try:
1039
 
            os.utime('a', (t, t))
1040
 
        except OSError:
1041
 
            # It looks like Win32 + FAT doesn't allow to change times on a dir.
1042
 
            raise tests.TestSkipped("can't update mtime of a dir on FAT")
1043
 
        saved_packed_stat = entry[1][0][-1]
1044
 
        self.assertIs(None, self.do_update_entry(state, entry, 'a'))
1045
 
        # We *do* go ahead and update the information in the dirblocks, but we
1046
 
        # don't bother setting IN_MEMORY_MODIFIED because it is trivial to
1047
 
        # recompute.
1048
 
        self.assertNotEqual(saved_packed_stat, entry[1][0][-1])
 
995
        self.assertIs(None, self.do_update_entry(state, entry, 'a'))
1049
996
        self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
1050
997
                         state._dirblock_state)
1051
998
 
1075
1022
                         state._dirblock_state)
1076
1023
 
1077
1024
    def test_update_entry_tree_reference(self):
 
1025
        self.set_update_entry()
1078
1026
        state = test_dirstate.InstrumentedDirState.initialize('dirstate')
1079
1027
        self.addCleanup(state.unlock)
1080
1028
        state.add('r', 'r-id', 'tree-reference', None, '')
1116
1064
 
1117
1065
        return packed_stat
1118
1066
 
1119
 
    # FIXME: Add unicode version
1120
1067
    def create_and_test_symlink(self, state, entry):
1121
1068
        """Create a symlink at 'a' and verify the state finds it.
1122
1069
 
1151
1098
 
1152
1099
    def test_update_file_to_symlink(self):
1153
1100
        """File becomes a symlink"""
1154
 
        self.requireFeature(features.SymlinkFeature)
 
1101
        self.requireFeature(SymlinkFeature)
1155
1102
        state, entry = self.get_state_with_a()
1156
1103
        # The file sha1 won't be cached unless the file is old
1157
1104
        state.adjust_time(+10)
1170
1117
 
1171
1118
    def test_update_dir_to_symlink(self):
1172
1119
        """Directory becomes a symlink"""
1173
 
        self.requireFeature(features.SymlinkFeature)
 
1120
        self.requireFeature(SymlinkFeature)
1174
1121
        state, entry = self.get_state_with_a()
1175
1122
        # The symlink target won't be cached if it isn't old
1176
1123
        state.adjust_time(+10)
1180
1127
 
1181
1128
    def test_update_symlink_to_file(self):
1182
1129
        """Symlink becomes a file"""
1183
 
        self.requireFeature(features.SymlinkFeature)
 
1130
        self.requireFeature(SymlinkFeature)
1184
1131
        state, entry = self.get_state_with_a()
1185
1132
        # The symlink and file info won't be cached unless old
1186
1133
        state.adjust_time(+10)
1190
1137
 
1191
1138
    def test_update_symlink_to_dir(self):
1192
1139
        """Symlink becomes a directory"""
1193
 
        self.requireFeature(features.SymlinkFeature)
 
1140
        self.requireFeature(SymlinkFeature)
1194
1141
        state, entry = self.get_state_with_a()
1195
1142
        # The symlink target won't be cached if it isn't old
1196
1143
        state.adjust_time(+10)
1219
1166
        self.assertEqual([('f', '', 14, True, dirstate.DirState.NULLSTAT)],
1220
1167
                         entry[1])
1221
1168
 
1222
 
        # Make the disk object look old enough to cache (but it won't cache the
1223
 
        # sha as it is a new file).
 
1169
        # Make the disk object look old enough to cache (but it won't cache the sha
 
1170
        # as it is a new file).
1224
1171
        state.adjust_time(+20)
1225
1172
        digest = 'b50e5406bb5e153ebbeb20268fcf37c87e1ecfb6'
1226
1173
        self.update_entry(state, entry, abspath='a', stat_value=stat_value)
1247
1194
        entry = state._get_entry(0, path_utf8='a file')
1248
1195
        state._sha_cutoff_time()
1249
1196
        state._cutoff_time += 10
1250
 
        sha1 = self.update_entry(state, entry, 'tree/a file',
1251
 
                                 os.lstat('tree/a file'))
 
1197
        sha1 = dirstate.update_entry(state, entry, 'tree/a file',
 
1198
            os.lstat('tree/a file'))
1252
1199
        self.assertEqual(expected_sha, sha1)
1253
1200
 
1254
1201
    def test_sha1provider_stat_and_sha1_used(self):
1259
1206
        state._sha1_provider = UppercaseSHA1Provider()
1260
1207
        # If we used the standard provider, it would look like nothing has
1261
1208
        # changed
1262
 
        file_ids_changed = [change[0] for change
1263
 
                            in tree.iter_changes(tree.basis_tree())]
 
1209
        file_ids_changed = [change[0] for change 
 
1210
                in tree.iter_changes(tree.basis_tree())]
1264
1211
        self.assertEqual(['a-file-id'], file_ids_changed)
1265
1212
 
1266
1213
 
1281
1228
        return statvalue, sha1
1282
1229
 
1283
1230
 
1284
 
class TestProcessEntry(test_dirstate.TestCaseWithDirState):
1285
 
 
1286
 
    scenarios = multiply_scenarios(dir_reader_scenarios(), pe_scenarios)
1287
 
 
1288
 
    # Set by load_tests
1289
 
    _process_entry = None
 
1231
class TestCompiledUpdateEntry(TestUpdateEntry):
 
1232
    """Test the pyrex implementation of _read_dirblocks"""
 
1233
 
 
1234
    _test_needs_features = [CompiledDirstateHelpersFeature]
 
1235
 
 
1236
    def set_update_entry(self):
 
1237
        from bzrlib._dirstate_helpers_c import update_entry
 
1238
        self.update_entry = update_entry
 
1239
 
 
1240
 
 
1241
class TestProcessEntryPython(test_dirstate.TestCaseWithDirState):
1290
1242
 
1291
1243
    def setUp(self):
1292
 
        super(TestProcessEntry, self).setUp()
1293
 
        self.overrideAttr(dirstate, '_process_entry', self._process_entry)
 
1244
        super(TestProcessEntryPython, self).setUp()
 
1245
        self.setup_process_entry()
 
1246
 
 
1247
    def setup_process_entry(self):
 
1248
        from bzrlib import dirstate
 
1249
        orig = dirstate._process_entry
 
1250
        def cleanup():
 
1251
            dirstate._process_entry = orig
 
1252
        self.addCleanup(cleanup)
 
1253
        dirstate._process_entry = dirstate.ProcessEntryPython
1294
1254
 
1295
1255
    def assertChangedFileIds(self, expected, tree):
1296
1256
        tree.lock_read()
1301
1261
            tree.unlock()
1302
1262
        self.assertEqual(sorted(expected), sorted(file_ids))
1303
1263
 
1304
 
    def test_exceptions_raised(self):
1305
 
        # This is a direct test of bug #495023, it relies on osutils.is_inside
1306
 
        # getting called in an inner function. Which makes it a bit brittle,
1307
 
        # but at least it does reproduce the bug.
1308
 
        tree = self.make_branch_and_tree('tree')
1309
 
        self.build_tree(['tree/file', 'tree/dir/', 'tree/dir/sub',
1310
 
                         'tree/dir2/', 'tree/dir2/sub2'])
1311
 
        tree.add(['file', 'dir', 'dir/sub', 'dir2', 'dir2/sub2'])
1312
 
        tree.commit('first commit')
1313
 
        tree.lock_read()
1314
 
        self.addCleanup(tree.unlock)
1315
 
        basis_tree = tree.basis_tree()
1316
 
        def is_inside_raises(*args, **kwargs):
1317
 
            raise RuntimeError('stop this')
1318
 
        self.overrideAttr(osutils, 'is_inside', is_inside_raises)
1319
 
        self.assertListRaises(RuntimeError, tree.iter_changes, basis_tree)
1320
 
 
1321
1264
    def test_simple_changes(self):
1322
1265
        tree = self.make_branch_and_tree('tree')
1323
1266
        self.build_tree(['tree/file'])
1337
1280
        state._sha1_provider = UppercaseSHA1Provider()
1338
1281
        self.assertChangedFileIds(['file-id'], tree)
1339
1282
 
 
1283
 
 
1284
class TestProcessEntryC(TestProcessEntryPython):
 
1285
    _test_needs_features = [CompiledDirstateHelpersFeature]
 
1286
 
 
1287
    def setup_process_entry(self):
 
1288
        from bzrlib import _dirstate_helpers_c
 
1289
        orig = dirstate._process_entry
 
1290
        def cleanup():
 
1291
            dirstate._process_entry = orig
 
1292
        self.addCleanup(cleanup)
 
1293
        dirstate._process_entry = _dirstate_helpers_c.ProcessEntryC
 
1294