~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-06 12:14:01 UTC
  • mfrom: (1393.1.67)
  • Revision ID: robertc@robertcollins.net-20051006121401-ce87bcb93909bbdf
merge martins latest

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
# TODO: tests regarding version names
 
21
 
20
22
 
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
from bzrlib.weave import Weave, WeaveFormatError, WeaveError
27
29
from bzrlib.weavefile import write_weave, read_weave
28
 
from pprint import pformat
29
 
 
30
 
 
31
 
 
32
 
try:
33
 
    set
34
 
    frozenset
35
 
except NameError:
36
 
    from sets import Set, ImmutableSet
37
 
    set = Set
38
 
    frozenset = ImmutableSet
39
 
    del Set, ImmutableSet
40
 
 
 
30
from bzrlib.selftest import TestCase
 
31
from bzrlib.osutils import sha_string
41
32
 
42
33
 
43
34
# texts for use in testing
47
38
 
48
39
 
49
40
 
50
 
class TestBase(testsweet.TestBase):
 
41
class TestBase(TestCase):
51
42
    def check_read_write(self, k):
52
43
        """Check the weave k can be written & re-read."""
53
44
        from tempfile import TemporaryFile
61
52
            tf.seek(0)
62
53
            self.log('serialized weave:')
63
54
            self.log(tf.read())
 
55
 
 
56
            self.log('')
 
57
            self.log('parents: %s' % (k._parents == k2._parents))
 
58
            self.log('         %r' % k._parents)
 
59
            self.log('         %r' % k2._parents)
 
60
            self.log('')
 
61
 
 
62
            
64
63
            self.fail('read/write check failed')
65
64
        
66
65
        
75
74
    """Store and retrieve a simple text."""
76
75
    def runTest(self):
77
76
        k = Weave()
78
 
        idx = k.add([], TEXT_0)
 
77
        idx = k.add('text0', [], TEXT_0)
79
78
        self.assertEqual(k.get(idx), TEXT_0)
80
79
        self.assertEqual(idx, 0)
81
80
 
84
83
class AnnotateOne(TestBase):
85
84
    def runTest(self):
86
85
        k = Weave()
87
 
        k.add([], TEXT_0)
 
86
        k.add('text0', [], TEXT_0)
88
87
        self.assertEqual(k.annotate(0),
89
88
                         [(0, TEXT_0[0])])
90
89
 
93
92
    def runTest(self):
94
93
        k = Weave()
95
94
 
96
 
        idx = k.add([], TEXT_0)
 
95
        idx = k.add('text0', [], TEXT_0)
97
96
        self.assertEqual(idx, 0)
98
97
 
99
 
        idx = k.add([], TEXT_1)
 
98
        idx = k.add('text1', [], TEXT_1)
100
99
        self.assertEqual(idx, 1)
101
100
 
102
101
        self.assertEqual(k.get(0), TEXT_0)
103
102
        self.assertEqual(k.get(1), TEXT_1)
104
103
 
105
 
        k.dump(self.TEST_LOG)
106
 
 
107
 
 
108
 
 
109
 
class DeltaAdd(TestBase):
110
 
    """Detection of changes prior to inserting new revision."""
 
104
 
 
105
 
 
106
class AddWithGivenSha(TestBase):
111
107
    def runTest(self):
 
108
        """Add with caller-supplied SHA-1"""
112
109
        k = Weave()
113
 
        k.add([], ['line 1'])
114
 
 
115
 
        self.assertEqual(k._l,
116
 
                         [('{', 0),
117
 
                          'line 1',
118
 
                          ('}', 0),
119
 
                          ])
120
 
 
121
 
        changes = list(k._delta(set([0]),
122
 
                                ['line 1',
123
 
                                 'new line']))
124
 
 
125
 
        self.log('raw changes: ' + pformat(changes))
126
 
 
127
 
        # currently there are 3 lines in the weave, and we insert after them
128
 
        self.assertEquals(changes,
129
 
                          [(3, 3, ['new line'])])
130
 
 
131
 
        changes = k._delta(set([0]),
132
 
                           ['top line',
133
 
                            'line 1'])
134
 
        
135
 
        self.assertEquals(list(changes),
136
 
                          [(1, 1, ['top line'])])
137
 
 
138
 
        self.check_read_write(k)
 
110
 
 
111
        t = 'text0'
 
112
        k.add('text0', [], [t], sha1=sha_string(t))
 
113
 
139
114
 
140
115
 
141
116
class InvalidAdd(TestBase):
143
118
    def runTest(self):
