~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to tools/testweave.py

  • Committer: Martin Pool
  • Date: 2005-03-12 08:54:12 UTC
  • Revision ID: mbp@sourcefrog.net-20050312085412-13373aa129ccbad3
doc: notes on implementing codeville-style merge on
top of a weave; looks nice but opens a can of worms

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#! /usr/bin/python2.4
2
 
 
3
 
# Copyright (C) 2005 by Canonical Ltd
4
 
 
5
 
# This program is free software; you can redistribute it and/or modify
6
 
# it under the terms of the GNU General Public License as published by
7
 
# the Free Software Foundation; either version 2 of the License, or
8
 
# (at your option) any later version.
9
 
 
10
 
# This program is distributed in the hope that it will be useful,
11
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 
# GNU General Public License for more details.
14
 
 
15
 
# You should have received a copy of the GNU General Public License
16
 
# along with this program; if not, write to the Free Software
17
 
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
 
 
19
 
 
20
 
# TODO: tests regarding version names
21
 
 
22
 
 
23
 
 
24
 
"""test suite for weave algorithm"""
25
 
 
26
 
 
27
 
import testsweet
28
 
from bzrlib.weave import Weave, WeaveFormatError
29
 
from bzrlib.weavefile import write_weave, read_weave
30
 
from pprint import pformat
31
 
 
32
 
 
33
 
try:
34
 
    set
35
 
    frozenset
36
 
except NameError:
37
 
    from sets import Set, ImmutableSet
38
 
    set = Set
39
 
    frozenset = ImmutableSet
40
 
    del Set, ImmutableSet
41
 
 
42
 
 
43
 
 
44
 
# texts for use in testing
45
 
TEXT_0 = ["Hello world"]
46
 
TEXT_1 = ["Hello world",
47
 
          "A second line"]
48
 
 
49
 
 
50
 
 
51
 
class TestBase(testsweet.TestBase):
52
 
    def check_read_write(self, k):
53
 
        """Check the weave k can be written & re-read."""
54
 
        from tempfile import TemporaryFile
55
 
        tf = TemporaryFile()
56
 
 
57
 
        write_weave(k, tf)
58
 
        tf.seek(0)
59
 
        k2 = read_weave(tf)
60
 
 
61
 
        if k != k2:
62
 
            tf.seek(0)
63
 
            self.log('serialized weave:')
64
 
            self.log(tf.read())
65
 
 
66
 
            self.log('')
67
 
            self.log('parents: %s' % (k._parents == k2._parents))
68
 
            self.log('         %r' % k._parents)
69
 
            self.log('         %r' % k2._parents)
70
 
            self.log('')
71
 
 
72
 
            
73
 
            self.fail('read/write check failed')
74
 
        
75
 
        
76
 
 
77
 
 
78
 
class Easy(TestBase):
79
 
    def runTest(self):
80
 
        k = Weave()
81
 
 
82
 
 
83
 
class StoreText(TestBase):
84
 
    """Store and retrieve a simple text."""
85
 
    def runTest(self):
86
 
        k = Weave()
87
 
        idx = k.add('text0', [], TEXT_0)
88
 
        self.assertEqual(k.get(idx), TEXT_0)
89
 
        self.assertEqual(idx, 0)
90
 
 
91
 
 
92
 
 
93
 
class AnnotateOne(TestBase):
94
 
    def runTest(self):
95
 
        k = Weave()
96
 
        k.add('text0', [], TEXT_0)
97
 
        self.assertEqual(k.annotate(0),
98
 
                         [(0, TEXT_0[0])])
99
 
 
100
 
 
101
 
class StoreTwo(TestBase):
102
 
    def runTest(self):
103
 
        k = Weave()
104
 
 
105
 
        idx = k.add('text0', [], TEXT_0)
106
 
        self.assertEqual(idx, 0)
107
 
 
108
 
        idx = k.add('text1', [], TEXT_1)
109
 
        self.assertEqual(idx, 1)
110
 
 
111
 
        self.assertEqual(k.get(0), TEXT_0)
112
 
        self.assertEqual(k.get(1), TEXT_1)
