748
785
self.doMerge(['aaa', 'bbb', 'ccc'],
749
786
['aaa', 'ddd', 'ccc'],
751
['<<<<', 'aaa', '====', '>>>>', 'ccc'])
757
from unittest import TestSuite, TestLoader
762
suite.addTest(tl.loadTestsFromModule(testweave))
764
return int(not testsweet.run_suite(suite)) # for shell 0=true
767
if __name__ == '__main__':
769
sys.exit(testweave())
788
['<<<<<<<< ', 'aaa', '=======', '>>>>>>> ', 'ccc'])
791
class JoinWeavesTests(TestBase):
793
super(JoinWeavesTests, self).setUp()
794
self.weave1 = Weave()
795
self.lines1 = ['hello\n']
796
self.lines3 = ['hello\n', 'cruel\n', 'world\n']
797
self.weave1.add('v1', [], self.lines1)
798
self.weave1.add('v2', [0], ['hello\n', 'world\n'])
799
self.weave1.add('v3', [1], self.lines3)
801
def test_join_empty(self):
802
"""Join two empty weaves."""
803
eq = self.assertEqual
807
eq(w1.numversions(), 0)
809
def test_join_empty_to_nonempty(self):
810
"""Join empty weave onto nonempty."""
811
self.weave1.join(Weave())
812
self.assertEqual(len(self.weave1), 3)
814
def test_join_unrelated(self):
815
"""Join two weaves with no history in common."""
817
wb.add('b1', [], ['line from b\n'])
820
eq = self.assertEqual
822
eq(sorted(list(w1.iter_names())),
823
['b1', 'v1', 'v2', 'v3'])
825
def test_join_related(self):
826
wa = self.weave1.copy()
827
wb = self.weave1.copy()
828
wa.add('a1', ['v3'], ['hello\n', 'sweet\n', 'world\n'])
829
wb.add('b1', ['v3'], ['hello\n', 'pale blue\n', 'world\n'])
830
eq = self.assertEquals
835
eq(wa.get_lines('b1'),
836
['hello\n', 'pale blue\n', 'world\n'])
838
def test_join_parent_disagreement(self):
839
"""Cannot join weaves with different parents for a version."""
842
wa.add('v1', [], ['hello\n'])
844
wb.add('v1', ['v0'], ['hello\n'])
845
self.assertRaises(WeaveError,
848
def test_join_text_disagreement(self):
849
"""Cannot join weaves with different texts for a version."""
852
wa.add('v1', [], ['hello\n'])
853
wb.add('v1', [], ['not\n', 'hello\n'])
854
self.assertRaises(WeaveError,
857
def test_join_unordered(self):
858
"""Join weaves where indexes differ.
860
The source weave contains a different version at index 0."""
861
wa = self.weave1.copy()
863
wb.add('x1', [], ['line from x1\n'])
864
wb.add('v1', [], ['hello\n'])
865
wb.add('v2', ['v1'], ['hello\n', 'world\n'])
867
eq = self.assertEquals
868
eq(sorted(wa.iter_names()), ['v1', 'v2', 'v3', 'x1',])
869
eq(wa.get_text('x1'), 'line from x1\n')
871
def test_written_detection(self):
872
# Test detection of weave file corruption.
874
# Make sure that we can detect if a weave file has
875
# been corrupted. This doesn't test all forms of corruption,
876
# but it at least helps verify the data you get, is what you want.
877
from cStringIO import StringIO
880
w.add('v1', [], ['hello\n'])
881
w.add('v2', ['v1'], ['hello\n', 'there\n'])
886
# Because we are corrupting, we need to make sure we have the exact text
887
self.assertEquals('# bzr weave file v5\n'
888
'i\n1 f572d396fae9206628714fb2ce00f72e94f2258f\nn v1\n\n'
889
'i 0\n1 90f265c6e75f1c8f9ab76dcf85528352c5f215ef\nn v2\n\n'
890
'w\n{ 0\n. hello\n}\n{ 1\n. there\n}\nW\n',
893
# Change a single letter
894
tmpf = StringIO('# bzr weave file v5\n'
895
'i\n1 f572d396fae9206628714fb2ce00f72e94f2258f\nn v1\n\n'
896
'i 0\n1 90f265c6e75f1c8f9ab76dcf85528352c5f215ef\nn v2\n\n'
897
'w\n{ 0\n. hello\n}\n{ 1\n. There\n}\nW\n')
901
self.assertEqual('hello\n', w.get_text('v1'))
902
self.assertRaises(errors.WeaveInvalidChecksum, w.get_text, 'v2')
903
self.assertRaises(errors.WeaveInvalidChecksum, w.get_lines, 'v2')
904
self.assertRaises(errors.WeaveInvalidChecksum, list, w.get_iter('v2'))
905
self.assertRaises(errors.WeaveInvalidChecksum, w.check)
907
# Change the sha checksum
908
tmpf = StringIO('# bzr weave file v5\n'
909
'i\n1 f572d396fae9206628714fb2ce00f72e94f2258f\nn v1\n\n'
910
'i 0\n1 f0f265c6e75f1c8f9ab76dcf85528352c5f215ef\nn v2\n\n'
911
'w\n{ 0\n. hello\n}\n{ 1\n. there\n}\nW\n')
915
self.assertEqual('hello\n', w.get_text('v1'))
916
self.assertRaises(errors.WeaveInvalidChecksum, w.get_text, 'v2')
917
self.assertRaises(errors.WeaveInvalidChecksum, w.get_lines, 'v2')
918
self.assertRaises(errors.WeaveInvalidChecksum, list, w.get_iter('v2'))
919
self.assertRaises(errors.WeaveInvalidChecksum, w.check)
922
class InstrumentedWeave(Weave):
923
"""Keep track of how many times functions are called."""
925
def __init__(self, weave_name=None):
926
self._extract_count = 0
927
Weave.__init__(self, weave_name=weave_name)
929
def _extract(self, versions):
930
self._extract_count += 1
931
return Weave._extract(self, versions)
934
class JoinOptimization(TestCase):
935
"""Test that Weave.join() doesn't extract all texts, only what must be done."""
938
w1 = InstrumentedWeave()
939
w2 = InstrumentedWeave()
942
txt1 = ['a\n', 'b\n']
943
txt2 = ['a\n', 'c\n']
944
txt3 = ['a\n', 'b\n', 'c\n']
946
w1.add('txt0', [], txt0) # extract 1a
947
w2.add('txt0', [], txt0) # extract 1b
948
w1.add('txt1', [0], txt1)# extract 2a
949
w2.add('txt2', [0], txt2)# extract 2b
950
w1.join(w2) # extract 3a to add txt2
951
w2.join(w1) # extract 3b to add txt1
953
w1.add('txt3', [1, 2], txt3) # extract 4a
954
w2.add('txt3', [1, 2], txt3) # extract 4b
955
# These secretly have inverted parents
957
# This should not have to do any extractions
958
w1.join(w2) # NO extract, texts already present with same parents
959
w2.join(w1) # NO extract, texts already present with same parents
961
self.assertEqual(4, w1._extract_count)
962
self.assertEqual(4, w2._extract_count)
964
def test_double_parent(self):
965
# It should not be considered illegal to add
966
# a revision with the same parent twice
967
w1 = InstrumentedWeave()
968
w2 = InstrumentedWeave()
971
txt1 = ['a\n', 'b\n']
972
txt2 = ['a\n', 'c\n']
973
txt3 = ['a\n', 'b\n', 'c\n']
975
w1.add('txt0', [], txt0)
976
w2.add('txt0', [], txt0)
977
w1.add('txt1', [0], txt1)
978
w2.add('txt1', [0,0], txt1)
979
# Same text, effectively the same, because the
980
# parent is only repeated
981
w1.join(w2) # extract 3a to add txt2
982
w2.join(w1) # extract 3b to add txt1
985
class MismatchedTexts(TestCase):
986
"""Test that merging two weaves with different texts fails."""
988
def test_reweave(self):
992
w1.add('txt0', [], ['a\n'])
993
w2.add('txt0', [], ['a\n'])
994
w1.add('txt1', [0], ['a\n', 'b\n'])
995
w2.add('txt1', [0], ['a\n', 'c\n'])
997
self.assertRaises(errors.WeaveTextDiffers, w1.reweave, w2)