~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/selftest/test_weave.py

  • Committer: Robert Collins
  • Date: 2005-10-16 23:53:02 UTC
  • mto: This revision was merged to the branch mainline in revision 1459.
  • Revision ID: robertc@lifelesslap.robertcollins.net-20051016235302-818de607403e1c6e
test that the presence of a signature does not make a missing base file magically appear present

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
18
 
19
19
 
20
 
 
 
20
# TODO: tests regarding version names
 
21
# TODO: rbc 20050108 test that join does not leave an inconsistent weave 
 
22
#       if it fails.
21
23
 
22
24
"""test suite for weave algorithm"""
23
25
 
 
26
from pprint import pformat
24
27
 
25
 
import testsweet
26
 
from bzrlib.weave import Weave, WeaveFormatError
 
28
import bzrlib.errors as errors
 
29
from bzrlib.weave import Weave, WeaveFormatError, WeaveError, reweave
27
30
from bzrlib.weavefile import write_weave, read_weave
28
 
from pprint import pformat
29
 
 
30
 
 
31
 
try:
32
 
    set
33
 
    frozenset
34
 
except NameError:
35
 
    from sets import Set, ImmutableSet
36
 
    set = Set
37
 
    frozenset = ImmutableSet
38
 
    del Set, ImmutableSet
39
 
 
 
31
from bzrlib.selftest import TestCase
 
32
from bzrlib.osutils import sha_string
40
33
 
41
34
 
42
35
# texts for use in testing
46
39
 
47
40
 
48
41
 
49
 
class TestBase(testsweet.TestBase):
 
42
class TestBase(TestCase):
50
43
    def check_read_write(self, k):
51
44
        """Check the weave k can be written & re-read."""
52
45
        from tempfile import TemporaryFile
60
53
            tf.seek(0)
61
54
            self.log('serialized weave:')
62
55
            self.log(tf.read())
 
56
 
 
57
            self.log('')
 
58
            self.log('parents: %s' % (k._parents == k2._parents))
 
59
            self.log('         %r' % k._parents)
 
60
            self.log('         %r' % k2._parents)
 
61
            self.log('')
 
62
 
 
63
            
63
64
            self.fail('read/write check failed')
64
65
        
65
66
        
74
75
    """Store and retrieve a simple text."""
75
76
    def runTest(self):
76
77
        k = Weave()
77
 
        idx = k.add([], TEXT_0)
 
78
        idx = k.add('text0', [], TEXT_0)
78
79
        self.assertEqual(k.get(idx), TEXT_0)
79
80
        self.assertEqual(idx, 0)
80
81
 
83
84
class AnnotateOne(TestBase):
84
85
    def runTest(self):
85
86
        k = Weave()
86
 
        k.add([], TEXT_0)
 
87
        k.add('text0', [], TEXT_0)
87
88
        self.assertEqual(k.annotate(0),
88
89
                         [(0, TEXT_0[0])])
89
90
 
92
93
    def runTest(self):
93
94
        k = Weave()
94
95
 
95
 
        idx = k.add([], TEXT_0)
 
96
        idx = k.add('text0', [], TEXT_0)
96
97
        self.assertEqual(idx, 0)
97
98
 
98
 
        idx = k.add([], TEXT_1)
 
99
        idx = k.add('text1', [], TEXT_1)
99
100
        self.assertEqual(idx, 1)
100
101
 
101
102
        self.assertEqual(k.get(0), TEXT_0)
102
103
        self.assertEqual(k.get(1), TEXT_1)
103
104
 
104
 
        k.dump(self.TEST_LOG)
 
105
 
 
106
 
 
107
class AddWithGivenSha(TestBase):
 
108
    def runTest(self):
 
109
        """Add with caller-supplied SHA-1"""
 
110
        k = Weave()
 
111
 
 
112
        t = 'text0'
 
113
        k.add('text0', [], [t], sha1=sha_string(t))
105
114
 
106
115
 
107
116
 
112
121
 
113
122
        self.assertRaises(IndexError,
114
123
                          k.add,
 
124
                          'text0',
115
125
                          [69],
116
126
                          ['new text!'])
117
127
 
118
128
 
 
129
class RepeatedAdd(TestBase):
 
130
    """Add the same version twice; harmless."""
 
131
    def runTest(self):
 
132
        k = Weave()
 
133
        idx = k.add('text0', [], TEXT_0)
 
134
        idx2 = k.add('text0', [], TEXT_0)
 
