~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
30
0.1.66 by Martin Pool
Cope without set/frozenset classes
31
32
try:
33
    set
34
    frozenset
35
except NameError:
36
    from sets import Set, ImmutableSet
37
    set = Set
38
    frozenset = ImmutableSet
0.1.67 by Martin Pool
More fixes to try to run on python2.3
39
    del Set, ImmutableSet
0.1.66 by Martin Pool
Cope without set/frozenset classes
40
41
42
0.1.2 by Martin Pool
Import testsweet module adapted from bzr.
43
# texts for use in testing
0.1.3 by Martin Pool
Change storage of texts for testing
44
TEXT_0 = ["Hello world"]
45
TEXT_1 = ["Hello world",
46
          "A second line"]
0.1.2 by Martin Pool
Import testsweet module adapted from bzr.
47
48
0.1.75 by Martin Pool
Remove VerInfo class; just store sets directly in the list of
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
0.1.2 by Martin Pool
Import testsweet module adapted from bzr.
69
class Easy(TestBase):
70
    def runTest(self):
0.1.38 by Martin Pool
Rename knit to weave. (I don't think there's an existing module called weave.)
71
        k = Weave()
0.1.2 by Martin Pool
Import testsweet module adapted from bzr.
72
73
74
class StoreText(TestBase):
75
    """Store and retrieve a simple text."""
76
    def runTest(self):
0.1.38 by Martin Pool
Rename knit to weave. (I don't think there's an existing module called weave.)
77
        k = Weave()
0.1.26 by Martin Pool
Refactor parameters to add command
78
        idx = k.add([], TEXT_0)
0.1.4 by Martin Pool
Start indexing knits by both integer and version string.
79
        self.assertEqual(k.get(idx), TEXT_0)
80
        self.assertEqual(idx, 0)
0.1.2 by Martin Pool
Import testsweet module adapted from bzr.
81
82
0.1.7 by Martin Pool
Add trivial annotate text
83
84
class AnnotateOne(TestBase):
85
    def runTest(self):
0.1.38 by Martin Pool
Rename knit to weave. (I don't think there's an existing module called weave.)
86
        k = Weave()
0.1.26 by Martin Pool
Refactor parameters to add command
87
        k.add([], TEXT_0)
0.1.7 by Martin Pool
Add trivial annotate text
88
        self.assertEqual(k.annotate(0),
89
                         [(0, TEXT_0[0])])
90
91
0.1.5 by Martin Pool
Add test for storing two text versions.
92
class StoreTwo(TestBase):
93
    def runTest(self):
0.1.38 by Martin Pool
Rename knit to weave. (I don't think there's an existing module called weave.)
94
        k = Weave()
0.1.5 by Martin Pool
Add test for storing two text versions.
95
0.1.26 by Martin Pool
Refactor parameters to add command
96
        idx = k.add([], TEXT_0)
0.1.5 by Martin Pool
Add test for storing two text versions.
97
        self.assertEqual(idx, 0)
98
0.1.26 by Martin Pool
Refactor parameters to add command
99
        idx = k.add([], TEXT_1)
0.1.5 by Martin Pool
Add test for storing two text versions.
100
        self.assertEqual(idx, 1)
101
102
        self.assertEqual(k.get(0), TEXT_0)
103
        self.assertEqual(k.get(1), TEXT_1)
104
0.1.13 by Martin Pool
Knit structure now allows for versions to include the lines present in other
105
        k.dump(self.TEST_LOG)
106
107
0.1.21 by Martin Pool
Start computing a delta to insert a new revision
108
0.1.55 by Martin Pool
doc
109
class DeltaAdd(TestBase):
0.1.21 by Martin Pool
Start computing a delta to insert a new revision
110
    """Detection of changes prior to inserting new revision."""
111
    def runTest(self):
0.1.38 by Martin Pool
Rename knit to weave. (I don't think there's an existing module called weave.)
112
        k = Weave()
0.1.26 by Martin Pool
Refactor parameters to add command
113
        k.add([], ['line 1'])
0.1.21 by Martin Pool
Start computing a delta to insert a new revision
114
0.1.52 by Martin Pool
Update tests for new weave representation
115
        self.assertEqual(k._l,
116
                         [('{', 0),
117
                          'line 1',
118
                          ('}', 0),
119
                          ])