113
 
 
114
 
        k.dump(self.TEST_LOG)
115
 
 
116
 
 
117
 
 
118
 
class InvalidAdd(TestBase):
119
 
    """Try to use invalid version number during add."""
120
 
    def runTest(self):
121
 
        k = Weave()
122
 
 
123
 
        self.assertRaises(IndexError,
124
 
                          k.add,
125
 
                          'text0',
126
 
                          [69],
127
 
                          ['new text!'])
128
 
 
129
 
 
130
 
class InsertLines(TestBase):
131
 
    """Store a revision that adds one line to the original.
132
 
 
133
 
    Look at the annotations to make sure that the first line is matched
134
 
    and not stored repeatedly."""
135
 
    def runTest(self):
136
 
        k = Weave()
137
 
 
138
 
        k.add('text0', [], ['line 1'])
139
 
        k.add('text1', [0], ['line 1', 'line 2'])
140
 
 
141
 
        self.assertEqual(k.annotate(0),
142
 
                         [(0, 'line 1')])
143
 
 
144
 
        self.assertEqual(k.get(1),
145
 
                         ['line 1',
146
 
                          'line 2'])
147
 
 
148
 
        self.assertEqual(k.annotate(1),
149
 
                         [(0, 'line 1'),
150
 
                          (1, 'line 2')])
151
 
 
152
 
        k.add('text2', [0], ['line 1', 'diverged line'])
153
 
 
154
 
        self.assertEqual(k.annotate(2),
155
 
                         [(0, 'line 1'),
156
 
                          (2, 'diverged line')])
157
 
 
158
 
        text3 = ['line 1', 'middle line', 'line 2']
159
 
        k.add('text3',
160
 
              [0, 1],
161
 
              text3)
162
 
 
163
 
        # self.log("changes to text3: " + pformat(list(k._delta(set([0, 1]), text3))))
164
 
 
165
 
        self.log("k._weave=" + pformat(k._weave))
166
 
 
167
 
        self.assertEqual(k.annotate(3),
168
 
                         [(0, 'line 1'),
169
 
                          (3, 'middle line'),
170
 
                          (1, 'line 2')])
171
 
 
172
 
        # now multiple insertions at different places
173
 
        k.add('text4',
174
 
              [0, 1, 3],
175
 
              ['line 1', 'aaa', 'middle line', 'bbb', 'line 2', 'ccc'])
176
 
 
177
 
        self.assertEqual(k.annotate(4), 
178
 
                         [(0, 'line 1'),
179
 
                          (4, 'aaa'),
180
 
                          (3, 'middle line'),
181
 
                          (4, 'bbb'),
182
 
                          (1, 'line 2'),
183
 
                          (4, 'ccc')])
184
 
 
185
 
 
186
 
 
187
 
class DeleteLines(TestBase):
188
 
    """Deletion of lines from existing text.
189
 
 
190
 
    Try various texts all based on a common ancestor."""
191
 
    def runTest(self):
192
 
        k = Weave()
193
 
 
194
 
        base_text = ['one', 'two', 'three', 'four']
195
 
 
196
 
        k.add('text0', [], base_text)
197
 
        
198
 
        texts = [['one', 'two', 'three'],
199
 
                 ['two', 'three', 'four'],
200
 
                 ['one', 'four'],
201
 
                 ['one', 'two', 'three', 'four'],
202
 
                 ]
203
 
 
204
 
        i = 1
205
 
        for t in texts:
206
 
            ver = k.add('text%d' % i,
207
 
                        [0], t)
208
 
            i += 1
209
 
 
210
 
        self.log('final weave:')
211
 
        self.log('k._weave=' + pformat(k._weave))
212
 
 
213
 
        for i in range(len(texts)):
214
 
            self.assertEqual(k.get(i+1),
215
 
                             texts[i])
216
 
            
217
 
 
218
 
 
219
 
 
220
 
class SuicideDelete(TestBase):
221
 
    """Invalid weave which tries to add and delete simultaneously."""
222
 
    def runTest(self):
223
 
        k = Weave()