135
        self.assertEqual(idx, idx2)
 
136
 
 
137
 
 
138
 
 
139
class InvalidRepeatedAdd(TestBase):
 
140
    def runTest(self):
 
141
        k = Weave()
 
142
        idx = k.add('text0', [], TEXT_0)
 
143
        self.assertRaises(WeaveError,
 
144
                          k.add,
 
145
                          'text0',
 
146
                          [],
 
147
                          ['not the same text'])
 
148
        self.assertRaises(WeaveError,
 
149
                          k.add,
 
150
                          'text0',
 
151
                          [12],         # not the right parents
 
152
                          TEXT_0)
 
153
        
 
154
 
 
155
 
119
156
class InsertLines(TestBase):
120
157
    """Store a revision that adds one line to the original.
121
158
 
124
161
    def runTest(self):
125
162
        k = Weave()
126
163
 
127
 
        k.add([], ['line 1'])
128
 
        k.add([0], ['line 1', 'line 2'])
 
164
        k.add('text0', [], ['line 1'])
 
165
        k.add('text1', [0], ['line 1', 'line 2'])
129
166
 
130
167
        self.assertEqual(k.annotate(0),
131
168
                         [(0, 'line 1')])
138
175
                         [(0, 'line 1'),
139
176
                          (1, 'line 2')])
140
177
 
141
 
        k.add([0], ['line 1', 'diverged line'])
 
178
        k.add('text2', [0], ['line 1', 'diverged line'])
142
179
 
143
180
        self.assertEqual(k.annotate(2),
144
181
                         [(0, 'line 1'),
145
182
                          (2, 'diverged line')])
146
183
 
147
184
        text3 = ['line 1', 'middle line', 'line 2']
148
 
        k.add([0, 1],
 
185
        k.add('text3',
 
186
              [0, 1],
149
187
              text3)
150
188
 
151
189
        # self.log("changes to text3: " + pformat(list(k._delta(set([0, 1]), text3))))
158
196
                          (1, 'line 2')])
159
197
 
160
198
        # now multiple insertions at different places
161
 
        k.add([0, 1, 3],
 
199
        k.add('text4',
 
200
              [0, 1, 3],
162
201
              ['line 1', 'aaa', 'middle line', 'bbb', 'line 2', 'ccc'])
163
202
 
164
203
        self.assertEqual(k.annotate(4), 
180
219
 
181
220
        base_text = ['one', 'two', 'three', 'four']
182
221
 
183
 
        k.add([], base_text)
 
222
        k.add('text0', [], base_text)
184
223
        
185
224
        texts = [['one', 'two', 'three'],
186
225
                 ['two', 'three', 'four'],
188
227
                 ['one', 'two', 'three', 'four'],
189
228
                 ]
190
229
 
 
230
        i = 1
191
231
        for t in texts:
192
 
            ver = k.add([0], t)
 
232
            ver = k.add('text%d' % i,
 
233
                        [0], t)
 
234
            i += 1
193
235
 
194
236
        self.log('final weave:')
195
237
        self.log('k._weave=' + pformat(k._weave))
406
448
    def runTest(self):
407
449
        k = Weave()
408
450
 
409
 
        k.add([], ["line the first",
 
451
        k.add('text0', [], ["line the first",
410
452
                   "line 2",
411
453
                   "line 3",
412
454
                   "fine"])
413
455
 
414
456
        self.assertEqual(len(k.get(0)), 4)
415
457
 
416
 
        k.add([0], ["line the first",
 
458
        k.add('text1', [0], ["line the first",
417
459
                   "fine"])
418
460
 
419
461
        self.assertEqual(k.get(1),
454
496
        self.assertEqual(k.get(0),
455
497
                         ["first line"])
456
498
 
457
 
        k.dump(self.TEST_LOG)
458
 
 
459
499
 
460
500
class DivergedIncludes(TestBase):
461
501
    """Weave with two diverged texts based on version 0.
501
541
        text0 = ['cheddar', 'stilton', 'gruyere']
502
542
        text1 = ['cheddar', 'blue vein', 'neufchatel', 'chevre']
503
543
        
504
 
        k.add([], text0)
505
 
        k.add([0], text1)
 
544
        k.add('text0', [], text0)
 
545
        k.add('text1', [0], text1)
506
546
 
507
547
        self.log('k._weave=' + pformat(k._weave))
508
548
 
522
562
                 ['header', '', 'line from 1', 'fixup line', 'line from 2'],
523
563
                 ]
524
564
 