120
0.1.22 by Martin Pool
Calculate delta for new versions relative to a set of parent versions.
121
        changes = list(k._delta(set([0]),
122
                                ['line 1',
123
                                 'new line']))
0.1.21 by Martin Pool
Start computing a delta to insert a new revision
124
125
        self.log('raw changes: ' + pformat(changes))
126
0.1.52 by Martin Pool
Update tests for new weave representation
127
        # currently there are 3 lines in the weave, and we insert after them
0.1.22 by Martin Pool
Calculate delta for new versions relative to a set of parent versions.
128
        self.assertEquals(changes,
0.1.52 by Martin Pool
Update tests for new weave representation
129
                          [(3, 3, ['new line'])])
0.1.22 by Martin Pool
Calculate delta for new versions relative to a set of parent versions.
130
0.1.24 by Martin Pool
Add another change for delta of new version.
131
        changes = k._delta(set([0]),
132
                           ['top line',
133
                            'line 1'])
134
        
135
        self.assertEquals(list(changes),
0.1.54 by Martin Pool
Fix weave line calculation when making deltas
136
                          [(1, 1, ['top line'])])
0.1.24 by Martin Pool
Add another change for delta of new version.
137
0.1.75 by Martin Pool
Remove VerInfo class; just store sets directly in the list of
138
        self.check_read_write(k)
0.1.24 by Martin Pool
Add another change for delta of new version.
139
0.1.21 by Martin Pool
Start computing a delta to insert a new revision
140
0.1.27 by Martin Pool
Check that version numbers passed in are reasonable
141
class InvalidAdd(TestBase):
142
    """Try to use invalid version number during add."""
143
    def runTest(self):
0.1.38 by Martin Pool
Rename knit to weave. (I don't think there's an existing module called weave.)
144
        k = Weave()
0.1.27 by Martin Pool
Check that version numbers passed in are reasonable
145
872 by Martin Pool
- update testweave
146
        self.assertRaises(ValueError,
0.1.27 by Martin Pool
Check that version numbers passed in are reasonable
147
                          k.add,
148
                          [69],
149
                          ['new text!'])
150
151
0.1.26 by Martin Pool
Refactor parameters to add command
152
class InsertLines(TestBase):
0.1.13 by Martin Pool
Knit structure now allows for versions to include the lines present in other
153
    """Store a revision that adds one line to the original.
154
155
    Look at the annotations to make sure that the first line is matched
156
    and not stored repeatedly."""
157
    def runTest(self):
0.1.38 by Martin Pool
Rename knit to weave. (I don't think there's an existing module called weave.)
158
        k = Weave()
0.1.13 by Martin Pool
Knit structure now allows for versions to include the lines present in other
159
0.1.26 by Martin Pool
Refactor parameters to add command
160
        k.add([], ['line 1'])
161
        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
162
163
        self.assertEqual(k.annotate(0),
164
                         [(0, 'line 1')])
165
0.1.25 by Martin Pool
Handle insertion of new weave layers that insert text on top of the basis
166
        self.assertEqual(k.get(1),
167
                         ['line 1',
168
                          'line 2'])
169
0.1.13 by Martin Pool
Knit structure now allows for versions to include the lines present in other
170
        self.assertEqual(k.annotate(1),
171
                         [(0, 'line 1'),
172
                          (1, 'line 2')])
173
0.1.28 by Martin Pool
More tests for insertion of lines in new versions.
174
        k.add([0], ['line 1', 'diverged line'])
175
176
        self.assertEqual(k.annotate(2),
177
                         [(0, 'line 1'),
178
                          (2, 'diverged line')])
179
0.1.54 by Martin Pool
Fix weave line calculation when making deltas
180
        text3 = ['line 1', 'middle line', 'line 2']
0.1.28 by Martin Pool
More tests for insertion of lines in new versions.
181
        k.add([0, 1],
0.1.54 by Martin Pool
Fix weave line calculation when making deltas
182
              text3)
183
184
        self.log("changes to text3: " + pformat(list(k._delta(set([0, 1]), text3))))
185
186
        self.log("k._l=" + pformat(k._l))
