/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to tools/testweave.py

  • Committer: Martin Pool
  • Date: 2005-07-18 11:23:40 UTC
  • Revision ID: mbp@sourcefrog.net-20050718112340-4ffbfa3624bb6ef3
- weavebench should set random seed to make it reproducible

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