525
 
        k.add([], texts[0])
526
 
        k.add([0], texts[1])
527
 
        k.add([0], texts[2])
528
 
        k.add([0, 1, 2], texts[3])
 
565
        k.add('text0', [], texts[0])
 
566
        k.add('text1', [0], texts[1])
 
567
        k.add('text2', [0], texts[2])
 
568
        k.add('merge', [0, 1, 2], texts[3])
529
569
 
530
570
        for i, t in enumerate(texts):
531
571
            self.assertEqual(k.get(i), t)
593
633
                 ['header', 'aaa', 'bbb', 'line from 2', 'more from 2'],
594
634
                 ]
595
635
 
596
 
        k.add([], texts[0])
597
 
        k.add([0], texts[1])
598
 
        k.add([0], texts[2])
 
636
        k.add('text0', [], texts[0])
 
637
        k.add('text1', [0], texts[1])
 
638
        k.add('text2', [0], texts[2])
599
639
 
600
640
        self.log('k._weave=' + pformat(k._weave))
601
641
 
641
681
 
642
682
        k = Weave()
643
683
        parents = set()
 
684
        i = 0
644
685
        for t in texts:
645
 
            ver = k.add(list(parents), t)
 
686
            ver = k.add('text%d' % i,
 
687
                        list(parents), t)
646
688
            parents.add(ver)
 
689
            i += 1
647
690
 
648
691
        self.log("k._weave=" + pformat(k._weave))
649
692
 
663
706
            return x + '\n'
664
707
        
665
708
        w = Weave()
666
 
        w.add([], map(addcrlf, base))
667
 
        w.add([0], map(addcrlf, a))
668
 
        w.add([0], map(addcrlf, b))
 
709
        w.add('text0', [], map(addcrlf, base))
 
710
        w.add('text1', [0], map(addcrlf, a))
 
711
        w.add('text2', [0], map(addcrlf, b))
669
712
 
670
713
        self.log('weave is:')
671
714
        tmpf = StringIO()
749
792
                     ['aaa', 'ddd', 'ccc'],
750
793
                     ['aaa', 'ccc'],
751
794
                     ['<<<<', 'aaa', '====', '>>>>', 'ccc'])
752
 
    
753
 
 
754
 
 
755
 
def testweave():
756
 
    import testsweet
757
 
    from unittest import TestSuite, TestLoader
758
 
    import testweave
759
 
 
760
 
    tl = TestLoader()
761
 
    suite = TestSuite()
762
 
    suite.addTest(tl.loadTestsFromModule(testweave))
763
 
    
764
 
    return int(not testsweet.run_suite(suite)) # for shell 0=true
 
795
 
 
796
 
 
797
class JoinWeavesTests(TestBase):
 
798
    def setUp(self):
 
799
        super(JoinWeavesTests, self).setUp()
 
800
        self.weave1 = Weave()
 
801
        self.lines1 = ['hello\n']
 
802
        self.lines3 = ['hello\n', 'cruel\n', 'world\n']
 
803
        self.weave1.add('v1', [], self.lines1)
 
804
        self.weave1.add('v2', [0], ['hello\n', 'world\n'])
 
805
        self.weave1.add('v3', [1], self.lines3)
 
806
        
 
807
    def test_join_empty(self):
 
808
        """Join two empty weaves."""
 
809
        eq = self.assertEqual
 
810
        w1 = Weave()
 
811
        w2 = Weave()
 
812
        w1.join(w2)
 
813
        eq(w1.numversions(), 0)
 
814
        
 
815
    def test_join_empty_to_nonempty(self):
 
816
        """Join empty weave onto nonempty."""
 
817
        self.weave1.join(Weave())
 
818
        self.assertEqual(len(self.weave1), 3)
 
819
 
 
820
    def test_join_unrelated(self):
 
821
        """Join two weaves with no history in common."""
 
822
        wb = Weave()
 
823
        wb.add('b1', [], ['line from b\n'])
 
824
        w1 = self.weave1
 
825
        w1.join(wb)
 
826
        eq = self.assertEqual
 
827
        eq(len(w1), 4)
 
828
        eq(sorted(list(w1.iter_names())),
 
829
           ['b1', 'v1', 'v2', 'v3'])
 
830
 
 
831
    def test_join_related(self):
 
832
        wa = self.weave1.copy()
 
833
        wb = self.weave1.copy()
 
834
        wa.add('a1', ['v3'], ['hello\n', 'sweet\n', 'world\n'])
 