0.1.28 by Martin Pool
More tests for insertion of lines in new versions.
187
188
        self.assertEqual(k.annotate(3),
189
                         [(0, 'line 1'),
190
                          (3, 'middle line'),
191
                          (1, 'line 2')])
192
0.1.31 by Martin Pool
Fix insertion of multiple regions, calculating the right line offset as we go.
193
        # now multiple insertions at different places
194
        k.add([0, 1, 3],
195
              ['line 1', 'aaa', 'middle line', 'bbb', 'line 2', 'ccc'])
196
197
        self.assertEqual(k.annotate(4), 
198
                         [(0, 'line 1'),
199
                          (4, 'aaa'),
200
                          (3, 'middle line'),
201
                          (4, 'bbb'),
202
                          (1, 'line 2'),
203
                          (4, 'ccc')])
0.1.13 by Martin Pool
Knit structure now allows for versions to include the lines present in other
204
0.1.40 by Martin Pool
Add test for extracting from weave with nested insertions
205
0.1.48 by Martin Pool
Basic parsing of delete instructions.
206
0.1.56 by Martin Pool
Handle deletion of lines by marking the region with a deletion
207
class DeleteLines(TestBase):
208
    """Deletion of lines from existing text.
209
210
    Try various texts all based on a common ancestor."""
211
    def runTest(self):
212
        k = Weave()
213
214
        base_text = ['one', 'two', 'three', 'four']
215
216
        k.add([], base_text)
217
        
218
        texts = [['one', 'two', 'three'],
219
                 ['two', 'three', 'four'],
220
                 ['one', 'four'],
221
                 ['one', 'two', 'three', 'four'],
222
                 ]
223
224
        for t in texts:
225
            ver = k.add([0], t)
226
227
        self.log('final weave:')
228
        self.log('k._l=' + pformat(k._l))
229
230
        for i in range(len(texts)):
231
            self.assertEqual(k.get(i+1),
232
                             texts[i])
233
            
