99
idx = k.add('text0', [], TEXT_0)
96
idx = k.add([], TEXT_0)
100
97
self.assertEqual(idx, 0)
102
idx = k.add('text1', [], TEXT_1)
99
idx = k.add([], TEXT_1)
103
100
self.assertEqual(idx, 1)
105
102
self.assertEqual(k.get(0), TEXT_0)
106
103
self.assertEqual(k.get(1), TEXT_1)
109
class AddWithGivenSha(TestBase):
105
k.dump(self.TEST_LOG)
109
class DeltaAdd(TestBase):
110
"""Detection of changes prior to inserting new revision."""
110
111
def runTest(self):
111
"""Add with caller-supplied SHA-1"""
115
k.add('text0', [], [t], sha1=sha_string(t))
118
class GetSha1(TestBase):
119
def test_get_sha1(self):
121
k.add('text0', [], 'text0')
122
self.assertEqual('34dc0e430c642a26c3dd1c2beb7a8b4f4445eb79',
124
self.assertRaises(errors.WeaveRevisionNotPresent,
126
self.assertRaises(errors.WeaveRevisionNotPresent,
113
k.add([], ['line 1'])
115
self.assertEqual(k._l,
121
changes = list(k._delta(set([0]),
125
self.log('raw changes: ' + pformat(changes))
127
# currently there are 3 lines in the weave, and we insert after them
128
self.assertEquals(changes,
129
[(3, 3, ['new line'])])
131
changes = k._delta(set([0]),
135
self.assertEquals(list(changes),
136
[(1, 1, ['top line'])])
138
self.check_read_write(k)
130
141
class InvalidAdd(TestBase):
131
142
"""Try to use invalid version number during add."""
132
143
def runTest(self):
135
self.assertRaises(IndexError,
146
self.assertRaises(ValueError,
142
class RepeatedAdd(TestBase):
143
"""Add the same version twice; harmless."""
146
idx = k.add('text0', [], TEXT_0)
147
idx2 = k.add('text0', [], TEXT_0)
148
self.assertEqual(idx, idx2)
151
class InvalidRepeatedAdd(TestBase):
154
idx = k.add('text0', [], TEXT_0)
155
self.assertRaises(WeaveError,
159
['not the same text'])
160
self.assertRaises(WeaveError,
163
[12], # not the right parents
167
152
class InsertLines(TestBase):
168
153
"""Store a revision that adds one line to the original.
709
674
self.check_read_write(k)
712
class MergeCases(TestBase):
713
def doMerge(self, base, a, b, mp):
714
from cStringIO import StringIO
715
from textwrap import dedent
721
w.add('text0', [], map(addcrlf, base))
722
w.add('text1', [0], map(addcrlf, a))
723
w.add('text2', [0], map(addcrlf, b))
725
self.log('weave is:')
728
self.log(tmpf.getvalue())
730
self.log('merge plan:')
731
p = list(w.plan_merge(1, 2))
732
for state, line in p:
734
self.log('%12s | %s' % (state, line[:-1]))
738
mt.writelines(w.weave_merge(p))
740
self.log(mt.getvalue())
742
mp = map(addcrlf, mp)
743
self.assertEqual(mt.readlines(), mp)
746
def testOneInsert(self):
752
def testSeparateInserts(self):
753
self.doMerge(['aaa', 'bbb', 'ccc'],
754
['aaa', 'xxx', 'bbb', 'ccc'],
755
['aaa', 'bbb', 'yyy', 'ccc'],
756
['aaa', 'xxx', 'bbb', 'yyy', 'ccc'])
758
def testSameInsert(self):
759
self.doMerge(['aaa', 'bbb', 'ccc'],
760
['aaa', 'xxx', 'bbb', 'ccc'],
761
['aaa', 'xxx', 'bbb', 'yyy', 'ccc'],
762
['aaa', 'xxx', 'bbb', 'yyy', 'ccc'])
764
def testOverlappedInsert(self):
765
self.doMerge(['aaa', 'bbb'],
766
['aaa', 'xxx', 'yyy', 'bbb'],
767
['aaa', 'xxx', 'bbb'],
768
['aaa', '<<<<<<<', 'xxx', 'yyy', '=======', 'xxx',
771
# really it ought to reduce this to
772
# ['aaa', 'xxx', 'yyy', 'bbb']
775
def testClashReplace(self):
776
self.doMerge(['aaa'],
779
['<<<<<<<', 'xxx', '=======', 'yyy', 'zzz',
782
def testNonClashInsert(self):
783
self.doMerge(['aaa'],
786
['<<<<<<<', 'xxx', 'aaa', '=======', 'yyy', 'zzz',
789
self.doMerge(['aaa'],
795
def testDeleteAndModify(self):
796
"""Clashing delete and modification.
798
If one side modifies a region and the other deletes it then
799
there should be a conflict with one side blank.
802
#######################################
803
# skippd, not working yet
806
self.doMerge(['aaa', 'bbb', 'ccc'],
807
['aaa', 'ddd', 'ccc'],
809
['<<<<<<<<', 'aaa', '=======', '>>>>>>>', 'ccc'])
812
class JoinWeavesTests(TestBase):
814
super(JoinWeavesTests, self).setUp()
815
self.weave1 = Weave()
816
self.lines1 = ['hello\n']
817
self.lines3 = ['hello\n', 'cruel\n', 'world\n']
818
self.weave1.add('v1', [], self.lines1)
819
self.weave1.add('v2', [0], ['hello\n', 'world\n'])
820
self.weave1.add('v3', [1], self.lines3)
822
def test_join_empty(self):
823
"""Join two empty weaves."""
824
eq = self.assertEqual
828
eq(w1.numversions(), 0)
830
def test_join_empty_to_nonempty(self):
831
"""Join empty weave onto nonempty."""
832
self.weave1.join(Weave())
833
self.assertEqual(len(self.weave1), 3)
835
def test_join_unrelated(self):
836
"""Join two weaves with no history in common."""
838
wb.add('b1', [], ['line from b\n'])
841
eq = self.assertEqual
843
eq(sorted(list(w1.iter_names())),
844
['b1', 'v1', 'v2', 'v3'])
846
def test_join_related(self):
847
wa = self.weave1.copy()
848
wb = self.weave1.copy()
849
wa.add('a1', ['v3'], ['hello\n', 'sweet\n', 'world\n'])
850
wb.add('b1', ['v3'], ['hello\n', 'pale blue\n', 'world\n'])
851
eq = self.assertEquals
856
eq(wa.get_lines('b1'),
857
['hello\n', 'pale blue\n', 'world\n'])
859
def test_join_parent_disagreement(self):
860
"""Cannot join weaves with different parents for a version."""
863
wa.add('v1', [], ['hello\n'])
865
wb.add('v1', ['v0'], ['hello\n'])
866
self.assertRaises(WeaveError,
869
def test_join_text_disagreement(self):
870
"""Cannot join weaves with different texts for a version."""
873
wa.add('v1', [], ['hello\n'])
874
wb.add('v1', [], ['not\n', 'hello\n'])
875
self.assertRaises(WeaveError,
878
def test_join_unordered(self):
879
"""Join weaves where indexes differ.
881
The source weave contains a different version at index 0."""
882
wa = self.weave1.copy()
884
wb.add('x1', [], ['line from x1\n'])
885
wb.add('v1', [], ['hello\n'])
886
wb.add('v2', ['v1'], ['hello\n', 'world\n'])
888
eq = self.assertEquals
889
eq(sorted(wa.iter_names()), ['v1', 'v2', 'v3', 'x1',])
890
eq(wa.get_text('x1'), 'line from x1\n')
893
class Corruption(TestCase):
895
def test_detection(self):
896
# Test weaves detect corruption.
898
# Weaves contain a checksum of their texts.
899
# When a text is extracted, this checksum should be
903
w.add('v1', [], ['hello\n'])
904
w.add('v2', ['v1'], ['hello\n', 'there\n'])
906
# We are going to invasively corrupt the text
907
# Make sure the internals of weave are the same
908
self.assertEqual([('{', 0)
916
self.assertEqual(['f572d396fae9206628714fb2ce00f72e94f2258f'
917
, '90f265c6e75f1c8f9ab76dcf85528352c5f215ef'
922
w._weave[4] = 'There\n'
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)
931
w._weave[4] = 'there\n'
932
self.assertEqual('hello\nthere\n', w.get_text('v2'))
934
#Invalid checksum, first digit changed
935
w._sha1s[1] = 'f0f265c6e75f1c8f9ab76dcf85528352c5f215ef'
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)
943
def test_written_detection(self):
944
# Test detection of weave file corruption.
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
952
w.add('v1', [], ['hello\n'])
953
w.add('v2', ['v1'], ['hello\n', 'there\n'])
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',
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')
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)
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')
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)
679
from unittest import TestSuite, TestLoader
684
suite.addTest(tl.loadTestsFromModule(testweave))
686
return int(not testsweet.run_suite(suite)) # for shell 0=true
689
if __name__ == '__main__':
691
sys.exit(testweave())