~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_weave.py

Merge from integration.

Show diffs side-by-side

added added

removed removed

Lines of Context:
28
28
import bzrlib.errors as errors
29
29
from bzrlib.weave import Weave, WeaveFormatError, WeaveError, reweave
30
30
from bzrlib.weavefile import write_weave, read_weave
31
 
from bzrlib.selftest import TestCase
 
31
from bzrlib.tests import TestCase
32
32
from bzrlib.osutils import sha_string
33
33
 
34
34
 
38
38
          "A second line"]
39
39
 
40
40
 
41
 
 
42
41
class TestBase(TestCase):
43
42
    def check_read_write(self, k):
44
43
        """Check the weave k can be written & re-read."""
85
84
        self.assertEqual(idx, 0)
86
85
 
87
86
 
88
 
 
89
87
class AnnotateOne(TestBase):
90
88
    def runTest(self):
91
89
        k = Weave()
108
106
        self.assertEqual(k.get(1), TEXT_1)
109
107
 
110
108
 
111
 
 
112
109
class AddWithGivenSha(TestBase):
113
110
    def runTest(self):
114
111
        """Add with caller-supplied SHA-1"""
118
115
        k.add('text0', [], [t], sha1=sha_string(t))
119
116
 
120
117
 
 
118
class GetSha1(TestBase):
 
119
    def test_get_sha1(self):
 
120
        k = Weave()
 
121
        k.add('text0', [], 'text0')
 
122
        self.assertEqual('34dc0e430c642a26c3dd1c2beb7a8b4f4445eb79',
 
123
                         k.get_sha1('text0'))
 
124
        self.assertRaises(errors.WeaveRevisionNotPresent,
 
125
                          k.get_sha1, 0)
 
126
        self.assertRaises(errors.WeaveRevisionNotPresent,
 
127
                          k.get_sha1, 'text1')
 
128
                        
121
129
 
122
130
class InvalidAdd(TestBase):
123
131
    """Try to use invalid version number during add."""
140
148
        self.assertEqual(idx, idx2)
141
149
 
142
150
 
143
 
 
144
151
class InvalidRepeatedAdd(TestBase):
145
152
    def runTest(self):
146
153
        k = Weave()
157
164
                          TEXT_0)
158
165
        
159
166
 
160
 
 
161
167
class InsertLines(TestBase):
162
168
    """Store a revision that adds one line to the original.
163
169
 
214
220
                          (4, 'ccc')])
215
221
 
216
222
 
217
 
 
218
223
class DeleteLines(TestBase):
219
224
    """Deletion of lines from existing text.
220
225
 
244
249
        for i in range(len(texts)):
245
250
            self.assertEqual(k.get(i+1),
246
251
                             texts[i])
247
 
            
248
 
 
249
252
 
250
253
 
251
254
class SuicideDelete(TestBase):
271
274
                          0)        
272
275
 
273
276
 
274
 
 
275
277
class CannedDelete(TestBase):
276
278
    """Unpack canned weave with deleted lines."""
277
279
    def runTest(self):
288
290
                'last line',
289
291
                ('}', 0),
290
292
                ]
 
293
        k._sha1s = [sha_string('first lineline to be deletedlast line')
 
294
                  , sha_string('first linelast line')]
291
295
 
292
296
        self.assertEqual(k.get(0),
293
297
                         ['first line',
301
305
                          ])
302
306
 
303
307
 
304
 
 
305
308
class CannedReplacement(TestBase):
306
309
    """Unpack canned weave with deleted lines."""
307
310
    def runTest(self):
321
324
                'last line',
322
325
                ('}', 0),
323
326
                ]
 
327
        k._sha1s = [sha_string('first lineline to be deletedlast line')
 
328
                  , sha_string('first linereplacement linelast line')]
324
329
 
325
330
        self.assertEqual(k.get(0),
326
331
                         ['first line',
335
340
                          ])
336
341
 
337
342
 
338
 
 
339
343
class BadWeave(TestBase):
340
344
    """Test that we trap an insert which should not occur."""
341
345
    def runTest(self):
421
425
                '}',
422
426
                ('}', 0)]
423
427
 
 
428
        k._sha1s = [sha_string('foo {}')
 
429
                  , sha_string('foo {  added in version 1  also from v1}')
 
430
                  , sha_string('foo {  added in v2}')
 
431
                  , sha_string('foo {  added in version 1  added in v2  also from v1}')
 
432
                  ]
 
