~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
1083 by Martin Pool
- add space to store revision-id in weave files
20
# TODO: tests regarding version names
21
0.1.2 by Martin Pool
Import testsweet module adapted from bzr.
22
23
0.1.38 by Martin Pool
Rename knit to weave. (I don't think there's an existing module called weave.)
24
"""test suite for weave algorithm"""
0.1.2 by Martin Pool
Import testsweet module adapted from bzr.
25
1323 by Martin Pool
- caller can pass SHA-1 to Weave.add for efficiency
26
from pprint import pformat
0.1.2 by Martin Pool
Import testsweet module adapted from bzr.
27
1237 by Martin Pool
- allow the same version to be repeatedly added to a weave
28
from bzrlib.weave import Weave, WeaveFormatError, WeaveError
872 by Martin Pool
- update testweave
29
from bzrlib.weavefile import write_weave, read_weave
1233 by Martin Pool
- fix up weave tests for new test framework
30
from bzrlib.selftest import TestCase
1323 by Martin Pool
- caller can pass SHA-1 to Weave.add for efficiency
31
from bzrlib.osutils import sha_string
0.1.66 by Martin Pool
Cope without set/frozenset classes
32
33
try:
34
    set
35
    frozenset
36
except NameError:
37
    from sets import Set, ImmutableSet
38
    set = Set
39
    frozenset = ImmutableSet
0.1.67 by Martin Pool
More fixes to try to run on python2.3
40
    del Set, ImmutableSet
0.1.66 by Martin Pool
Cope without set/frozenset classes
41
42
43
0.1.2 by Martin Pool
Import testsweet module adapted from bzr.
44
# texts for use in testing
0.1.3 by Martin Pool
Change storage of texts for testing
45
TEXT_0 = ["Hello world"]
46
TEXT_1 = ["Hello world",
47
          "A second line"]
0.1.2 by Martin Pool
Import testsweet module adapted from bzr.
48
49
0.1.75 by Martin Pool
Remove VerInfo class; just store sets directly in the list of
50
1233 by Martin Pool
- fix up weave tests for new test framework
51
class TestBase(TestCase):
0.1.75 by Martin Pool
Remove VerInfo class; just store sets directly in the list of
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())
1083 by Martin Pool
- add space to store revision-id in weave files
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
            
0.1.75 by Martin Pool
Remove VerInfo class; just store sets directly in the list of
73
            self.fail('read/write check failed')
74
        
75
        
76
77
0.1.2 by Martin Pool
Import testsweet module adapted from bzr.
78
class Easy(TestBase):
79
    def runTest(self):
0.1.38 by Martin Pool
Rename knit to weave. (I don't think there's an existing module called weave.)
80
        k = Weave()
0.1.2 by Martin Pool
Import testsweet module adapted from bzr.
81
82
83
class StoreText(TestBase):
84
    """Store and retrieve a simple text."""
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()
1083 by Martin Pool
- add space to store revision-id in weave files
87
        idx = k.add('text0', [], TEXT_0)
0.1.4 by Martin Pool
Start indexing knits by both integer and version string.
88
        self.assertEqual(k.get(idx), TEXT_0)
89
        self.assertEqual(idx, 0)
0.1.2 by Martin Pool
Import testsweet module adapted from bzr.
90
91
0.1.7 by Martin Pool
Add trivial annotate text
92
93
class AnnotateOne(TestBase):
94
    def runTest(self):
0.1.38 by Martin Pool
Rename knit to weave. (I don't think there's an existing module called weave.)
95
        k = Weave()
1083 by Martin Pool
- add space to store revision-id in weave files
96
        k.add('text0', [], TEXT_0)
0.1.7 by Martin Pool
Add trivial annotate text
97
        self.assertEqual(k.annotate(0),
98
                         [(0, TEXT_0[0])])
99
100
0.1.5 by Martin Pool
Add test for storing two text versions.
101
class StoreTwo(TestBase):
102
    def runTest(self):