224
 
 
225
 
        k._parents = [(),
226
 
                ]
227
 
        k._weave = [('{', 0),
228
 
                'first line',
229
 
                ('[', 0),
230
 
                'deleted in 0',
231
 
                (']', 0),
232
 
                ('}', 0),
233
 
                ]
234
 
        ################################### SKIPPED
235
 
        # Weave.get doesn't trap this anymore
236
 
        return 
237
 
 
238
 
        self.assertRaises(WeaveFormatError,
239
 
                          k.get,
240
 
                          0)        
241
 
 
242
 
 
243
 
 
244
 
class CannedDelete(TestBase):
245
 
    """Unpack canned weave with deleted lines."""
246
 
    def runTest(self):
247
 
        k = Weave()
248
 
 
249
 
        k._parents = [(),
250
 
                frozenset([0]),
251
 
                ]
252
 
        k._weave = [('{', 0),
253
 
                'first line',
254
 
                ('[', 1),
255
 
                'line to be deleted',
256
 
                (']', 1),
257
 
                'last line',
258
 
                ('}', 0),
259
 
                ]
260
 
 
261
 
        self.assertEqual(k.get(0),
262
 
                         ['first line',
263
 
                          'line to be deleted',
264
 
                          'last line',
265
 
                          ])
266
 
 
267
 
        self.assertEqual(k.get(1),
268
 
                         ['first line',
269
 
                          'last line',
270
 
                          ])
271
 
 
272
 
 
273
 
 
274
 
class CannedReplacement(TestBase):
275
 
    """Unpack canned weave with deleted lines."""
276
 
    def runTest(self):
277
 
        k = Weave()
278
 
 
279
 
        k._parents = [frozenset(),
280
 
                frozenset([0]),
281
 
                ]
282
 
        k._weave = [('{', 0),
283
 
                'first line',
284
 
                ('[', 1),
285
 
                'line to be deleted',
286
 
                (']', 1),
287
 
                ('{', 1),
288
 
                'replacement line',                
289
 
                ('}', 1),
290
 
                'last line',
291
 
                ('}', 0),
292
 
                ]
293
 
 
294
 
        self.assertEqual(k.get(0),
295
 
                         ['first line',
296
 
                          'line to be deleted',
297
 
                          'last line',
298
 
                          ])
299
 
 
300
 
        self.assertEqual(k.get(1),
301
 
                         ['first line',
302
 
                          'replacement line',
303
 
                          'last line',
304
 
                          ])
305
 
 
306
 
 
307
 
 
308
 
class BadWeave(TestBase):
309
 
    """Test that we trap an insert which should not occur."""
310
 
    def runTest(self):
311
 
        k = Weave()
312
 
 
313
 
        k._parents = [frozenset(),
314
 
                ]
315
 
        k._weave = ['bad line',
316
 
                ('{', 0),
317
 
                'foo {',
318
 
                ('{', 1),
319
 
                '  added in version 1',
320
 
                ('{', 2),
321
 
                '  added in v2',
322
 
                ('}', 2),
323
 
                '  also from v1',
324
 
                ('}', 1),
325
 
                '}',
326
 
                ('}', 0)]
327
 
 
328
 
        ################################### SKIPPED
329
 
        # Weave.get doesn't trap this anymore
330
 
        return 
331
 
 
332
 
 
333
 
        self.assertRaises(WeaveFormatError,
334
 
                          k.get,
335
 
                          0)
336
 
 
337
 
 
338
 
class BadInsert(TestBase):
339
 
    """Test that we trap an insert which should not occur."""
340
 
    def runTest(self):
341
 
        k = Weave()
342
 
 
343
 
        k._parents = [frozenset(),
344
 
                frozenset([0]),
345
 
                frozenset([0]),
346
 
                frozenset([0,1,2]),
347
 
                ]
348
 
        k._weave = [('{', 0),
349
 
                'foo {',
350
 
                ('{', 1),
351
 
                '  added in version 1',
352
 
                ('{', 1),
353
 
                '  more in 1',
354
 
                ('}', 1),
355
 
                ('}', 1),
356
 
                ('}', 0)]