835
        wb.add('b1', ['v3'], ['hello\n', 'pale blue\n', 'world\n'])
 
836
        eq = self.assertEquals
 
837
        eq(len(wa), 4)
 
838
        eq(len(wb), 4)
 
839
        wa.join(wb)
 
840
        eq(len(wa), 5)
 
841
        eq(wa.get_lines('b1'),
 
842
           ['hello\n', 'pale blue\n', 'world\n'])
 
843
 
 
844
    def test_join_parent_disagreement(self):
 
845
        """Cannot join weaves with different parents for a version."""
 
846
        wa = Weave()
 
847
        wb = Weave()
 
848
        wa.add('v1', [], ['hello\n'])
 
849
        wb.add('v0', [], [])
 
850
        wb.add('v1', ['v0'], ['hello\n'])
 
851
        self.assertRaises(WeaveError,
 
852
                          wa.join, wb)
 
853
 
 
854
    def test_join_text_disagreement(self):
 
855
        """Cannot join weaves with different texts for a version."""
 
856
        wa = Weave()
 
857
        wb = Weave()
 
858
        wa.add('v1', [], ['hello\n'])
 
859
        wb.add('v1', [], ['not\n', 'hello\n'])
 
860
        self.assertRaises(WeaveError,
 
861
                          wa.join, wb)
 
862
 
 
863
    def test_join_unordered(self):
 
864
        """Join weaves where indexes differ.
 
865
        
 
866
        The source weave contains a different version at index 0."""
 
867
        wa = self.weave1.copy()
 
868
        wb = Weave()
 
869
        wb.add('x1', [], ['line from x1\n'])
 
870
        wb.add('v1', [], ['hello\n'])
 
871
        wb.add('v2', ['v1'], ['hello\n', 'world\n'])
 
872
        wa.join(wb)
 
873
        eq = self.assertEquals
 
874
        eq(sorted(wa.iter_names()), ['v1', 'v2', 'v3', 'x1',])
 
875
        eq(wa.get_text('x1'), 'line from x1\n')
 
876
 
 
877
    def test_reweave_with_empty(self):
 
878
        wb = Weave()
 
879
        wr = reweave(self.weave1, wb)
 
880
        eq = self.assertEquals
 
881
        eq(sorted(wr.iter_names()), ['v1', 'v2', 'v3'])
 
882
        eq(wr.get_lines('v3'), ['hello\n', 'cruel\n', 'world\n'])
 
883
        self.weave1.reweave(wb)
 
884
        self.assertEquals(wr, self.weave1)
 
885
 
 
886
    def test_join_with_ghosts_raises_parent_mismatch(self):
 
887
        wa = self.weave1.copy()
 
888
        wb = Weave()
 
889
        wb.add('x1', [], ['line from x1\n'])
 
890
        wb.add('v1', [], ['hello\n'])
 
891
        wb.add('v2', ['v1', 'x1'], ['hello\n', 'world\n'])
 
892
        self.assertRaises(errors.WeaveParentMismatch, wa.join, wb)
 
893
 
 
894
    def test_reweave_with_ghosts(self):
 
895
        """Join that inserts parents of an existing revision.
 
896
 
 
897
        This can happen when merging from another branch who
 
898
        knows about revisions the destination does not.  In 
 
899
        this test the second weave knows of an additional parent of 
 
900
        v2.  Any revisions which are in common still have to have the 
 
901
        same text."""
 
902
        wa = self.weave1.copy()
 
903
        wb = Weave()
 
904
        wb.add('x1', [], ['line from x1\n'])
 
905
        wb.add('v1', [], ['hello\n'])
 
906
        wb.add('v2', ['v1', 'x1'], ['hello\n', 'world\n'])
 
907
        wc = reweave(wa, wb)
 
908
        eq = self.assertEquals
 
909
        eq(sorted(wc.iter_names()), ['v1', 'v2', 'v3', 'x1',])
 
910
        eq(wc.get_text('x1'), 'line from x1\n')
 
911
        eq(wc.get_lines('v2'), ['hello\n', 'world\n'])
 
912
        eq(wc.parent_names('v2'), ['v1', 'x1'])
 
913
        self.weave1.reweave(wb)
 
914
        self.assertEquals(wc, self.weave1)
765
915
 
766
916
 
767
917
if __name__ == '__main__':
768
918
    import sys
769
 
    sys.exit(testweave())
 
919
    import unittest
 
920
    sys.exit(unittest.main())
770
921