234
235
236
0.1.49 by Martin Pool
Add another constraint: revisions should not delete text that they
237
class SuicideDelete(TestBase):
0.1.55 by Martin Pool
doc
238
    """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
239
    def runTest(self):
240
        k = Weave()
241
0.1.75 by Martin Pool
Remove VerInfo class; just store sets directly in the list of
242
        k._v = [(),
0.1.49 by Martin Pool
Add another constraint: revisions should not delete text that they
243
                ]
244
        k._l = [('{', 0),
245
                'first line',
246
                ('[', 0),
247
                'deleted in 0',
248
                (']', 0),
249
                ('}', 0),
250
                ]
891 by Martin Pool
- fix up refactoring of weave
251
        ################################### SKIPPED
252
        # Weave.get doesn't trap this anymore
253
        return 
0.1.49 by Martin Pool
Add another constraint: revisions should not delete text that they
254
255
        self.assertRaises(WeaveFormatError,
256
                          k.get,
257
                          0)        
258
259
260
0.1.48 by Martin Pool
Basic parsing of delete instructions.
261
class CannedDelete(TestBase):
262
    """Unpack canned weave with deleted lines."""
263
    def runTest(self):
264
        k = Weave()
265
0.1.75 by Martin Pool
Remove VerInfo class; just store sets directly in the list of
266
        k._v = [(),
267
                frozenset([0]),
0.1.48 by Martin Pool
Basic parsing of delete instructions.
268
                ]
269
        k._l = [('{', 0),
270
                'first line',
271
                ('[', 1),
272
                'line to be deleted',
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
0.1.50 by Martin Pool
Basic implementation of deletion markers
284
        self.assertEqual(k.get(1),
285
                         ['first line',
286
                          'last line',
287
                          ])
288
0.1.48 by Martin Pool
Basic parsing of delete instructions.
289
290
0.1.51 by Martin Pool
Add test for replacement lines
291
class CannedReplacement(TestBase):
292
    """Unpack canned weave with deleted lines."""
293
    def runTest(self):
294
        k = Weave()
295
0.1.75 by Martin Pool
Remove VerInfo class; just store sets directly in the list of
296
        k._v = [frozenset(),
297
                frozenset([0]),
0.1.51 by Martin Pool
Add test for replacement lines
298
                ]
299
        k._l = [('{', 0),
300
                'first line',
301
                ('[', 1),
302
                'line to be deleted',
303
                (']', 1),
304
                ('{', 1),
305
                'replacement line',                
306
                ('}', 1),
307
                'last line',
308
                ('}', 0),
309
                ]
310
311
        self.assertEqual(k.get(0),
312
                         ['first line',
313
                          'line to be deleted',
314
                          'last line',
315
                          ])
316
317
        self.assertEqual(k.get(1),
318
                         ['first line',
319
                          'replacement line',
320
                          'last line',
321
                          ])
322
323
324
0.1.46 by Martin Pool
More constraints on structure of weave, and checks that they work
325
class BadWeave(TestBase):
326
    """Test that we trap an insert which should not occur."""
327
    def runTest(self):
328
        k = Weave()
329
0.1.75 by Martin Pool
Remove VerInfo class; just store sets directly in the list of
330
        k._v = [frozenset(),
0.1.46 by Martin Pool
More constraints on structure of weave, and checks that they work
331
                ]
332
        k._l = ['bad line',
333
                ('{', 0),
334
                'foo {',
335
                ('{', 1),
336
                '  added in version 1',
337
                ('{', 2),
338
                '  added in v2',
339
                ('}', 2),
340
                '  also from v1',
341
                ('}', 1),
342
                '}',
343
                ('}', 0)]
344
891 by Martin Pool
- fix up refactoring of weave
345
        ################################### SKIPPED
346
        # Weave.get doesn't trap this anymore
347
        return 
348
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
                          0)
353
354
355
class BadInsert(TestBase):
356
    """Test that we trap an insert which should not occur."""
357
    def runTest(self):
358
        k = Weave()
359
0.1.75 by Martin Pool
Remove VerInfo class; just store sets directly in the list of
360
        k._v = [frozenset(),
361
                frozenset([0]),
362
                frozenset([0]),
363
                frozenset([0,1,2]),
0.1.46 by Martin Pool
More constraints on structure of weave, and checks that they work
364
                ]
365
        k._l = [('{', 0),
366
                'foo {',
367
                ('{', 1),
368
                '  added in version 1',
369
                ('{', 1),
370
                '  more in 1',
371
                ('}', 1),
372
                ('}', 1),
373
                ('}', 0)]
374
891 by Martin Pool
- fix up refactoring of weave
375
376
        # this is not currently enforced by get
377
        return  ##########################################
378
0.1.47 by Martin Pool
New WeaveError and WeaveFormatError rather than assertions.
379
        self.assertRaises(WeaveFormatError,
0.1.46 by Martin Pool
More constraints on structure of weave, and checks that they work
380
                          k.get,
381
                          0)
382
0.1.47 by Martin Pool
New WeaveError and WeaveFormatError rather than assertions.
383
        self.assertRaises(WeaveFormatError,
0.1.46 by Martin Pool
More constraints on structure of weave, and checks that they work
384
                          k.get,
385
                          1)
386
0.1.40 by Martin Pool
Add test for extracting from weave with nested insertions
387
388
class InsertNested(TestBase):
389
    """Insertion with nested instructions."""
390
    def runTest(self):
391
        k = Weave()
392
0.1.75 by Martin Pool
Remove VerInfo class; just store sets directly in the list of
393
        k._v = [frozenset(),
394
                frozenset([0]),
395
                frozenset([0]),
396
                frozenset([0,1,2]),
0.1.40 by Martin Pool
Add test for extracting from weave with nested insertions
397
                ]
398
        k._l = [('{', 0),
399
                'foo {',
400
                ('{', 1),
401
                '  added in version 1',
0.1.42 by Martin Pool
More tests for nested insert instructions
402
                ('{', 2),
403
                '  added in v2',
404
                ('}', 2),
405
                '  also from v1',
0.1.40 by Martin Pool
Add test for extracting from weave with nested insertions
406
                ('}', 1),
407
                '}',
408
                ('}', 0)]
409
410
        self.assertEqual(k.get(0),
411
                         ['foo {',
412
                          '}'])
413
414
        self.assertEqual(k.get(1),
415
                         ['foo {',
416
                          '  added in version 1',
0.1.42 by Martin Pool
More tests for nested insert instructions
417
                          '  also from v1',
0.1.40 by Martin Pool
Add test for extracting from weave with nested insertions
418
                          '}'])
419
                       
0.1.44 by Martin Pool
More tests for nested insert instructions
420
        self.assertEqual(k.get(2),
421
                         ['foo {',
422
                          '  added in v2',
423
                          '}'])
424
425
        self.assertEqual(k.get(3),
426
                         ['foo {',
427
                          '  added in version 1',
428
                          '  added in v2',
429
                          '  also from v1',
430
                          '}'])
431
                         
0.1.45 by Martin Pool
doc
432
0.1.40 by Martin Pool
Add test for extracting from weave with nested insertions
433
0.1.56 by Martin Pool
Handle deletion of lines by marking the region with a deletion
434
class DeleteLines2(TestBase):
0.1.30 by Martin Pool
Start adding tests for line deletion
435
    """Test recording revisions that delete lines.