0.1.38 by Martin Pool
Rename knit to weave. (I don't think there's an existing module called weave.)
103
        k = Weave()
0.1.5 by Martin Pool
Add test for storing two text versions.
104
1083 by Martin Pool
- add space to store revision-id in weave files
105
        idx = k.add('text0', [], TEXT_0)
0.1.5 by Martin Pool
Add test for storing two text versions.
106
        self.assertEqual(idx, 0)
107
1083 by Martin Pool
- add space to store revision-id in weave files
108
        idx = k.add('text1', [], TEXT_1)
0.1.5 by Martin Pool
Add test for storing two text versions.
109
        self.assertEqual(idx, 1)
110
111
        self.assertEqual(k.get(0), TEXT_0)
112
        self.assertEqual(k.get(1), TEXT_1)
113
0.1.13 by Martin Pool
Knit structure now allows for versions to include the lines present in other
114
0.1.21 by Martin Pool
Start computing a delta to insert a new revision
115
1323 by Martin Pool
- caller can pass SHA-1 to Weave.add for efficiency
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
0.1.27 by Martin Pool
Check that version numbers passed in are reasonable
126
class InvalidAdd(TestBase):
127
    """Try to use invalid version number during add."""
128
    def runTest(self):
0.1.38 by Martin Pool
Rename knit to weave. (I don't think there's an existing module called weave.)
129
        k = Weave()
0.1.27 by Martin Pool
Check that version numbers passed in are reasonable
130
937 by Martin Pool
- weave raises IndexError when an invalid revision is given
131
        self.assertRaises(IndexError,
0.1.27 by Martin Pool
Check that version numbers passed in are reasonable
132
                          k.add,
1083 by Martin Pool
- add space to store revision-id in weave files
133
                          'text0',
0.1.27 by Martin Pool
Check that version numbers passed in are reasonable
134
                          [69],
135
                          ['new text!'])
136
137
1237 by Martin Pool
- allow the same version to be repeatedly added to a weave
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
0.1.26 by Martin Pool
Refactor parameters to add command
165
class InsertLines(TestBase):
0.1.13 by Martin Pool
Knit structure now allows for versions to include the lines present in other
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):
0.1.38 by Martin Pool
Rename knit to weave. (I don't think there's an existing module called weave.)
171
        k = Weave()
0.1.13 by Martin Pool
Knit structure now allows for versions to include the lines present in other
172
1083 by Martin Pool
- add space to store revision-id in weave files
173
        k.add('text0', [], ['line 1'])
174
        k.add('text1', [0], ['line 1', 'line 2'])
0.1.13 by Martin Pool
Knit structure now allows for versions to include the lines present in other
175
176
        self.assertEqual(k.annotate(0),
177
                         [(0, 'line 1')])
178
0.1.25 by Martin Pool
Handle insertion of new weave layers that insert text on top of the basis
179
        self.assertEqual(k.get(1),
180
                         ['line 1',
181
                          'line 2'])
182
0.1.13 by Martin Pool
Knit structure now allows for versions to include the lines present in other
183
        self.assertEqual(k.annotate(1),
184
                         [(0, 'line 1'),
185
                          (1, 'line 2')])
186
1083 by Martin Pool
- add space to store revision-id in weave files
187
        k.add('text2', [0], ['line 1', 'diverged line'])
0.1.28 by Martin Pool
More tests for insertion of lines in new versions.
188
189
        self.assertEqual(k.annotate(2),
190
                         [(0, 'line 1'),
191
                          (2, 'diverged line')])
192
0.1.54 by Martin Pool
Fix weave line calculation when making deltas
193
        text3 = ['line 1', 'middle line', 'line 2']
1083 by Martin Pool
- add space to store revision-id in weave files
194
        k.add('text3',
195
              [0, 1],
0.1.54 by Martin Pool
Fix weave line calculation when making deltas
196
              text3)