144
119
        k = Weave()
145
120
 
146
 
        self.assertRaises(ValueError,
 
121
        self.assertRaises(IndexError,
147
122
                          k.add,
 
123
                          'text0',
148
124
                          [69],
149
125
                          ['new text!'])
150
126
 
151
127
 
 
128
class RepeatedAdd(TestBase):
 
129
    """Add the same version twice; harmless."""
 
130
    def runTest(self):
 
131
        k = Weave()
 
132
        idx = k.add('text0', [], TEXT_0)
 
133
        idx2 = k.add('text0', [], TEXT_0)
 
134
        self.assertEqual(idx, idx2)
 
135
 
 
136
 
 
137
 
 
138
class InvalidRepeatedAdd(TestBase):
 
139
    def runTest(self):
 
140
        k = Weave()
 
141
        idx = k.add('text0', [], TEXT_0)
 
142
        self.assertRaises(WeaveError,
 
143
                          k.add,
 
144
                          'text0',
 
145
                          [],
 
146
                          ['not the same text'])
 
147
        self.assertRaises(WeaveError,
 
148
                          k.add,
 
149
                          'text0',
 
150
                          [12],         # not the right parents
 
151
                          TEXT_0)
 
152
        
 
153
 
 
154
 
152
155
class InsertLines(TestBase):
153
156
    """Store a revision that adds one line to the original.
154
157
 
157
160
    def runTest(self):
158
161
        k = Weave()
159
162
 
160
 
        k.add([], ['line 1'])
161
 
        k.add([0], ['line 1', 'line 2'])
 
163
        k.add('text0', [], ['line 1'])
 
164
        k.add('text1', [0], ['line 1', 'line 2'])
162
165
 
163
166
        self.assertEqual(k.annotate(0),
164
167
                         [(0, 'line 1')])
171
174
                         [(0, 'line 1'),
172
175
                          (1, 'line 2')])
173
176
 
174
 
        k.add([0], ['line 1', 'diverged line'])
 
177
        k.add('text2', [0], ['line 1', 'diverged line'])
175
178
 
176
179
        self.assertEqual(k.annotate(2),
177
180
                         [(0, 'line 1'),
178
181
                          (2, 'diverged line')])
179
182
 
180
183
        text3 = ['line 1', 'middle line', 'line 2']
181
 
        k.add([0, 1],
 
184
        k.add('text3',
 
185
              [0, 1],
182
186
              text3)
183
187
 
184
 
        self.log("changes to text3: " + pformat(list(k._delta(set([0, 1]), text3))))
 
188
        # self.log("changes to text3: " + pformat(list(k._delta(set([0, 1]), text3))))
185
189
 
186
 
        self.log("k._l=" + pformat(k._l))
 
190
        self.log("k._weave=" + pformat(k._weave))
187
191
 
188
192
        self.assertEqual(k.annotate(3),
189
193
                         [(0, 'line 1'),
191
195
                          (1, 'line 2')])
192
196
 
193
197
        # now multiple insertions at different places
194
 
        k.add([0, 1, 3],
 
198
        k.add('text4',
 
199
              [0, 1, 3],
195
200
              ['line 1', 'aaa', 'middle line', 'bbb', 'line 2', 'ccc'])
196
201
 
197
202
        self.assertEqual(k.annotate(4), 
213
218
 
214
219
        base_text = ['one', 'two', 'three', 'four']
215
220
 
216
 
        k.add([], base_text)
 
221
        k.add('text0', [], base_text)
217
222
        
218
223
        texts = [['one', 'two', 'three'],
219
224
                 ['two', 'three', 'four'],
221
226
                 ['one', 'two', 'three', 'four'],
222
227
                 ]
223
228
 
 
229
        i = 1
224
230
        for t in texts:
225
 
            ver = k.add([0], t)
 
231
            ver = k.add('text%d' % i,
 
232
                        [0], t)
 
233
            i += 1
226
234
 
227
235
        self.log('final weave:')
228
 
        self.log('k._l=' + pformat(k._l))
 
236
        self.log('k._weave=' + pformat(k._weave))
229
237
 
230
238
        for i in range(len(texts)):
231
239
            self.assertEqual(k.get(i+1),
239
247
    def runTest(self):
240
248
        k = Weave()
241
249
 
242
 
        k._v = [(),
 
250
        k._parents = [(),
243
251
                ]
244
 
        k._l = [('{', 0),
 
252
        k._weave = [('{', 0),
245
253
                'first line',
246
254
                ('[', 0),
247
255
                'deleted in 0',
248
256
                (']', 0),
249
257
                ('}', 0),
250
258
                ]
 
259
        ################################### SKIPPED
 
260
        # Weave.get doesn't trap this anymore
 
261
        return 
251
262
 
252
263
        self.assertRaises(WeaveFormatError,
253
264
                          k.get,
260
271
    def runTest(self):
261
272
        k = Weave()
262
273
 
263
 
        k._v = [(),
 
274
        k._parents = [(),
264
275
                frozenset([0]),
265
276
                ]
266
 
        k._l = [('{', 0),
 
277
        k._weave = [('{', 0),
267
278
                'first line',
268
279
                ('[', 1),
269
280
                'line to be deleted',
290
301
    def runTest(self):
291
302
        k = Weave()
292
303
 
293
 
        k._v = [frozenset(),
 
304
        k._parents = [frozenset(),
294
305
                frozenset([0]),
295
306
                ]
296
 
        k._l = [('{', 0),
 
307
        k._weave = [('{', 0),
297
308
                'first line',
298
309
                ('[', 1),
299
310
                'line to be deleted',
324
335
    def runTest(self):
325
336
        k = Weave()
326
337
 
327
 
        k._v = [frozenset(),
 
338
        k._parents = [frozenset(),
328
339
                ]
329
 
        k._l = ['bad line',
 
340
        k._weave = ['bad line',
330
341
                ('{', 0),
331
342
                'foo {',
332
343
                ('{', 1),
339
350
                '}',
340
351
                ('}', 0)]
341
352
 
 
353
        ################################### SKIPPED
 
354
        # Weave.get doesn't trap this anymore
 
355
        return 
 
356
 
 
357
 
342
358
        self.assertRaises(WeaveFormatError,
343
359
                          k.get,
344
360
                          0)
349
365
    def runTest(self):
350
366
        k = Weave()
351
367
 
352
 
        k._v = [frozenset(),
 
368
        k._parents = [frozenset(),
353
369
                frozenset([0]),
354
370
                frozenset([0]),
355
371
                frozenset([0,1,2]),
356
372
                ]
357
 
        k._l = [('{', 0),
 
373
        k._weave = [('{', 0),
358
374
                'foo {',
359
375
                ('{', 1),
360
376
                '  added in version 1',
364
380
                ('}', 1),
365
381
                ('}', 0)]
366
382
 
 
383
 
 
384
        # this is not currently enforced by get
 
385
        return  ##########################################
 
386
 
367
387
        self.assertRaises(WeaveFormatError,
368
388
                          k.get,
369
389
                          0)
378
398
    def runTest(self):
379
399
        k = Weave()
380
400
 
381
 
        k._v = [frozenset(),
 
401
        k._parents = [frozenset(),
382
402
                frozenset([0]),
383
403
                frozenset([0]),
384
404
                frozenset([0,1,2]),
385
405
                ]
386
 
        k._l = [('{', 0),
 
406
        k._weave = [('{', 0),
387
407
                'foo {',
388
408
                ('{', 1),
389
409
                '  added in version 1',
427
447
    def runTest(self):
428
448
        k = Weave()
429
449
 
430
 
        k.add([], ["line the first",
 
450
        k.add('text0', [], ["line the first",
431
451
                   "line 2",
432
452
                   "line 3",
433
453
                   "fine"])
434
454
 
435
455
        self.assertEqual(len(k.get(0)), 4)
436
456
 
437
 
        k.add([0], ["line the first",
 
457
        k.add('text1', [0], ["line the first",
438
458
                   "fine"])
439
459
 
440
460
        self.assertEqual(k.get(1),
460
480
    def runTest(self):
461
481
        k = Weave()
462
482
 
463
 
        k._v = [frozenset(), frozenset([0])]
464
 
        k._l = [('{', 0),
 
483
        k._parents = [frozenset(), frozenset([0])]
 
484
        k._weave = [('{', 0),
465
485
                "first line",
466
486
                ('}', 0),
467
487
                ('{', 1),
475
495
        self.assertEqual(k.get(0),
476
496
                         ["first line"])
477
497
 
478
 
        k.dump(self.TEST_LOG)
479
 
 
480
498
 
481
499
class DivergedIncludes(TestBase):
482
500
    """Weave with two diverged texts based on version 0.
484
502
    def runTest(self):
485
503
        k = Weave()
486
504
 
487
 
        k._v = [frozenset(),
 
505
        k._parents = [frozenset(),
488
506
                frozenset([0]),
489
507
                frozenset([0]),
490
508
                ]
491
 
        k._l = [('{', 0),
 
509
        k._weave = [('{', 0),
492
510
                "first line",
493
511
                ('}', 0),
494
512
                ('{', 1),
510
528
                         ["first line",
511
529
                          "alternative second line"])
512
530
 
513
 
        self.assertEqual(k.inclusions([2]),
514
 
                         set([0, 2]))
 
531
        self.assertEqual(list(k.inclusions([2])),
 
532
                         [0, 2])
515
533
 
516
534
 
517
535
 
522
540
        text0 = ['cheddar', 'stilton', 'gruyere']
523
541
        text1 = ['cheddar', 'blue vein', 'neufchatel', 'chevre']
524
542
        
525
 
        k.add([], text0)
526
 
        k.add([0], text1)
 
543
        k.add('text0', [], text0)
 
544
        k.add('text1', [0], text1)
527
545
 
528
 
        self.log('k._l=' + pformat(k._l))
 
546
        self.log('k._weave=' + pformat(k._weave))
529
547
 
530
548
        self.assertEqual(k.get(0), text0)
531
549
        self.assertEqual(k.get(1), text1)
543
561
                 ['header', '', 'line from 1', 'fixup line', 'line from 2'],
544
562
                 ]
545
563
 
546
 
        k.add([], texts[0])
547
 
        k.add([0], texts[1])
548
 
        k.add([0], texts[2])
549
 
        k.add([0, 1, 2], texts[3])
 
564
        k.add('text0', [], texts[0])
 
565
        k.add('text1', [0], texts[1])
 
566
        k.add('text2', [0], texts[2])
 
567
        k.add('merge', [0, 1, 2], texts[3])
550
568
 
551
569
        for i, t in enumerate(texts):
552
570
            self.assertEqual(k.get(i), t)
559
577
                          (2, 'line from 2'),
560
578
                          ])
