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