433
 
424
434
        self.assertEqual(k.get(0),
425
435
                         ['foo {',
426
436
                          '}'])
444
454
                          '}'])
445
455
                         
446
456
 
447
 
 
448
457
class DeleteLines2(TestBase):
449
458
    """Test recording revisions that delete lines.
450
459
 
472
481
                          (0, "fine")])
473
482
 
474
483
 
475
 
 
476
484
class IncludeVersions(TestBase):
477
485
    """Check texts that are stored across multiple revisions.
478
486
 
494
502
                "second line",
495
503
                ('}', 1)]
496
504
 
 
505
        k._sha1s = [sha_string('first line')
 
506
                  , sha_string('first linesecond line')]
 
507
 
497
508
        self.assertEqual(k.get(1),
498
509
                         ["first line",
499
510
                          "second line"])
523
534
                ('}', 2),                
524
535
                ]
525
536
 
 
537
        k._sha1s = [sha_string('first line')
 
538
                  , sha_string('first linesecond line')
 
539
                  , sha_string('first linealternative second line')]
 
540
 
526
541
        self.assertEqual(k.get(0),
527
542
                         ["first line"])
528
543
 
538
553
                         [0, 2])
539
554
 
540
555
 
541
 
 
542
556
class ReplaceLine(TestBase):
543
557
    def runTest(self):
544
558
        k = Weave()
555
569
        self.assertEqual(k.get(1), text1)
556
570
 
557
571
 
558
 
 
559
572
class Merge(TestBase):
560
573
    """Storage of versions that merge diverged parents"""
561
574
    def runTest(self):
612
625
                           [['bbb']]])
613
626
 
614
627
 