197
937 by Martin Pool
- weave raises IndexError when an invalid revision is given
198
        # 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
199
944 by Martin Pool
- refactor member names in Weave code
200
        self.log("k._weave=" + pformat(k._weave))
0.1.28 by Martin Pool
More tests for insertion of lines in new versions.
201
202
        self.assertEqual(k.annotate(3),
203
                         [(0, 'line 1'),
204
                          (3, 'middle line'),
205
                          (1, 'line 2')])
206
0.1.31 by Martin Pool
Fix insertion of multiple regions, calculating the right line offset as we go.
207
        # now multiple insertions at different places
1083 by Martin Pool
- add space to store revision-id in weave files
208
        k.add('text4',
209
              [0, 1, 3],
0.1.31 by Martin Pool
Fix insertion of multiple regions, calculating the right line offset as we go.
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')])
0.1.13 by Martin Pool
Knit structure now allows for versions to include the lines present in other
219
0.1.40 by Martin Pool
Add test for extracting from weave with nested insertions
220
0.1.48 by Martin Pool
Basic parsing of delete instructions.
221
0.1.56 by Martin Pool
Handle deletion of lines by marking the region with a deletion
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
1083 by Martin Pool
- add space to store revision-id in weave files
231
        k.add('text0', [], base_text)
0.1.56 by Martin Pool
Handle deletion of lines by marking the region with a deletion
232
        
233
        texts = [['one', 'two', 'three'],
234
                 ['two', 'three', 'four'],
235
                 ['one', 'four'],
236
                 ['one', 'two', 'three', 'four'],
237
                 ]
238
1083 by Martin Pool
- add space to store revision-id in weave files
239
        i = 1
0.1.56 by Martin Pool
Handle deletion of lines by marking the region with a deletion
240
        for t in texts:
1083 by Martin Pool
- add space to store revision-id in weave files
241
            ver = k.add('text%d' % i,
242
                        [0], t)
243
            i += 1
0.1.56 by Martin Pool
Handle deletion of lines by marking the region with a deletion
244
245
        self.log('final weave:')
944 by Martin Pool
- refactor member names in Weave code
246
        self.log('k._weave=' + pformat(k._weave))
0.1.56 by Martin Pool
Handle deletion of lines by marking the region with a deletion
247
248
        for i in range(len(texts)):
249
            self.assertEqual(k.get(i+1),
250
                             texts[i])
251
            
252
253
254
0.1.49 by Martin Pool
Add another constraint: revisions should not delete text that they
255
class SuicideDelete(TestBase):
0.1.55 by Martin Pool
doc
256
    """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
257
    def runTest(self):
258
        k = Weave()
259
944 by Martin Pool
- refactor member names in Weave code
260
        k._parents = [(),
0.1.49 by Martin Pool
Add another constraint: revisions should not delete text that they
261
                ]
944 by Martin Pool
- refactor member names in Weave code
262
        k._weave = [('{', 0),
0.1.49 by Martin Pool
Add another constraint: revisions should not delete text that they
263
                'first line',
264
                ('[', 0),
265
                'deleted in 0',
266
                (']', 0),
267
                ('}', 0),
268
                ]
891 by Martin Pool
- fix up refactoring of weave
269
        ################################### SKIPPED
270
        # Weave.get doesn't trap this anymore
271
        return 
0.1.49 by Martin Pool
Add another constraint: revisions should not delete text that they
272
273
        self.assertRaises(WeaveFormatError,
274
                          k.get,
275
                          0)        
276
277
278
0.1.48 by Martin Pool
Basic parsing of delete instructions.
279
class CannedDelete(TestBase):
280
    """Unpack canned weave with deleted lines."""
281
    def runTest(self):
282
        k = Weave()
283
944 by Martin Pool
- refactor member names in Weave code
284
        k._parents = [(),
0.1.75 by Martin Pool
Remove VerInfo class; just store sets directly in the list of
285
                frozenset([0]),
0.1.48 by Martin Pool
Basic parsing of delete instructions.
286
                ]
944 by Martin Pool
- refactor member names in Weave code
287
        k._weave = [('{', 0),
0.1.48 by Martin Pool
Basic parsing of delete instructions.
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
0.1.50 by Martin Pool
Basic implementation of deletion markers
302
        self.assertEqual(k.get(1),
303
                         ['first line',
304
                          'last line',
305
                          ])
306
0.1.48 by Martin Pool
Basic parsing of delete instructions.
307
308
0.1.51 by Martin Pool
Add test for replacement lines
309
class CannedReplacement(TestBase):
310
    """Unpack canned weave with deleted lines."""
311
    def runTest(self):
312
        k = Weave()
313
944 by Martin Pool
- refactor member names in Weave code
314
        k._parents = [frozenset(),
0.1.75 by Martin Pool
Remove VerInfo class; just store sets directly in the list of
315
                frozenset([0]),
0.1.51 by Martin Pool
Add test for replacement lines
316
                ]
944 by Martin Pool
- refactor member names in Weave code
317
        k._weave = [('{', 0),
0.1.51 by Martin Pool
Add test for replacement lines
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
0.1.46 by Martin Pool
More constraints on structure of weave, and checks that they work
343
class BadWeave(TestBase):
344
    """Test that we trap an insert which should not occur."""
345
    def runTest(self):
346
        k = Weave()
347
944 by Martin Pool
- refactor member names in Weave code
348
        k._parents = [frozenset(),
0.1.46 by Martin Pool
More constraints on structure of weave, and checks that they work
349
                ]
944 by Martin Pool
- refactor member names in Weave code
350
        k._weave = ['bad line',
0.1.46 by Martin Pool
More constraints on structure of weave, and checks that they work
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
891 by Martin Pool
- fix up refactoring of weave
363
        ################################### SKIPPED
364
        # Weave.get doesn't trap this anymore
365
        return 
366
367
0.1.47 by Martin Pool
New WeaveError and WeaveFormatError rather than assertions.
368
        self.assertRaises(WeaveFormatError,
0.1.46 by Martin Pool
More constraints on structure of weave, and checks that they work
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
944 by Martin Pool
- refactor member names in Weave code
378
        k._parents = [frozenset(),
0.1.75 by Martin Pool
Remove VerInfo class; just store sets directly in the list of
379
                frozenset([0]),
380
                frozenset([0]),
381
                frozenset([0,1,2]),
0.1.46 by Martin Pool
More constraints on structure of weave, and checks that they work
382
                ]
944 by Martin Pool
- refactor member names in Weave code
383
        k._weave = [('{', 0),
0.1.46 by Martin Pool
More constraints on structure of weave, and checks that they work
384
                'foo {',
385
                ('{', 1),
386
                '  added in version 1',
387
                ('{', 1),
388
                '  more in 1',
389
                ('}', 1),
390
                ('}', 1),
391
                ('}', 0)]
392
891 by Martin Pool
- fix up refactoring of weave
393
394
        # this is not currently enforced by get
395
        return  ##########################################
396
0.1.47 by Martin Pool
New WeaveError and WeaveFormatError rather than assertions.
397
        self.assertRaises(WeaveFormatError,
0.1.46 by Martin Pool
More constraints on structure of weave, and checks that they work
398
                          k.get,
399
                          0)
400
0.1.47 by Martin Pool
New WeaveError and WeaveFormatError rather than assertions.
401
        self.assertRaises(WeaveFormatError,
0.1.46 by Martin Pool
More constraints on structure of weave, and checks that they work
402
                          k.get,
403
                          1)
404
0.1.40 by Martin Pool
Add test for extracting from weave with nested insertions
405
406
class InsertNested(TestBase):
407
    """Insertion with nested instructions."""
408
    def runTest(self):
409
        k = Weave()
410
944 by Martin Pool
- refactor member names in Weave code
411
        k._parents = [frozenset(),
0.1.75 by Martin Pool
Remove VerInfo class; just store sets directly in the list of
412
                frozenset([0]),
413
                frozenset([0]),
414
                frozenset([0,1,2]),
0.1.40 by Martin Pool
Add test for extracting from weave with nested insertions
415
                ]
944 by Martin Pool
- refactor member names in Weave code
416
        k._weave = [('{', 0),
0.1.40 by Martin Pool
Add test for extracting from weave with nested insertions
417
                'foo {',
418
                ('{', 1),
419
                '  added in version 1',
0.1.42 by Martin Pool
More tests for nested insert instructions
420
                ('{', 2),
421
                '  added in v2',
422
                ('}', 2),
423
                '  also from v1',
0.1.40 by Martin Pool
Add test for extracting from weave with nested insertions
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',
0.1.42 by Martin Pool
More tests for nested insert instructions
435
                          '  also from v1',
0.1.40 by Martin Pool
Add test for extracting from weave with nested insertions
436
                          '}'])
437
                       
0.1.44 by Martin Pool
More tests for nested insert instructions
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
                         
0.1.45 by Martin Pool
doc
450
0.1.40 by Martin Pool
Add test for extracting from weave with nested insertions
451
0.1.56 by Martin Pool
Handle deletion of lines by marking the region with a deletion
452
class DeleteLines2(TestBase):
0.1.30 by Martin Pool
Start adding tests for line deletion
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):
0.1.38 by Martin Pool
Rename knit to weave. (I don't think there's an existing module called weave.)
458
        k = Weave()
0.1.30 by Martin Pool
Start adding tests for line deletion
459
1083 by Martin Pool
- add space to store revision-id in weave files
460
        k.add('text0', [], ["line the first",
0.1.30 by Martin Pool
Start adding tests for line deletion
461
                   "line 2",
462
                   "line 3",
463
                   "fine"])
464
465
        self.assertEqual(len(k.get(0)), 4)
466
1083 by Martin Pool
- add space to store revision-id in weave files
467
        k.add('text1', [0], ["line the first",
0.1.30 by Martin Pool
Start adding tests for line deletion
468
                   "fine"])
469
470
        self.assertEqual(k.get(1),
471
                         ["line the first",
472
                          "fine"])
473
0.1.56 by Martin Pool
Handle deletion of lines by marking the region with a deletion
474
        self.assertEqual(k.annotate(1),
475
                         [(0, "line the first"),
476
                          (0, "fine")])
477
0.1.30 by Martin Pool
Start adding tests for line deletion
478
0.1.26 by Martin Pool
Refactor parameters to add command
479
0.1.13 by Martin Pool
Knit structure now allows for versions to include the lines present in other
480
class IncludeVersions(TestBase):
481
    """Check texts that are stored across multiple revisions.
482
0.1.38 by Martin Pool
Rename knit to weave. (I don't think there's an existing module called weave.)
483
    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
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):
0.1.38 by Martin Pool
Rename knit to weave. (I don't think there's an existing module called weave.)
491
        k = Weave()