357
 
 
358
 
 
359
 
        # this is not currently enforced by get
360
 
        return  ##########################################
361
 
 
362
 
        self.assertRaises(WeaveFormatError,
363
 
                          k.get,
364
 
                          0)
365
 
 
366
 
        self.assertRaises(WeaveFormatError,
367
 
                          k.get,
368
 
                          1)
369
 
 
370
 
 
371
 
class InsertNested(TestBase):
372
 
    """Insertion with nested instructions."""
373
 
    def runTest(self):
374
 
        k = Weave()
375
 
 
376
 
        k._parents = [frozenset(),
377
 
                frozenset([0]),
378
 
                frozenset([0]),
379
 
                frozenset([0,1,2]),
380
 
                ]
381
 
        k._weave = [('{', 0),
382
 
                'foo {',
383
 
                ('{', 1),
384
 
                '  added in version 1',
385
 
                ('{', 2),
386
 
                '  added in v2',
387
 
                ('}', 2),
388
 
                '  also from v1',
389
 
                ('}', 1),
390
 
                '}',
391
 
                ('}', 0)]
392
 
 
393
 
        self.assertEqual(k.get(0),
394
 
                         ['foo {',
395
 
                          '}'])
396
 
 
397
 
        self.assertEqual(k.get(1),
398
 
                         ['foo {',
399
 
                          '  added in version 1',
400
 
                          '  also from v1',
401
 
                          '}'])
402
 
                       
403
 
        self.assertEqual(k.get(2),
404
 
                         ['foo {',
405
 
                          '  added in v2',
406
 
                          '}'])
407
 
 
408
 
        self.assertEqual(k.get(3),
409
 
                         ['foo {',
410
 
                          '  added in version 1',
411
 
                          '  added in v2',
412
 
                          '  also from v1',
413
 
                          '}'])
414
 
                         
415
 
 
416
 
 
417
 
class DeleteLines2(TestBase):
418
 
    """Test recording revisions that delete lines.
419
 
 
420
 
    This relies on the weave having a way to represent lines knocked
421
 
    out by a later revision."""
422
 
    def runTest(self):
423
 
        k = Weave()
424
 
 
425
 
        k.add('text0', [], ["line the first",
426
 
                   "line 2",
427
 
                   "line 3",
428
 
                   "fine"])
429
 
 
430
 
        self.assertEqual(len(k.get(0)), 4)
431
 
 
432
 
        k.add('text1', [0], ["line the first",
433
 
                   "fine"])
434
 
 
435
 
        self.assertEqual(k.get(1),
436
 
                         ["line the first",
437
 
                          "fine"])
438
 
 
439
 
        self.assertEqual(k.annotate(1),
440
 
                         [(0, "line the first"),
441
 
                          (0, "fine")])
442
 
 
443
 
 
444
 
 
445
 
class IncludeVersions(TestBase):
446
 
    """Check texts that are stored across multiple revisions.
447
 
 
448
 
    Here we manually create a weave with particular encoding and make
449
 
    sure it unpacks properly.
450
 
 
451
 
    Text 0 includes nothing; text 1 includes text 0 and adds some
452
 
    lines.
453
 
    """
454
 
 
455
 
    def runTest(self):
456
 
        k = Weave()
457
 
 
458
 
        k._parents = [frozenset(), frozenset([0])]
459
 
        k._weave = [('{', 0),
460
 
                "first line",
461
 
                ('}', 0),
462
 
                ('{', 1),
463
 
                "second line",
464
 
                ('}', 1)]
465
 
 
466
 
        self.assertEqual(k.get(1),
467
 
                         ["first line",
468
 
                          "second line"])
469
 
 
470
 
        self.assertEqual(k.get(0),
471
 
                         ["first line"])
472
 
 
473
 
        k.dump(self.TEST_LOG)
474
 
 
475
 
 
476
 
class DivergedIncludes(TestBase):
477
 
    """Weave with two diverged texts based on version 0.
478
 
    """
479
 
    def runTest(self):
480
 
        k = Weave()