615
 
 
616
628
class NonConflict(TestBase):
617
629
    """Two descendants insert compatible changes.
618
630
 
625
637
        k.add([0], ['111', 'aaa', 'ccc', 'bbb'])
626
638
        k.add([1], ['aaa', 'ccc', 'bbb', '222'])
627
639
 
628
 
    
629
 
    
630
 
 
631
640
 
632
641
class AutoMerge(TestBase):
633
642
    def runTest(self):
651
660
                          'line from 1',
652
661
                          'bbb',
653
662
                          'line from 2', 'more from 2'])
654
 
        
655
663
 
656
664
 
657
665
class Khayyam(TestBase):
701
709
        self.check_read_write(k)
702
710
 
703
711
 
704
 
 
705
712
class MergeCases(TestBase):
706
713
    def doMerge(self, base, a, b, mp):
707
714
        from cStringIO import StringIO
881
888
        eq = self.assertEquals
882
889
        eq(sorted(wa.iter_names()), ['v1', 'v2', 'v3', 'x1',])
883
890
        eq(wa.get_text('x1'), 'line from x1\n')
 
891
 
 
892
 
 
893
class Corruption(TestCase):
 
894
 
 
895
    def test_detection(self):
 
896
        # Test weaves detect corruption.
 
897
        #
 
898
        # Weaves contain a checksum of their texts.
 
899
        # When a text is extracted, this checksum should be
 
900
        # verified.
 
901
 
 
902
        w = Weave()
 
903
        w.add('v1', [], ['hello\n'])
 
904
        w.add('v2', ['v1'], ['hello\n', 'there\n'])
 
905
 
 
906
        # We are going to invasively corrupt the text
 
907
        # Make sure the internals of weave are the same
 
908
        self.assertEqual([('{', 0)
 
909
                        , 'hello\n'
 
910
                        , ('}', None)
 
911
                        , ('{', 1)
 
912
                        , 'there\n'
 
913
                        , ('}', None)
 
914
                        ], w._weave)
 
915
 
 
916
        self.assertEqual(['f572d396fae9206628714fb2ce00f72e94f2258f'
 
917
                        , '90f265c6e75f1c8f9ab76dcf85528352c5f215ef'
 
918
                        ], w._sha1s)
 
919
        w.check()
 
920
 
 
921
        # Corrupted
 
922
        w._weave[4] = 'There\n'
 
923
 
 
924
        self.assertEqual('hello\n', w.get_text('v1'))
 
925
        self.assertRaises(errors.WeaveInvalidChecksum, w.get_text, 'v2')
 
926
        self.assertRaises(errors.WeaveInvalidChecksum, w.get_lines, 'v2')
 
927
        self.assertRaises(errors.WeaveInvalidChecksum, list, w.get_iter('v2'))
 
928
        self.assertRaises(errors.WeaveInvalidChecksum, w.check)
 
929
 
 
930
        # Corrected
 
931
        w._weave[4] = 'there\n'
 
932
        self.assertEqual('hello\nthere\n', w.get_text('v2'))
 
933
 
 
934
        #Invalid checksum, first digit changed
 
935
        w._sha1s[1] =  'f0f265c6e75f1c8f9ab76dcf85528352c5f215ef'
 
936
 
 
937
        self.assertEqual('hello\n', w.get_text('v1'))
 
938
        self.assertRaises(errors.WeaveInvalidChecksum, w.get_text, 'v2')
 
939
        self.assertRaises(errors.WeaveInvalidChecksum, w.get_lines, 'v2')
 
940
        self.assertRaises(errors.WeaveInvalidChecksum, list, w.get_iter('v2'))
 
941
        self.assertRaises(errors.WeaveInvalidChecksum, w.check)
 
942
 
 
943
    def test_written_detection(self):
 
944
        # Test detection of weave file corruption.
 
945
        #
 
946
        # Make sure that we can detect if a weave file has
 
947
        # been corrupted. This doesn't test all forms of corruption,
 
948
        # but it at least helps verify the data you get, is what you want.
 
949
        from cStringIO import StringIO
 
950
 
 
951
        w = Weave()
 
952
        w.add('v1', [], ['hello\n'])
 
953
        w.add('v2', ['v1'], ['hello\n', 'there\n'])
 
954
 
 
955
        tmpf = StringIO()
 
956
        write_weave(w, tmpf)
 
957
 
 
958
        # Because we are corrupting, we need to make sure we have the exact text
 
959
        self.assertEquals('# bzr weave file v5\n'
 
960
                          'i\n1 f572d396fae9206628714fb2ce00f72e94f2258f\nn v1\n\n'
 
961
                          'i 0\n1 90f265c6e75f1c8f9ab76dcf85528352c5f215ef\nn v2\n\n'
 
962
                          'w\n{ 0\n. hello\n}\n{ 1\n. there\n}\nW\n',
 
963
                          tmpf.getvalue())
 
964
 
 
965
        # Change a single letter
 
966
        tmpf = StringIO('# bzr weave file v5\n'
 
967
                        'i\n1 f572d396fae9206628714fb2ce00f72e94f2258f\nn v1\n\n'
 
968
                        'i 0\n1 90f265c6e75f1c8f9ab76dcf85528352c5f215ef\nn v2\n\n'
 
969
                        'w\n{ 0\n. hello\n}\n{ 1\n. There\n}\nW\n')
 
970
 
 
971
        w = read_weave(tmpf)
 
972
 
 
973
        self.assertEqual('hello\n', w.get_text('v1'))
 
974
        self.assertRaises(errors.WeaveInvalidChecksum, w.get_text, 'v2')
 
975
        self.assertRaises(errors.WeaveInvalidChecksum, w.get_lines, 'v2')
 
976
        self.assertRaises(errors.WeaveInvalidChecksum, list, w.get_iter('v2'))
 
977
        self.assertRaises(errors.WeaveInvalidChecksum, w.check)
 
978
 
 
979
        # Change the sha checksum
 
980
        tmpf = StringIO('# bzr weave file v5\n'
 
981
                        'i\n1 f572d396fae9206628714fb2ce00f72e94f2258f\nn v1\n\n'
 
982
                        'i 0\n1 f0f265c6e75f1c8f9ab76dcf85528352c5f215ef\nn v2\n\n'
 
983
                        'w\n{ 0\n. hello\n}\n{ 1\n. there\n}\nW\n')
 
984
 
 
985
        w = read_weave(tmpf)
 
986
 
 
987
        self.assertEqual('hello\n', w.get_text('v1'))
 
988
        self.assertRaises(errors.WeaveInvalidChecksum, w.get_text, 'v2')
 
989
        self.assertRaises(errors.WeaveInvalidChecksum, w.get_lines, 'v2')
 
990
        self.assertRaises(errors.WeaveInvalidChecksum, list, w.get_iter('v2'))
 
991
        self.assertRaises(errors.WeaveInvalidChecksum, w.check)
 
992
 
 
993