0.1.13 by Martin Pool
Knit structure now allows for versions to include the lines present in other
492
944 by Martin Pool
- refactor member names in Weave code
493
        k._parents = [frozenset(), frozenset([0])]
494
        k._weave = [('{', 0),
0.1.39 by Martin Pool
Change to a more realistic weave structure which can represent insertions and
495
                "first line",
496
                ('}', 0),
497
                ('{', 1),
498
                "second line",
499
                ('}', 1)]
0.1.13 by Martin Pool
Knit structure now allows for versions to include the lines present in other
500
501
        self.assertEqual(k.get(1),
502
                         ["first line",
503
                          "second line"])
504
505
        self.assertEqual(k.get(0),
506
                         ["first line"])
507
0.1.5 by Martin Pool
Add test for storing two text versions.
508
0.1.14 by Martin Pool
Another test for version inclusion
509
class DivergedIncludes(TestBase):
0.1.38 by Martin Pool
Rename knit to weave. (I don't think there's an existing module called weave.)
510
    """Weave with two diverged texts based on version 0.
0.1.14 by Martin Pool
Another test for version inclusion
511
    """
512
    def runTest(self):
0.1.38 by Martin Pool
Rename knit to weave. (I don't think there's an existing module called weave.)
513
        k = Weave()
0.1.14 by Martin Pool
Another test for version inclusion
514
944 by Martin Pool
- refactor member names in Weave code
515
        k._parents = [frozenset(),
0.1.75 by Martin Pool
Remove VerInfo class; just store sets directly in the list of
516
                frozenset([0]),
517
                frozenset([0]),
0.1.17 by Martin Pool
Use objects rather than tuples for tracking VerInfo for
518
                ]