481
 
 
482
 
        k._parents = [frozenset(),
483
 
                frozenset([0]),
484
 
                frozenset([0]),
485
 
                ]
486
 
        k._weave = [('{', 0),
487
 
                "first line",
488
 
                ('}', 0),
489
 
                ('{', 1),
490
 
                "second line",
491
 
                ('}', 1),
492
 
                ('{', 2),
493
 
                "alternative second line",
494
 
                ('}', 2),                
495
 
                ]
496
 
 
497
 
        self.assertEqual(k.get(0),
498
 
                         ["first line"])
499
 
 
500
 
        self.assertEqual(k.get(1),
501
 
                         ["first line",
502
 
                          "second line"])
503
 
 
504
 
        self.assertEqual(k.get(2),
505
 
                         ["first line",
506
 
                          "alternative second line"])
507
 
 
508
 
        self.assertEqual(list(k.inclusions([2])),
509
 
                         [0, 2])
510
 
 
511
 
 
512
 
 
513
 
class ReplaceLine(TestBase):
514
 
    def runTest(self):
515
 
        k = Weave()
516
 
 
517
 
        text0 = ['cheddar', 'stilton', 'gruyere']
518
 
        text1 = ['cheddar', 'blue vein', 'neufchatel', 'chevre']
519
 
        
520
 
        k.add('text0', [], text0)
521
 
        k.add('text1', [0], text1)
522
 
 
523
 
        self.log('k._weave=' + pformat(k._weave))
524
 
 
525
 
        self.assertEqual(k.get(0), text0)
526
 
        self.assertEqual(k.get(1), text1)
527
 
 
528
 
 
529
 
 
530
 
class Merge(TestBase):
531
 
    """Storage of versions that merge diverged parents"""
532
 
    def runTest(self):
533
 
        k = Weave()
534
 
 
535
 
        texts = [['header'],
536
 
                 ['header', '', 'line from 1'],
537
 
                 ['header', '', 'line from 2', 'more from 2'],
538
 
                 ['header', '', 'line from 1', 'fixup line', 'line from 2'],
539
 
                 ]
540
 
 
541
 
        k.add('text0', [], texts[0])
542
 
        k.add('text1', [0], texts[1])
543
 
        k.add('text2', [0], texts[2])
544
 
        k.add('merge', [0, 1, 2], texts[3])
545
 
 
546
 
        for i, t in enumerate(texts):
547
 
            self.assertEqual(k.get(i), t)
548
 
 
549
 
        self.assertEqual(k.annotate(3),
550
 
                         [(0, 'header'),
551
 
                          (1, ''),
552
 
                          (1, 'line from 1'),
553
 
                          (3, 'fixup line'),
554
 
                          (2, 'line from 2'),
555
 
                          ])
556
 
 
557
 
        self.assertEqual(list(k.inclusions([3])),
558
 
                         [0, 1, 2, 3])
559
 
 
560
 
        self.log('k._weave=' + pformat(k._weave))
561
 
 
562
 
        self.check_read_write(k)
563
 
 
564
 
 
565
 
class Conflicts(TestBase):
566
 
    """Test detection of conflicting regions during a merge.
567
 
 
568
 
    A base version is inserted, then two descendents try to
569
 
    insert different lines in the same place.  These should be
570
 
    reported as a possible conflict and forwarded to the user."""
571
 
    def runTest(self):
572
 
        return  # NOT RUN
573
 
        k = Weave()
574
 
 
575
 
        k.add([], ['aaa', 'bbb'])
576
 
        k.add([0], ['aaa', '111', 'bbb'])
577
 
        k.add([1], ['aaa', '222', 'bbb'])
578
 
 
579
 
        merged = k.merge([1, 2])
580
 
 
581
 
        self.assertEquals([[['aaa']],
582
 
                           [['111'], ['222']],
583
 
                           [['bbb']]])
584
 
 
585
 
 
586
 
 
587
 
class NonConflict(TestBase):
588
 
    """Two descendants insert compatible changes.
589
 
 
590
 
    No conflict should be reported."""
591
 
    def runTest(self):
592
 
        return  # NOT RUN
