~bzr-pqm/bzr/bzr.dev

0.1.55 by Martin Pool
doc
1
#! /usr/bin/python2.4
2
0.1.2 by Martin Pool
Import testsweet module adapted from bzr.
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
0.1.38 by Martin Pool
Rename knit to weave. (I don't think there's an existing module called weave.)
22
"""test suite for weave algorithm"""
0.1.2 by Martin Pool
Import testsweet module adapted from bzr.
23
24
0.1.75 by Martin Pool
Remove VerInfo class; just store sets directly in the list of
25
import testsweet
872 by Martin Pool
- update testweave
26
from bzrlib.weave import Weave, WeaveFormatError
27
from bzrlib.weavefile import write_weave, read_weave
0.1.57 by Martin Pool
Fix bug in an update edit that both deletes and inserts -- previously
28
from pprint import pformat
0.1.2 by Martin Pool
Import testsweet module adapted from bzr.
29
0.1.66 by Martin Pool
Cope without set/frozenset classes
30
31
try:
32
    set
33
    frozenset
34
except NameError:
35
    from sets import Set, ImmutableSet
36
    set = Set
37
    frozenset = ImmutableSet
0.1.67 by Martin Pool
More fixes to try to run on python2.3
38
    del Set, ImmutableSet
0.1.66 by Martin Pool
Cope without set/frozenset classes
39
40
41
0.1.2 by Martin Pool
Import testsweet module adapted from bzr.
42
# texts for use in testing
0.1.3 by Martin Pool
Change storage of texts for testing
43
TEXT_0 = ["Hello world"]
44
TEXT_1 = ["Hello world",
45
          "A second line"]
0.1.2 by Martin Pool
Import testsweet module adapted from bzr.
46
47
0.1.75 by Martin Pool
Remove VerInfo class; just store sets directly in the list of
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
0.1.2 by Martin Pool
Import testsweet module adapted from bzr.
68
class Easy(TestBase):
69
    def runTest(self):
0.1.38 by Martin Pool
Rename knit to weave. (I don't think there's an existing module called weave.)
70
        k = Weave()
0.1.2 by Martin Pool
Import testsweet module adapted from bzr.
71
72
73
class StoreText(TestBase):
74
    """Store and retrieve a simple text."""
75
    def runTest(self):
0.1.38 by Martin Pool
Rename knit to weave. (I don't think there's an existing module called weave.)
76
        k = Weave()
0.1.26 by Martin Pool
Refactor parameters to add command
77
        idx = k.add([], TEXT_0)
0.1.4 by Martin Pool
Start indexing knits by both integer and version string.
78
        self.assertEqual(k.get(idx), TEXT_0)
79
        self.assertEqual(idx, 0)
0.1.2 by Martin Pool
Import testsweet module adapted from bzr.
80
81
0.1.7 by Martin Pool
Add trivial annotate text
82
83
class AnnotateOne(TestBase):
84
    def runTest(self):
0.1.38 by Martin Pool
Rename knit to weave. (I don't think there's an existing module called weave.)
85
        k = Weave()
0.1.26 by Martin Pool
Refactor parameters to add command
86
        k.add([], TEXT_0)
0.1.7 by Martin Pool
Add trivial annotate text
87
        self.assertEqual(k.annotate(0),
88
                         [(0, TEXT_0[0])])
89
90
0.1.5 by Martin Pool
Add test for storing two text versions.
91
class StoreTwo(TestBase):
92
    def runTest(self):
0.1.38 by Martin Pool
Rename knit to weave. (I don't think there's an existing module called weave.)
93
        k = Weave()
0.1.5 by Martin Pool
Add test for storing two text versions.
94
0.1.26 by Martin Pool
Refactor parameters to add command
95
        idx = k.add([], TEXT_0)
0.1.5 by Martin Pool
Add test for storing two text versions.
96
        self.assertEqual(idx, 0)
97
0.1.26 by Martin Pool
Refactor parameters to add command
98
        idx = k.add([], TEXT_1)
0.1.5 by Martin Pool
Add test for storing two text versions.
99
        self.assertEqual(idx, 1)