944 by Martin Pool
- refactor member names in Weave code
519
        k._weave = [('{', 0),
0.1.39 by Martin Pool
Change to a more realistic weave structure which can represent insertions and
520
                "first line",
521
                ('}', 0),
522
                ('{', 1),
523
                "second line",
524
                ('}', 1),
525
                ('{', 2),
526
                "alternative second line",
527
                ('}', 2),                
528
                ]
0.1.14 by Martin Pool
Another test for version inclusion
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
924 by Martin Pool
- Add IntSet class
541
        self.assertEqual(list(k.inclusions([2])),
542
                         [0, 2])
0.1.77 by Martin Pool
New Weave.get_included() does transitive expansion
543
0.1.57 by Martin Pool
Fix bug in an update edit that both deletes and inserts -- previously
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
        
1083 by Martin Pool
- add space to store revision-id in weave files
553
        k.add('text0', [], text0)
554
        k.add('text1', [0], text1)
0.1.57 by Martin Pool
Fix bug in an update edit that both deletes and inserts -- previously
555
944 by Martin Pool
- refactor member names in Weave code
556
        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
557
0.1.59 by Martin Pool
More modification tests
558
        self.assertEqual(k.get(0), text0)
0.1.57 by Martin Pool
Fix bug in an update edit that both deletes and inserts -- previously
559
        self.assertEqual(k.get(1), text1)
