~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to tools/testweave.py

  • Committer: Aaron Bentley
  • Date: 2005-07-26 14:06:11 UTC
  • mto: (1092.1.41) (1185.3.4) (974.1.47)
  • mto: This revision was merged to the branch mainline in revision 982.
  • Revision ID: abentley@panoramicfeedback.com-20050726140611-403e366f3c79c1f1
Fixed python invocation

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