100
101
        self.assertEqual(k.get(0), TEXT_0)
102
        self.assertEqual(k.get(1), TEXT_1)
103
0.1.13 by Martin Pool
Knit structure now allows for versions to include the lines present in other
104
        k.dump(self.TEST_LOG)
105
106
0.1.21 by Martin Pool
Start computing a delta to insert a new revision
107
0.1.27 by Martin Pool
Check that version numbers passed in are reasonable
108
class InvalidAdd(TestBase):
109
    """Try to use invalid version number during add."""
110
    def runTest(self):
0.1.38 by Martin Pool
Rename knit to weave. (I don't think there's an existing module called weave.)
111
        k = Weave()
0.1.27 by Martin Pool
Check that version numbers passed in are reasonable
112
937 by Martin Pool
- weave raises IndexError when an invalid revision is given
113
        self.assertRaises(IndexError,
0.1.27 by Martin Pool
Check that version numbers passed in are reasonable
114
                          k.add,
115
                          [69],
116
                          ['new text!'])
117
118
0.1.26 by Martin Pool
Refactor parameters to add command
119
class InsertLines(TestBase):
0.1.13 by Martin Pool
Knit structure now allows for versions to include the lines present in other
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):
0.1.38 by Martin Pool
Rename knit to weave. (I don't think there's an existing module called weave.)
125
        k = Weave()
0.1.13 by Martin Pool
Knit structure now allows for versions to include the lines present in other
126
0.1.26 by Martin Pool
Refactor parameters to add command
127
        k.add([], ['line 1'])
128
        k.add([0], ['line 1', 'line 2'])
0.1.13 by Martin Pool
Knit structure now allows for versions to include the lines present in other
129
130
        self.assertEqual(k.annotate(0),
131
                         [(0, 'line 1')])
132
0.1.25 by Martin Pool
Handle insertion of new weave layers that insert text on top of the basis
133
        self.assertEqual(k.get(1),
134
                         ['line 1',
135
                          'line 2'])
136
0.1.13 by Martin Pool
Knit structure now allows for versions to include the lines present in other
137
        self.assertEqual(k.annotate(1),
138
                         [(0, 'line 1'),
139
                          (1, 'line 2')])
140
0.1.28 by Martin Pool
More tests for insertion of lines in new versions.
141
        k.add([0], ['line 1', 'diverged line'])
142
143
        self.assertEqual(k.annotate(2),
144
                         [(0, 'line 1'),
145
                          (2, 'diverged line')])
146
0.1.54 by Martin Pool
Fix weave line calculation when making deltas
147
        text3 = ['line 1', 'middle line', 'line 2']
0.1.28 by Martin Pool
More tests for insertion of lines in new versions.
148
        k.add([0, 1],
0.1.54 by Martin Pool
Fix weave line calculation when making deltas
149
              text3)
150
937 by Martin Pool
- weave raises IndexError when an invalid revision is given
151
        # self.log("changes to text3: " + pformat(list(k._delta(set([0, 1]), text3))))
0.1.54 by Martin Pool
Fix weave line calculation when making deltas
152
944 by Martin Pool
- refactor member names in Weave code
153
        self.log("k._weave=" + pformat(k._weave))
0.1.28 by Martin Pool
More tests for insertion of lines in new versions.
154
155
        self.assertEqual(k.annotate(3),
156
                         [(0, 'line 1'),
157
                          (3, 'middle line'),
158
                          (1, 'line 2')])
159
0.1.31 by Martin Pool
Fix insertion of multiple regions, calculating the right line offset as we go.
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')])
0.1.13 by Martin Pool
Knit structure now allows for versions to include the lines present in other
171
0.1.40 by Martin Pool
Add test for extracting from weave with nested insertions
172
0.1.48 by Martin Pool
Basic parsing of delete instructions.
173
0.1.56 by Martin Pool
Handle deletion of lines by marking the region with a deletion
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:')
944 by Martin Pool
- refactor member names in Weave code
195
        self.log('k._weave=' + pformat(k._weave))
