~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/selftest/test_weave.py

  • Committer: mbp at sourcefrog
  • Date: 2005-04-05 08:24:51 UTC
  • Revision ID: mbp@sourcefrog.net-20050405082451-408ebb0fd108440f
start adding quotes

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