560
0.1.64 by Martin Pool
Add test for merging versions
561
562
563
class Merge(TestBase):
0.1.95 by Martin Pool
- preliminary merge conflict detection
564
    """Storage of versions that merge diverged parents"""
0.1.64 by Martin Pool
Add test for merging versions
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
1083 by Martin Pool
- add space to store revision-id in weave files
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])
0.1.64 by Martin Pool
Add test for merging versions
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
924 by Martin Pool
- Add IntSet class
590
        self.assertEqual(list(k.inclusions([3])),
591
                         [0, 1, 2, 3])
0.1.77 by Martin Pool
New Weave.get_included() does transitive expansion
592
944 by Martin Pool
- refactor member names in Weave code
593
        self.log('k._weave=' + pformat(k._weave))
0.1.64 by Martin Pool
Add test for merging versions
594
0.1.75 by Martin Pool
Remove VerInfo class; just store sets directly in the list of
595
        self.check_read_write(k)
0.1.65 by Martin Pool
Add Weave.merge_iter to get automerged lines
596
597
0.1.95 by Martin Pool
- preliminary merge conflict detection
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
0.1.65 by Martin Pool
Add Weave.merge_iter to get automerged lines
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
1083 by Martin Pool
- add space to store revision-id in weave files
645
        k.add('text0', [], texts[0])
646
        k.add('text1', [0], texts[1])
647
        k.add('text2', [0], texts[2])