0.1.56 by Martin Pool
Handle deletion of lines by marking the region with a deletion
196
197
        for i in range(len(texts)):
198
            self.assertEqual(k.get(i+1),
199
                             texts[i])
200
            
201
202
203
0.1.49 by Martin Pool
Add another constraint: revisions should not delete text that they
204
class SuicideDelete(TestBase):
0.1.55 by Martin Pool
doc
205
    """Invalid weave which tries to add and delete simultaneously."""
0.1.49 by Martin Pool
Add another constraint: revisions should not delete text that they
206
    def runTest(self):
207
        k = Weave()
208
944 by Martin Pool
- refactor member names in Weave code
209
        k._parents = [(),
0.1.49 by Martin Pool
Add another constraint: revisions should not delete text that they
210
                ]
944 by Martin Pool
- refactor member names in Weave code
211
        k._weave = [('{', 0),
0.1.49 by Martin Pool
Add another constraint: revisions should not delete text that they
212
                'first line',
213
                ('[', 0),
214
                'deleted in 0',
215
                (']', 0),
216
                ('}', 0),
217
                ]
891 by Martin Pool
- fix up refactoring of weave
218
        ################################### SKIPPED
219
        # Weave.get doesn't trap this anymore
220
        return 
0.1.49 by Martin Pool
Add another constraint: revisions should not delete text that they
221
222
        self.assertRaises(WeaveFormatError,
223
                          k.get,
224
                          0)        
225
226
227
0.1.48 by Martin Pool
Basic parsing of delete instructions.
228
class CannedDelete(TestBase):
229
    """Unpack canned weave with deleted lines."""
230
    def runTest(self):
231
        k = Weave()
232
944 by Martin Pool
- refactor member names in Weave code
233
        k._parents = [(),
0.1.75 by Martin Pool
Remove VerInfo class; just store sets directly in the list of
234
                frozenset([0]),
0.1.48 by Martin Pool
Basic parsing of delete instructions.
235
                ]