561
579
 
562
 
        self.assertEqual(k.inclusions([3]),
563
 
                         set([0, 1, 2, 3]))
 
580
        self.assertEqual(list(k.inclusions([3])),
 
581
                         [0, 1, 2, 3])
564
582
 
565
 
        self.log('k._l=' + pformat(k._l))
 
583
        self.log('k._weave=' + pformat(k._weave))
566
584
 
567
585
        self.check_read_write(k)
568
586
 
614
632
                 ['header', 'aaa', 'bbb', 'line from 2', 'more from 2'],
615
633
                 ]
616
634
 
617
 
        k.add([], texts[0])
618
 
        k.add([0], texts[1])
619
 
        k.add([0], texts[2])
 
635
        k.add('text0', [], texts[0])
 
636
        k.add('text1', [0], texts[1])
 
637
        k.add('text2', [0], texts[2])
620
638
 
621
 
        self.log('k._l=' + pformat(k._l))
 
639
        self.log('k._weave=' + pformat(k._weave))
622
640
 
623
641
        m = list(k.mash_iter([0, 1, 2]))
624
642
 
662
680
 
663
681
        k = Weave()
664
682
        parents = set()
 
683
        i = 0
665
684
        for t in texts:
666
 
            ver = k.add(list(parents), t)
 