593
 
        k = Weave()
594
 
 
595
 
        k.add([], ['aaa', 'bbb'])
596
 
        k.add([0], ['111', 'aaa', 'ccc', 'bbb'])
597
 
        k.add([1], ['aaa', 'ccc', 'bbb', '222'])
598
 
 
599
 
    
600
 
    
601
 
 
602
 
 
603
 
class AutoMerge(TestBase):
604
 
    def runTest(self):
605
 
        k = Weave()
606
 
 
607
 
        texts = [['header', 'aaa', 'bbb'],
608
 
                 ['header', 'aaa', 'line from 1', 'bbb'],
609
 
                 ['header', 'aaa', 'bbb', 'line from 2', 'more from 2'],
610
 
                 ]
611
 
 
612
 
        k.add('text0', [], texts[0])
613
 
        k.add('text1', [0], texts[1])
614
 
        k.add('text2', [0], texts[2])
615
 
 
616
 
        self.log('k._weave=' + pformat(k._weave))
617
 
 
618
 
        m = list(k.mash_iter([0, 1, 2]))
619
 
 
620
 
        self.assertEqual(m,
621
 
                         ['header', 'aaa',
622
 
                          'line from 1',
623
 
                          'bbb',
624
 
                          'line from 2', 'more from 2'])
625
 
        
626
 
 
627
 
 
628
 
class Khayyam(TestBase):
629
 
    """Test changes to multi-line texts, and read/write"""
630
 
    def runTest(self):
631
 
        rawtexts = [
632
 
            """A Book of Verses underneath the Bough,
633
 
            A Jug of Wine, a Loaf of Bread, -- and Thou
634
 
            Beside me singing in the Wilderness --
635
 
            Oh, Wilderness were Paradise enow!""",
636
 
            
637
 
            """A Book of Verses underneath the Bough,
638
 
            A Jug of Wine, a Loaf of Bread, -- and Thou
639
 
            Beside me singing in the Wilderness --
640
 
            Oh, Wilderness were Paradise now!""",
641
 
 
642
 
            """A Book of poems underneath the tree,
643
 
            A Jug of Wine, a Loaf of Bread,
644
 
            and Thou
645
 
            Beside me singing in the Wilderness --
646
 
            Oh, Wilderness were Paradise now!
647
 
 
648
 
            -- O. Khayyam""",
649
 
 
650
 
            """A Book of Verses underneath the Bough,
651
 
            A Jug of Wine, a Loaf of Bread,
652
 
            and Thou
653
 
            Beside me singing in the Wilderness --
654
 
            Oh, Wilderness were Paradise now!""",
655
 
            ]
656
 
        texts = [[l.strip() for l in t.split('\n')] for t in rawtexts]
657
 
 
658
 
        k = Weave()
659
 
        parents = set()
660
 
        i = 0
661
 
        for t in texts:
662
 
            ver = k.add('text%d' % i,
663
 
                        list(parents), t)
664
 
            parents.add(ver)
665
 
            i += 1
666
 
 
667
 
        self.log("k._weave=" + pformat(k._weave))
668
 
 
669
 
        for i, t in enumerate(texts):
670
 
            self.assertEqual(k.get(i), t)
671
 
 
672
 
        self.check_read_write(k)
673
 
 
674
 
 
675
 
 
676
 
class MergeCases(TestBase):
677
 
    def doMerge(self, base, a, b, mp):
678
 
        from cStringIO import StringIO
679
 
        from textwrap import dedent
680
 
 
681
 
        def addcrlf(x):
682
 
            return x + '\n'
683
 
        
684
 
        w = Weave()
685
 
        w.add('text0', [], map(addcrlf, base))
686
 
        w.add('text1', [0], map(addcrlf, a))
687
 
        w.add('text2', [0], map(addcrlf, b))
688
 
 
689
 
        self.log('weave is:')
690
 
        tmpf = StringIO()
691
 
        write_weave(w, tmpf)
692
 
        self.log(tmpf.getvalue())
693
 
 
694
 
        self.log('merge plan:')
695
 
        p = list(w.plan_merge(1, 2))