944 by Martin Pool
- refactor member names in Weave code
236
        k._weave = [('{', 0),
0.1.48 by Martin Pool
Basic parsing of delete instructions.
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
0.1.50 by Martin Pool
Basic implementation of deletion markers
251
        self.assertEqual(k.get(1),
252
                         ['first line',
253
                          'last line',
254
                          ])
255
0.1.48 by Martin Pool
Basic parsing of delete instructions.
256
257
0.1.51 by Martin Pool
Add test for replacement lines
258
class CannedReplacement(TestBase):
259
    """Unpack canned weave with deleted lines."""
260
    def runTest(self):
261
        k = Weave()
262
944 by Martin Pool
- refactor member names in Weave code
263
        k._parents = [frozenset(),
0.1.75 by Martin Pool
Remove VerInfo class; just store sets directly in the list of
264
                frozenset([0]),
0.1.51 by Martin Pool
Add test for replacement lines
265
                ]
944 by Martin Pool
- refactor member names in Weave code
266
        k._weave = [('{', 0),
0.1.51 by Martin Pool
Add test for replacement lines
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
0.1.46 by Martin Pool
More constraints on structure of weave, and checks that they work
292
class BadWeave(TestBase):
293
    """Test that we trap an insert which should not occur."""
294
    def runTest(self):
295
        k = Weave()
296
944 by Martin Pool
- refactor member names in Weave code
297
        k._parents = [frozenset(),
0.1.46 by Martin Pool
More constraints on structure of weave, and checks that they work
298
                ]
944 by Martin Pool
- refactor member names in Weave code
299
        k._weave = ['bad line',
0.1.46 by Martin Pool
More constraints on structure of weave, and checks that they work
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
891 by Martin Pool
- fix up refactoring of weave
312
        ################################### SKIPPED
313
        # Weave.get doesn't trap this anymore
314
        return 
315
316
0.1.47 by Martin Pool
New WeaveError and WeaveFormatError rather than assertions.
317
        self.assertRaises(WeaveFormatError,
0.1.46 by Martin Pool
More constraints on structure of weave, and checks that they work
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
944 by Martin Pool
- refactor member names in Weave code
327
        k._parents = [frozenset(),
0.1.75 by Martin Pool
Remove VerInfo class; just store sets directly in the list of
328
                frozenset([0]),
329
                frozenset([0]),
330
                frozenset([0,1,2]),
0.1.46 by Martin Pool
More constraints on structure of weave, and checks that they work
331
                ]
944 by Martin Pool
- refactor member names in Weave code
332
        k._weave = [('{', 0),
0.1.46 by Martin Pool
More constraints on structure of weave, and checks that they work
333
                'foo {',
334
                ('{', 1),
335
                '  added in version 1',
336
                ('{', 1),
337
                '  more in 1',
338
                ('}', 1),
339
                ('}', 1),
340
                ('}', 0)]
341
891 by Martin Pool
- fix up refactoring of weave
342
343
        # this is not currently enforced by get
344
        return  ##########################################
345
0.1.47 by Martin Pool
New WeaveError and WeaveFormatError rather than assertions.
346
        self.assertRaises(WeaveFormatError,
0.1.46 by Martin Pool
More constraints on structure of weave, and checks that they work
347
                          k.get,
348
                          0)
349
0.1.47 by Martin Pool
New WeaveError and WeaveFormatError rather than assertions.
350
        self.assertRaises(WeaveFormatError,
0.1.46 by Martin Pool
More constraints on structure of weave, and checks that they work
351
                          k.get,
352
                          1)
353
0.1.40 by Martin Pool
Add test for extracting from weave with nested insertions
354
355
class InsertNested(TestBase):
356
    """Insertion with nested instructions."""
357
    def runTest(self):
358
        k = Weave()
359
944 by Martin Pool
- refactor member names in Weave code
360
        k._parents = [frozenset(),
0.1.75 by Martin Pool
Remove VerInfo class; just store sets directly in the list of
361
                frozenset([0]),
362
                frozenset([0]),
363
                frozenset([0,1,2]),
0.1.40 by Martin Pool
Add test for extracting from weave with nested insertions
364
                ]
944 by Martin Pool
- refactor member names in Weave code
365
        k._weave = [('{', 0),
0.1.40 by Martin Pool
Add test for extracting from weave with nested insertions
366
                'foo {',
367
                ('{', 1),
368
                '  added in version 1',
0.1.42 by Martin Pool
More tests for nested insert instructions
369
                ('{', 2),
370
                '  added in v2',
371
                ('}', 2),
372
                '  also from v1',
0.1.40 by Martin Pool
Add test for extracting from weave with nested insertions
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',
0.1.42 by Martin Pool
More tests for nested insert instructions
384
                          '  also from v1',
0.1.40 by Martin Pool
Add test for extracting from weave with nested insertions
385
                          '}'])
386
                       
0.1.44 by Martin Pool
More tests for nested insert instructions
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
                         
0.1.45 by Martin Pool
doc
399
0.1.40 by Martin Pool
Add test for extracting from weave with nested insertions
400
0.1.56 by Martin Pool
Handle deletion of lines by marking the region with a deletion
401
class DeleteLines2(TestBase):
0.1.30 by Martin Pool
Start adding tests for line deletion
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):
0.1.38 by Martin Pool
Rename knit to weave. (I don't think there's an existing module called weave.)
407
        k = Weave()
0.1.30 by Martin Pool
Start adding tests for line deletion
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
0.1.56 by Martin Pool
Handle deletion of lines by marking the region with a deletion
423
        self.assertEqual(k.annotate(1),
424
                         [(0, "line the first"),
425
                          (0, "fine")])
426
0.1.30 by Martin Pool
Start adding tests for line deletion
427
0.1.26 by Martin Pool
Refactor parameters to add command
428
0.1.13 by Martin Pool
Knit structure now allows for versions to include the lines present in other
429
class IncludeVersions(TestBase):
430
    """Check texts that are stored across multiple revisions.
431
0.1.38 by Martin Pool
Rename knit to weave. (I don't think there's an existing module called weave.)
432
    Here we manually create a weave with particular encoding and make
0.1.13 by Martin Pool
Knit structure now allows for versions to include the lines present in other
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):
0.1.38 by Martin Pool
Rename knit to weave. (I don't think there's an existing module called weave.)
440
        k = Weave()
0.1.13 by Martin Pool
Knit structure now allows for versions to include the lines present in other
441
944 by Martin Pool
- refactor member names in Weave code
442
        k._parents = [frozenset(), frozenset([0])]
443
        k._weave = [('{', 0),
0.1.39 by Martin Pool
Change to a more realistic weave structure which can represent insertions and
444
                "first line",
445
                ('}', 0),
446
                ('{', 1),
447
                "second line",
448
                ('}', 1)]
0.1.13 by Martin Pool
Knit structure now allows for versions to include the lines present in other
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
0.1.5 by Martin Pool
Add test for storing two text versions.
459
0.1.14 by Martin Pool
Another test for version inclusion
460
class DivergedIncludes(TestBase):
0.1.38 by Martin Pool
Rename knit to weave. (I don't think there's an existing module called weave.)
461
    """Weave with two diverged texts based on version 0.
0.1.14 by Martin Pool
Another test for version inclusion
462
    """
463
    def runTest(self):
0.1.38 by Martin Pool
Rename knit to weave. (I don't think there's an existing module called weave.)
464
        k = Weave()
0.1.14 by Martin Pool
Another test for version inclusion
465
944 by Martin Pool
- refactor member names in Weave code
466
        k._parents = [frozenset(),
0.1.75 by Martin Pool
Remove VerInfo class; just store sets directly in the list of
467
                frozenset([0]),
468
                frozenset([0]),
0.1.17 by Martin Pool
Use objects rather than tuples for tracking VerInfo for
469
                ]
944 by Martin Pool
- refactor member names in Weave code
470
        k._weave = [('{', 0),
0.1.39 by Martin Pool
Change to a more realistic weave structure which can represent insertions and
471
                "first line",
472
                ('}', 0),
473
                ('{', 1),
474
                "second line",
475
                ('}', 1),
476
                ('{', 2),
477
                "alternative second line",
478
                ('}', 2),                
479
                ]
0.1.14 by Martin Pool
Another test for version inclusion
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
924 by Martin Pool
- Add IntSet class
492
        self.assertEqual(list(k.inclusions([2])),
493
                         [0, 2])
0.1.77 by Martin Pool
New Weave.get_included() does transitive expansion
494
0.1.57 by Martin Pool
Fix bug in an update edit that both deletes and inserts -- previously
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
944 by Martin Pool
- refactor member names in Weave code
507
        self.log('k._weave=' + pformat(k._weave))
0.1.57 by Martin Pool
Fix bug in an update edit that both deletes and inserts -- previously
508
0.1.59 by Martin Pool
More modification tests
509
        self.assertEqual(k.get(0), text0)
0.1.57 by Martin Pool
Fix bug in an update edit that both deletes and inserts -- previously
510
        self.assertEqual(k.get(1), text1)
511
0.1.64 by Martin Pool
Add test for merging versions
512
513
514
class Merge(TestBase):
0.1.95 by Martin Pool
- preliminary merge conflict detection
515
    """Storage of versions that merge diverged parents"""
0.1.64 by Martin Pool
Add test for merging versions
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
924 by Martin Pool
- Add IntSet class
541
        self.assertEqual(list(k.inclusions([3])),
542
                         [0, 1, 2, 3])
0.1.77 by Martin Pool
New Weave.get_included() does transitive expansion
543
944 by Martin Pool
- refactor member names in Weave code
544
        self.log('k._weave=' + pformat(k._weave))
0.1.64 by Martin Pool
Add test for merging versions
545
0.1.75 by Martin Pool
Remove VerInfo class; just store sets directly in the list of
546
        self.check_read_write(k)
0.1.65 by Martin Pool
Add Weave.merge_iter to get automerged lines
547
548
0.1.95 by Martin Pool
- preliminary merge conflict detection
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
0.1.65 by Martin Pool
Add Weave.merge_iter to get automerged lines
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
944 by Martin Pool
- refactor member names in Weave code
600
        self.log('k._weave=' + pformat(k._weave))
0.1.65 by Martin Pool
Add Weave.merge_iter to get automerged lines
601
0.1.95 by Martin Pool
- preliminary merge conflict detection
602
        m = list(k.mash_iter([0, 1, 2]))
0.1.65 by Martin Pool
Add Weave.merge_iter to get automerged lines
603
604
        self.assertEqual(m,
605
                         ['header', 'aaa',
606
                          'line from 1',
607
                          'bbb',
608
                          'line from 2', 'more from 2'])
0.1.57 by Martin Pool
Fix bug in an update edit that both deletes and inserts -- previously
609
        
610
611
612
class Khayyam(TestBase):
0.1.75 by Martin Pool
Remove VerInfo class; just store sets directly in the list of
613
    """Test changes to multi-line texts, and read/write"""
0.1.57 by Martin Pool
Fix bug in an update edit that both deletes and inserts -- previously
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!""",
0.1.59 by Martin Pool
More modification tests
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 --
0.1.75 by Martin Pool
Remove VerInfo class; just store sets directly in the list of
638
            Oh, Wilderness were Paradise now!""",
0.1.57 by Martin Pool
Fix bug in an update edit that both deletes and inserts -- previously
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:
0.1.78 by Martin Pool
Rename Weave.get_included to inclusions and getiter to get_iter
645
            ver = k.add(list(parents), t)
0.1.57 by Martin Pool
Fix bug in an update edit that both deletes and inserts -- previously
646
            parents.add(ver)
647
944 by Martin Pool
- refactor member names in Weave code
648
        self.log("k._weave=" + pformat(k._weave))
0.1.59 by Martin Pool
More modification tests
649
0.1.57 by Martin Pool
Fix bug in an update edit that both deletes and inserts -- previously
650
        for i, t in enumerate(texts):
0.1.75 by Martin Pool
Remove VerInfo class; just store sets directly in the list of
651
            self.assertEqual(k.get(i), t)
0.1.57 by Martin Pool
Fix bug in an update edit that both deletes and inserts -- previously
652
0.1.75 by Martin Pool
Remove VerInfo class; just store sets directly in the list of
653
        self.check_read_write(k)
0.1.57 by Martin Pool
Fix bug in an update edit that both deletes and inserts -- previously
654
655
920 by Martin Pool
- add more test cases for weave_merge
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
935 by Martin Pool
- log weave for merge tests to help debugging
670
        self.log('weave is:')
671
        tmpf = StringIO()
672
        write_weave(w, tmpf)
673
        self.log(tmpf.getvalue())
674
920 by Martin Pool
- add more test cases for weave_merge
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
0.1.38 by Martin Pool
Rename knit to weave. (I don't think there's an existing module called weave.)
738
def testweave():
0.1.2 by Martin Pool
Import testsweet module adapted from bzr.
739
    import testsweet
740
    from unittest import TestSuite, TestLoader
0.1.38 by Martin Pool
Rename knit to weave. (I don't think there's an existing module called weave.)
741
    import testweave
0.1.57 by Martin Pool
Fix bug in an update edit that both deletes and inserts -- previously
742
 
0.1.2 by Martin Pool
Import testsweet module adapted from bzr.
743
    tl = TestLoader()
744
    suite = TestSuite()
0.1.38 by Martin Pool
Rename knit to weave. (I don't think there's an existing module called weave.)
745
    suite.addTest(tl.loadTestsFromModule(testweave))
0.1.2 by Martin Pool
Import testsweet module adapted from bzr.
746
    
0.1.15 by Martin Pool
Fix inverted shell return code for testknit
747
    return int(not testsweet.run_suite(suite)) # for shell 0=true
0.1.2 by Martin Pool
Import testsweet module adapted from bzr.
748
749
750
if __name__ == '__main__':
751
    import sys
0.1.38 by Martin Pool
Rename knit to weave. (I don't think there's an existing module called weave.)
752
    sys.exit(testweave())
0.1.2 by Martin Pool
Import testsweet module adapted from bzr.
753