685
            ver = k.add('text%d' % i,
 
686
                        list(parents), t)
667
687
            parents.add(ver)
 
688
            i += 1
668
689
 
669
 
        self.log("k._l=" + pformat(k._l))
 
690
        self.log("k._weave=" + pformat(k._weave))
670
691
 
671
692
        for i, t in enumerate(texts):
672
693
            self.assertEqual(k.get(i), t)
674
695
        self.check_read_write(k)
675
696
 
676
697
 
677
 
def testweave():
678
 
    import testsweet
679
 
    from unittest import TestSuite, TestLoader
680
 
    import testweave
681
 
 
682
 
    tl = TestLoader()
683
 
    suite = TestSuite()
684
 
    suite.addTest(tl.loadTestsFromModule(testweave))
685
 
    
686
 
    return int(not testsweet.run_suite(suite)) # for shell 0=true
 
698
 
 
699
class MergeCases(TestBase):
 
700
    def doMerge(self, base, a, b, mp):
 
701
        from cStringIO import StringIO
 
702
        from textwrap import dedent
 
703
 
 
704
        def addcrlf(x):
 
705
            return x + '\n'
 
706
        
 
707
        w = Weave()
 
708
        w.add('text0', [], map(addcrlf, base))
 
709
        w.add('text1', [0], map(addcrlf, a))
 