0.1.65 by Martin Pool
Add Weave.merge_iter to get automerged lines
648
944 by Martin Pool
- refactor member names in Weave code
649
        self.log('k._weave=' + pformat(k._weave))
0.1.65 by Martin Pool
Add Weave.merge_iter to get automerged lines
650
0.1.95 by Martin Pool
- preliminary merge conflict detection
651
        m = list(k.mash_iter([0, 1, 2]))
0.1.65 by Martin Pool
Add Weave.merge_iter to get automerged lines
652
653
        self.assertEqual(m,
654
                         ['header', 'aaa',
655
                          'line from 1',
656
                          'bbb',
657
                          'line from 2', 'more from 2'])
0.1.57 by Martin Pool
Fix bug in an update edit that both deletes and inserts -- previously
658
        
659
660
661
class Khayyam(TestBase):
0.1.75 by Martin Pool
Remove VerInfo class; just store sets directly in the list of
662
    """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
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!""",
0.1.59 by Martin Pool
More modification tests
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 --
0.1.75 by Martin Pool
Remove VerInfo class; just store sets directly in the list of
687
            Oh, Wilderness were Paradise now!""",
0.1.57 by Martin Pool
Fix bug in an update edit that both deletes and inserts -- previously
688
            ]
689
        texts = [[l.strip() for l in t.split('\n')] for t in rawtexts]
690
691
        k = Weave()
692
        parents = set()
1083 by Martin Pool
- add space to store revision-id in weave files
693
        i = 0
0.1.57 by Martin Pool
Fix bug in an update edit that both deletes and inserts -- previously
694
        for t in texts:
1083 by Martin Pool
- add space to store revision-id in weave files
695
            ver = k.add('text%d' % i,
696
                        list(parents), t)
0.1.57 by Martin Pool
Fix bug in an update edit that both deletes and inserts -- previously
697
            parents.add(ver)
1083 by Martin Pool
- add space to store revision-id in weave files
698
            i += 1
0.1.57 by Martin Pool
Fix bug in an update edit that both deletes and inserts -- previously
699
944 by Martin Pool
- refactor member names in Weave code
700
        self.log("k._weave=" + pformat(k._weave))
0.1.59 by Martin Pool
More modification tests
701
0.1.57 by Martin Pool
Fix bug in an update edit that both deletes and inserts -- previously
702
        for i, t in enumerate(texts):
0.1.75 by Martin Pool
Remove VerInfo class; just store sets directly in the list of
703
            self.assertEqual(k.get(i), t)
0.1.57 by Martin Pool
Fix bug in an update edit that both deletes and inserts -- previously
704
0.1.75 by Martin Pool
Remove VerInfo class; just store sets directly in the list of
705
        self.check_read_write(k)
0.1.57 by Martin Pool
Fix bug in an update edit that both deletes and inserts -- previously
706
707
920 by Martin Pool
- add more test cases for weave_merge
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()
1083 by Martin Pool
- add space to store revision-id in weave files
718
        w.add('text0', [], map(addcrlf, base))
719
        w.add('text1', [0], map(addcrlf, a))
720
        w.add('text2', [0], map(addcrlf, b))
920 by Martin Pool
- add more test cases for weave_merge
721
935 by Martin Pool
- log weave for merge tests to help debugging
722
        self.log('weave is:')
723
        tmpf = StringIO()
724
        write_weave(w, tmpf)
725
        self.log(tmpf.getvalue())
726
920 by Martin Pool
- add more test cases for weave_merge
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'])
945 by Martin Pool
- add stubbed-out test for clashing replace and delete
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'])
920 by Martin Pool
- add more test cases for weave_merge
804
    
805
806
0.1.2 by Martin Pool
Import testsweet module adapted from bzr.
807
if __name__ == '__main__':
808
    import sys
1233 by Martin Pool
- fix up weave tests for new test framework
809
    import unittest
810
    sys.exit(unittest.main())
0.1.2 by Martin Pool
Import testsweet module adapted from bzr.
811