436
437
    This relies on the weave having a way to represent lines knocked
438
    out by a later revision."""
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.30 by Martin Pool
Start adding tests for line deletion
441
442
        k.add([], ["line the first",
443
                   "line 2",
444
                   "line 3",
445
                   "fine"])
446
447
        self.assertEqual(len(k.get(0)), 4)
448
449
        k.add([0], ["line the first",
450
                   "fine"])
451
452
        self.assertEqual(k.get(1),
453
                         ["line the first",
454
                          "fine"])
455
0.1.56 by Martin Pool
Handle deletion of lines by marking the region with a deletion
456
        self.assertEqual(k.annotate(1),
457
                         [(0, "line the first"),
458
                          (0, "fine")])
459
0.1.30 by Martin Pool
Start adding tests for line deletion
460
0.1.26 by Martin Pool
Refactor parameters to add command
461
0.1.13 by Martin Pool
Knit structure now allows for versions to include the lines present in other
462
class IncludeVersions(TestBase):
463
    """Check texts that are stored across multiple revisions.
464
0.1.38 by Martin Pool
Rename knit to weave. (I don't think there's an existing module called weave.)
465
    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
466
    sure it unpacks properly.
467
468
    Text 0 includes nothing; text 1 includes text 0 and adds some
469
    lines.
470
    """
471
472
    def runTest(self):
0.1.38 by Martin Pool
Rename knit to weave. (I don't think there's an existing module called weave.)
473
        k = Weave()
0.1.13 by Martin Pool
Knit structure now allows for versions to include the lines present in other
474
0.1.75 by Martin Pool
Remove VerInfo class; just store sets directly in the list of
475
        k._v = [frozenset(), frozenset([0])]
0.1.39 by Martin Pool
Change to a more realistic weave structure which can represent insertions and
476
        k._l = [('{', 0),
477
                "first line",
478
                ('}', 0),
479
                ('{', 1),
480
                "second line",
481
                ('}', 1)]
0.1.13 by Martin Pool
Knit structure now allows for versions to include the lines present in other
482
483
        self.assertEqual(k.get(1),
484
                         ["first line",
485
                          "second line"])
486
487
        self.assertEqual(k.get(0),
488
                         ["first line"])
489
490
        k.dump(self.TEST_LOG)
491
0.1.5 by Martin Pool
Add test for storing two text versions.
492
0.1.14 by Martin Pool
Another test for version inclusion
493
class DivergedIncludes(TestBase):
0.1.38 by Martin Pool
Rename knit to weave. (I don't think there's an existing module called weave.)
494
    """Weave with two diverged texts based on version 0.