710
        w.add('text2', [0], map(addcrlf, b))
 
711
 
 
712
        self.log('weave is:')
 
713
        tmpf = StringIO()
 
714
        write_weave(w, tmpf)
 
715
        self.log(tmpf.getvalue())
 
716
 
 
717
        self.log('merge plan:')
 
718
        p = list(w.plan_merge(1, 2))
 
719
        for state, line in p:
 
720
            if line:
 
721
                self.log('%12s | %s' % (state, line[:-1]))
 
722
 
 
723
        self.log('merge:')
 
724
        mt = StringIO()
 
725
        mt.writelines(w.weave_merge(p))
 
726
        mt.seek(0)
 
727
        self.log(mt.getvalue())
 
728
 
 
729
        mp = map(addcrlf, mp)
 
730
        self.assertEqual(mt.readlines(), mp)
 
731
        
 
732
        
 
733
    def testOneInsert(self):
 
734
        self.doMerge([],
 
735
                     ['aa'],
 
736
                     [],
 
737
                     ['aa'])
 
738
 
 
739
    def testSeparateInserts(self):
 
740
        self.doMerge(['aaa', 'bbb', 'ccc'],
 
741
                     ['aaa', 'xxx', 'bbb', 'ccc'],
 
742
                     ['aaa', 'bbb', 'yyy', 'ccc'],
 
743
                     ['aaa', 'xxx', 'bbb', 'yyy', 'ccc'])
 
744
 
 
745
    def testSameInsert(self):
 
746
        self.doMerge(['aaa', 'bbb', 'ccc'],
 
747
                     ['aaa', 'xxx', 'bbb', 'ccc'],
 
748
                     ['aaa', 'xxx', 'bbb', 'yyy', 'ccc'],
 
749
                     ['aaa', 'xxx', 'bbb', 'yyy', 'ccc'])
 
750
 
 
751
    def testOverlappedInsert(self):
 
752
        self.doMerge(['aaa', 'bbb'],
 
753
                     ['aaa', 'xxx', 'yyy', 'bbb'],
 
754
                     ['aaa', 'xxx', 'bbb'],
 
755
                     ['aaa', '<<<<', 'xxx', 'yyy', '====', 'xxx', '>>>>', 'bbb'])
 
756
 
 
757
        # really it ought to reduce this to 
 
758
        # ['aaa', 'xxx', 'yyy', 'bbb']
 
759
 
 
760
 
 
761
    def testClashReplace(self):
 
762
        self.doMerge(['aaa'],
 
763
                     ['xxx'],
 
764
                     ['yyy', 'zzz'],
 
765
                     ['<<<<', 'xxx', '====', 'yyy', 'zzz', '>>>>'])
 
766
 
 
767
    def testNonClashInsert(self):
 
768
        self.doMerge(['aaa'],
 
769
                     ['xxx', 'aaa'],
 
770
                     ['yyy', 'zzz'],
 
771
                     ['<<<<', 'xxx', 'aaa', '====', 'yyy', 'zzz', '>>>>'])
 
772
 
 
773
        self.doMerge(['aaa'],
 
774
                     ['aaa'],
 
775
                     ['yyy', 'zzz'],
 
776
                     ['yyy', 'zzz'])
 
777
 
 
778
 
 
779
    def testDeleteAndModify(self):
 
780
        """Clashing delete and modification.
 
781
 
 
782
        If one side modifies a region and the other deletes it then
 
783
        there should be a conflict with one side blank.
 
784
        """
 
785
 
 
786
        #######################################
 
787
        # skippd, not working yet
 
788
        return
 
789
        
 
790
        self.doMerge(['aaa', 'bbb', 'ccc'],
 
791
                     ['aaa', 'ddd', 'ccc'],
 
792
                     ['aaa', 'ccc'],
 
793
                     ['<<<<', 'aaa', '====', '>>>>', 'ccc'])
 
794
 
 
795
 
 
796
class JoinWeavesTests(TestBase):
 
797
    def setUp(self):
 
798
        super(JoinWeavesTests, self).setUp()
 
799
        self.weave1 = Weave()
 
800
        self.lines1 = ['hello\n']
 
801
        self.lines3 = ['hello\n', 'cruel\n', 'world\n']
 
802
        self.weave1.add('v1', [], self.lines1)
 
803
        self.weave1.add('v2', [0], ['hello\n', 'world\n'])
 
804
        self.weave1.add('v3', [1], self.lines3)
 