696
 
        for state, line in p:
697
 
            if line:
698
 
                self.log('%12s | %s' % (state, line[:-1]))
699
 
 
700
 
        self.log('merge:')
701
 
        mt = StringIO()
702
 
        mt.writelines(w.weave_merge(p))
703
 
        mt.seek(0)
704
 
        self.log(mt.getvalue())
705
 
 
706
 
        mp = map(addcrlf, mp)
707
 
        self.assertEqual(mt.readlines(), mp)
708
 
        
709
 
        
710
 
    def testOneInsert(self):
711
 
        self.doMerge([],
712
 
                     ['aa'],
713
 
                     [],
714
 
                     ['aa'])
715
 
 
716
 
    def testSeparateInserts(self):
717
 
        self.doMerge(['aaa', 'bbb', 'ccc'],
718
 
                     ['aaa', 'xxx', 'bbb', 'ccc'],
719
 
                     ['aaa', 'bbb', 'yyy', 'ccc'],
720
 
                     ['aaa', 'xxx', 'bbb', 'yyy', 'ccc'])
721
 
 
722
 
    def testSameInsert(self):
723
 
        self.doMerge(['aaa', 'bbb', 'ccc'],
724
 
                     ['aaa', 'xxx', 'bbb', 'ccc'],
725
 
                     ['aaa', 'xxx', 'bbb', 'yyy', 'ccc'],
726
 
                     ['aaa', 'xxx', 'bbb', 'yyy', 'ccc'])
727
 
 
728
 
    def testOverlappedInsert(self):
729
 
        self.doMerge(['aaa', 'bbb'],
730
 
                     ['aaa', 'xxx', 'yyy', 'bbb'],
731
 
                     ['aaa', 'xxx', 'bbb'],
732
 
                     ['aaa', '<<<<', 'xxx', 'yyy', '====', 'xxx', '>>>>', 'bbb'])
733
 
 
734
 
        # really it ought to reduce this to 
735
 
        # ['aaa', 'xxx', 'yyy', 'bbb']
736
 
 
737
 
 
738
 
    def testClashReplace(self):
739
 
        self.doMerge(['aaa'],
740
 
                     ['xxx'],
741
 
                     ['yyy', 'zzz'],
742
 
                     ['<<<<', 'xxx', '====', 'yyy', 'zzz', '>>>>'])
743
 
 
744
 
    def testNonClashInsert(self):
745
 
        self.doMerge(['aaa'],
746
 
                     ['xxx', 'aaa'],
747
 
                     ['yyy', 'zzz'],
748
 
                     ['<<<<', 'xxx', 'aaa', '====', 'yyy', 'zzz', '>>>>'])
749
 
 
750
 
        self.doMerge(['aaa'],
751
 
                     ['aaa'],
752
 
                     ['yyy', 'zzz'],
753
 
                     ['yyy', 'zzz'])
754
 
 
755
 
 
756
 
    def testDeleteAndModify(self):
757
 
        """Clashing delete and modification.
758
 
 
759
 
        If one side modifies a region and the other deletes it then
760
 
        there should be a conflict with one side blank.
761
 
        """
762
 
 
763
 
        #######################################
764
 
        # skippd, not working yet
765
 
        return
766
 
        
767
 
        self.doMerge(['aaa', 'bbb', 'ccc'],
768
 
                     ['aaa', 'ddd', 'ccc'],
769
 
                     ['aaa', 'ccc'],
770
 
                     ['<<<<', 'aaa', '====', '>>>>', 'ccc'])
771
 
    
772
 
 
773
 
 
774
 
def testweave():
775
 
    import testsweet
776
 
    from unittest import TestSuite, TestLoader
777
 
    import testweave
778
 
 
779
 
    tl = TestLoader()
780
 
    suite = TestSuite()
781
 
    suite.addTest(tl.loadTestsFromModule(testweave))
782
 
    
783
 
    return int(not testsweet.run_suite(suite)) # for shell 0=true
784
 
 
785
 
 
786
 
if __name__ == '__main__':
787
 
    import sys
788
 
    sys.exit(testweave())
789