0.1.14 by Martin Pool
Another test for version inclusion
495
    """
496
    def runTest(self):
0.1.38 by Martin Pool
Rename knit to weave. (I don't think there's an existing module called weave.)
497
        k = Weave()
0.1.14 by Martin Pool
Another test for version inclusion
498
0.1.75 by Martin Pool
Remove VerInfo class; just store sets directly in the list of
499
        k._v = [frozenset(),
500
                frozenset([0]),
501
                frozenset([0]),
0.1.17 by Martin Pool
Use objects rather than tuples for tracking VerInfo for
502
                ]
0.1.39 by Martin Pool
Change to a more realistic weave structure which can represent insertions and
503
        k._l = [('{', 0),
504
                "first line",
505
                ('}', 0),
506
                ('{', 1),
507
                "second line",
508
                ('}', 1),
509
                ('{', 2),
510
                "alternative second line",
511
                ('}', 2),                
512
                ]
0.1.14 by Martin Pool
Another test for version inclusion
513
514
        self.assertEqual(k.get(0),
515
                         ["first line"])
516
517
        self.assertEqual(k.get(1),
518
                         ["first line",
519
                          "second line"])
520
521
        self.assertEqual(k.get(2),
522
                         ["first line",
523
                          "alternative second line"])
524
0.1.78 by Martin Pool
Rename Weave.get_included to inclusions and getiter to get_iter
525
        self.assertEqual(k.inclusions([2]),
0.1.77 by Martin Pool
New Weave.get_included() does transitive expansion
526
                         set([0, 2]))
527
0.1.57 by Martin Pool
Fix bug in an update edit that both deletes and inserts -- previously
528
529
530
class ReplaceLine(TestBase):
531
    def runTest(self):
532
        k = Weave()
533
534
        text0 = ['cheddar', 'stilton', 'gruyere']
535
        text1 = ['cheddar', 'blue vein', 'neufchatel', 'chevre']
536
        
537
        k.add([], text0)
538
        k.add([0], text1)
539
540
        self.log('k._l=' + pformat(k._l))
541
0.1.59 by Martin Pool
More modification tests
542
        self.assertEqual(k.get(0), text0)
0.1.57 by Martin Pool
Fix bug in an update edit that both deletes and inserts -- previously
543
        self.assertEqual(k.get(1), text1)
544
0.1.64 by Martin Pool
Add test for merging versions
545
546
547
class Merge(TestBase):
0.1.95 by Martin Pool
- preliminary merge conflict detection
548
    """Storage of versions that merge diverged parents"""
0.1.64 by Martin Pool
Add test for merging versions
549
    def runTest(self):
550
        k = Weave()
551
552
        texts = [['header'],
553
                 ['header', '', 'line from 1'],
554
                 ['header', '', 'line from 2', 'more from 2'],
555
                 ['header', '', 'line from 1', 'fixup line', 'line from 2'],
556
                 ]
557
558
        k.add([], texts[0])
559
        k.add([0], texts[1])
560
        k.add([0], texts[2])
561
        k.add([0, 1, 2], texts[3])
562
563
        for i, t in enumerate(texts):
564
            self.assertEqual(k.get(i), t)
565
566
        self.assertEqual(k.annotate(3),
567
                         [(0, 'header'),
568
                          (1, ''),
569
                          (1, 'line from 1'),
570
                          (3, 'fixup line'),
571
                          (2, 'line from 2'),
572
                          ])
573
0.1.78 by Martin Pool
Rename Weave.get_included to inclusions and getiter to get_iter
574
        self.assertEqual(k.inclusions([3]),
0.1.77 by Martin Pool
New Weave.get_included() does transitive expansion
575
                         set([0, 1, 2, 3]))
576
0.1.64 by Martin Pool
Add test for merging versions
577
        self.log('k._l=' + pformat(k._l))
578
0.1.75 by Martin Pool
Remove VerInfo class; just store sets directly in the list of
579
        self.check_read_write(k)
0.1.65 by Martin Pool
Add Weave.merge_iter to get automerged lines
580
581
0.1.95 by Martin Pool
- preliminary merge conflict detection
582
class Conflicts(TestBase):
583
    """Test detection of conflicting regions during a merge.
584
585
    A base version is inserted, then two descendents try to
586
    insert different lines in the same place.  These should be
587
    reported as a possible conflict and forwarded to the user."""
588
    def runTest(self):
589
        return  # NOT RUN
590
        k = Weave()
591
592
        k.add([], ['aaa', 'bbb'])
593
        k.add([0], ['aaa', '111', 'bbb'])
594
        k.add([1], ['aaa', '222', 'bbb'])
595
596
        merged = k.merge([1, 2])
597
598
        self.assertEquals([[['aaa']],
599
                           [['111'], ['222']],
600
                           [['bbb']]])
601
602
603
604
class NonConflict(TestBase):
605
    """Two descendants insert compatible changes.