805
        
 
806
    def test_join_empty(self):
 
807
        """Join two empty weaves."""
 
808
        eq = self.assertEqual
 
809
        w1 = Weave()
 
810
        w2 = Weave()
 
811
        w1.join(w2)
 
812
        eq(w1.numversions(), 0)
 
813
        
 
814
    def test_join_empty_to_nonempty(self):
 
815
        """Join empty weave onto nonempty."""
 
816
        self.weave1.join(Weave())
 
817
        self.assertEqual(len(self.weave1), 3)
 
818
 
 
819
    def test_join_unrelated(self):
 
820
        """Join two weaves with no history in common."""
 
821
        wb = Weave()
 
822
        wb.add('b1', [], ['line from b\n'])
 
823
        w1 = self.weave1
 
824
        w1.join(wb)
 
825
        eq = self.assertEqual
 
826
        eq(len(w1), 4)
 
827
        eq(sorted(list(w1.iter_names())),
 
828
           ['b1', 'v1', 'v2', 'v3'])
 
829
 
 
830
    def test_join_related(self):
 
831
        wa = self.weave1.copy()
 
832
        wb = self.weave1.copy()
 
833
        wa.add('a1', ['v3'], ['hello\n', 'sweet\n', 'world\n'])
 
834
        wb.add('b1', ['v3'], ['hello\n', 'pale blue\n', 'world\n'])
 
835
        eq = self.assertEquals
 
836
        eq(len(wa), 4)
 
837
        eq(len(wb), 4)
 
838
        wa.join(wb)
 
839
        eq(len(wa), 5)
 
840
        eq(wa.get_lines('b1'),
 
841
           ['hello\n', 'pale blue\n', 'world\n'])
 
842
 
 
843
    def test_join_parent_disagreement(self):
 
844
        """Cannot join weaves with different parents for a version."""
 
845
        wa = Weave()
 
846
        wb = Weave()
 
847
        wa.add('v1', [], ['hello\n'])
 
848
        wb.add('v0', [], [])
 
849
        wb.add('v1', ['v0'], ['hello\n'])
 
850
        self.assertRaises(WeaveError,
 
851
                          wa.join, wb)
 
852
 
 
853
    def test_join_text_disagreement(self):
 
854
        """Cannot join weaves with different texts for a version."""
 
855
        wa = Weave()
 
856
        wb = Weave()
 
857
        wa.add('v1', [], ['hello\n'])
 
858
        wb.add('v1', [], ['not\n', 'hello\n'])
 
859
        self.assertRaises(WeaveError,
 
860
                          wa.join, wb)
 
861
 
 
862
    def test_join_unordered(self):
 
863
        """Join weaves where indexes differ.
 
864
        
 
865
        The source weave contains a different version at index 0."""
 
866
        wa = self.weave1.copy()
 
867
        wb = Weave()
 
868
        wb.add('x1', [], ['line from x1\n'])
 
869
        wb.add('v1', [], ['hello\n'])
 
870
        wb.add('v2', ['v1'], ['hello\n', 'world\n'])
 
871
        wa.join(wb)
 
872
        eq = self.assertEquals
 
873
        eq(sorted(wa.iter_names()), ['v1', 'v2', 'v3', 'x1',])
 
874
        eq(wa.get_text('x1'), 'line from x1\n')
 
875
 
 
876
    def test_join_with_ghosts(self):
 
877
        """Join that inserts parents of an existing revision.
 
878
 
 
879
        This can happen when merging from another branch who
 
880
        knows about revisions the destination does not.  In 
 
881
        this test the second weave knows of an additional parent of 
 
882
        v2.  Any revisions which are in common still have to have the 
 
883
        same text."""
 
884
        return ###############################
 
885
        wa = self.weave1.copy()
 
886
        wb = Weave()
 
887
        wb.add('x1', [], ['line from x1\n'])
 
888
        wb.add('v1', [], ['hello\n'])
 
889
        wb.add('v2', ['v1', 'x1'], ['hello\n', 'world\n'])
 
890
        wa.join(wb)
 
891
        eq = self.assertEquals
 
892
        eq(sorted(wa.iter_names()), ['v1', 'v2', 'v3', 'x1',])
 
893
        eq(wa.get_text('x1'), 'line from x1\n')
687
894
 
688
895
 
689
896
if __name__ == '__main__':
690
897
    import sys
691
 
    sys.exit(testweave())
 
898
    import unittest
 
899
    sys.exit(unittest.main())
692
900