606
607
    No conflict should be reported."""
608
    def runTest(self):
609
        return  # NOT RUN
610
        k = Weave()
611
612
        k.add([], ['aaa', 'bbb'])
613
        k.add([0], ['111', 'aaa', 'ccc', 'bbb'])
614
        k.add([1], ['aaa', 'ccc', 'bbb', '222'])
615
616
    
617
    
618
619
0.1.65 by Martin Pool
Add Weave.merge_iter to get automerged lines
620
class AutoMerge(TestBase):
621
    def runTest(self):
622
        k = Weave()
623
624
        texts = [['header', 'aaa', 'bbb'],
625
                 ['header', 'aaa', 'line from 1', 'bbb'],
626
                 ['header', 'aaa', 'bbb', 'line from 2', 'more from 2'],
627
                 ]
628
629
        k.add([], texts[0])
630
        k.add([0], texts[1])
631
        k.add([0], texts[2])
632
633
        self.log('k._l=' + pformat(k._l))
634
0.1.95 by Martin Pool
- preliminary merge conflict detection
635
        m = list(k.mash_iter([0, 1, 2]))
0.1.65 by Martin Pool
Add Weave.merge_iter to get automerged lines
636
637
        self.assertEqual(m,
638
                         ['header', 'aaa',
639
                          'line from 1',
640
                          'bbb',
641
                          'line from 2', 'more from 2'])
0.1.57 by Martin Pool
Fix bug in an update edit that both deletes and inserts -- previously
642
        
643
644
645
class Khayyam(TestBase):
0.1.75 by Martin Pool
Remove VerInfo class; just store sets directly in the list of
646
    """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
647
    def runTest(self):
648
        rawtexts = [
649
            """A Book of Verses underneath the Bough,
650
            A Jug of Wine, a Loaf of Bread, -- and Thou
651
            Beside me singing in the Wilderness --
652
            Oh, Wilderness were Paradise enow!""",
653
            
654
            """A Book of Verses underneath the Bough,
655
            A Jug of Wine, a Loaf of Bread, -- and Thou
656
            Beside me singing in the Wilderness --
657
            Oh, Wilderness were Paradise now!""",
0.1.59 by Martin Pool
More modification tests
658
659
            """A Book of poems underneath the tree,
660
            A Jug of Wine, a Loaf of Bread,
661
            and Thou
662
            Beside me singing in the Wilderness --
663
            Oh, Wilderness were Paradise now!
664
665
            -- O. Khayyam""",
666
667
            """A Book of Verses underneath the Bough,
668
            A Jug of Wine, a Loaf of Bread,
669
            and Thou
670
            Beside me singing in the Wilderness --
0.1.75 by Martin Pool
Remove VerInfo class; just store sets directly in the list of
671
            Oh, Wilderness were Paradise now!""",
0.1.57 by Martin Pool
Fix bug in an update edit that both deletes and inserts -- previously
672
            ]
673
        texts = [[l.strip() for l in t.split('\n')] for t in rawtexts]
674
675
        k = Weave()
676
        parents = set()
677
        for t in texts:
0.1.78 by Martin Pool
Rename Weave.get_included to inclusions and getiter to get_iter
678
            ver = k.add(list(parents), t)
0.1.57 by Martin Pool
Fix bug in an update edit that both deletes and inserts -- previously
679
            parents.add(ver)
680
0.1.59 by Martin Pool
More modification tests
681
        self.log("k._l=" + pformat(k._l))
682
0.1.57 by Martin Pool
Fix bug in an update edit that both deletes and inserts -- previously
683
        for i, t in enumerate(texts):
0.1.75 by Martin Pool
Remove VerInfo class; just store sets directly in the list of
684
            self.assertEqual(k.get(i), t)
0.1.57 by Martin Pool
Fix bug in an update edit that both deletes and inserts -- previously
685
0.1.75 by Martin Pool
Remove VerInfo class; just store sets directly in the list of
686
        self.check_read_write(k)
0.1.57 by Martin Pool
Fix bug in an update edit that both deletes and inserts -- previously
687
688
920 by Martin Pool
- add more test cases for weave_merge
689
690
class MergeCases(TestBase):
691
    def doMerge(self, base, a, b, mp):
692
        from cStringIO import StringIO
693
        from textwrap import dedent
694
695
        def addcrlf(x):
696
            return x + '\n'
697
        
698
        w = Weave()
699
        w.add([], map(addcrlf, base))
700
        w.add([0], map(addcrlf, a))
701
        w.add([0], map(addcrlf, b))
702
703
        self.log('merge plan:')
704
        p = list(w.plan_merge(1, 2))
705
        for state, line in p:
706
            if line:
707
                self.log('%12s | %s' % (state, line[:-1]))
708
709
        self.log('merge:')
710
        mt = StringIO()
711
        mt.writelines(w.weave_merge(p))
712
        mt.seek(0)
713
        self.log(mt.getvalue())
714
715
        mp = map(addcrlf, mp)
716
        self.assertEqual(mt.readlines(), mp)
717
        
718
        
719
    def testOneInsert(self):
720
        self.doMerge([],
721
                     ['aa'],
722
                     [],
723
                     ['aa'])
724
725
    def testSeparateInserts(self):
726
        self.doMerge(['aaa', 'bbb', 'ccc'],
727
                     ['aaa', 'xxx', 'bbb', 'ccc'],
728
                     ['aaa', 'bbb', 'yyy', 'ccc'],
729
                     ['aaa', 'xxx', 'bbb', 'yyy', 'ccc'])
730
731
    def testSameInsert(self):
732
        self.doMerge(['aaa', 'bbb', 'ccc'],
733
                     ['aaa', 'xxx', 'bbb', 'ccc'],
734
                     ['aaa', 'xxx', 'bbb', 'yyy', 'ccc'],
735
                     ['aaa', 'xxx', 'bbb', 'yyy', 'ccc'])
736
737
    def testOverlappedInsert(self):
738
        self.doMerge(['aaa', 'bbb'],
739
                     ['aaa', 'xxx', 'yyy', 'bbb'],
740
                     ['aaa', 'xxx', 'bbb'],
741
                     ['aaa', '<<<<', 'xxx', 'yyy', '====', 'xxx', '>>>>', 'bbb'])
742
743
        # really it ought to reduce this to 
744
        # ['aaa', 'xxx', 'yyy', 'bbb']
745
746
747
    def testClashReplace(self):
748
        self.doMerge(['aaa'],
749
                     ['xxx'],
750
                     ['yyy', 'zzz'],
751
                     ['<<<<', 'xxx', '====', 'yyy', 'zzz', '>>>>'])
752
753
    def testNonClashInsert(self):
754
        self.doMerge(['aaa'],
755
                     ['xxx', 'aaa'],
756
                     ['yyy', 'zzz'],
757
                     ['<<<<', 'xxx', 'aaa', '====', 'yyy', 'zzz', '>>>>'])
758
759
        self.doMerge(['aaa'],
760
                     ['aaa'],
761
                     ['yyy', 'zzz'],
762
                     ['yyy', 'zzz'])
763
    
764
765
0.1.38 by Martin Pool
Rename knit to weave. (I don't think there's an existing module called weave.)
766
def testweave():
0.1.2 by Martin Pool
Import testsweet module adapted from bzr.
767
    import testsweet
768
    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.)
769
    import testweave
0.1.57 by Martin Pool
Fix bug in an update edit that both deletes and inserts -- previously
770
 
0.1.2 by Martin Pool
Import testsweet module adapted from bzr.
771
    tl = TestLoader()
772
    suite = TestSuite()
0.1.38 by Martin Pool
Rename knit to weave. (I don't think there's an existing module called weave.)
773
    suite.addTest(tl.loadTestsFromModule(testweave))
0.1.2 by Martin Pool
Import testsweet module adapted from bzr.
774
    
0.1.15 by Martin Pool
Fix inverted shell return code for testknit
775
    return int(not testsweet.run_suite(suite)) # for shell 0=true
0.1.2 by Martin Pool
Import testsweet module adapted from bzr.
776
777
778
if __name__ == '__main__':
779
    import sys
0.1.38 by Martin Pool
Rename knit to weave. (I don't think there's an existing module called weave.)
780
    sys.exit(testweave())
0.1.2 by Martin Pool
Import testsweet module adapted from bzr.
781