~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to tools/testweave.py

  • Committer: Martin Pool
  • Date: 2005-07-11 03:12:11 UTC
  • Revision ID: mbp@sourcefrog.net-20050711031211-9e04b4d2f79fb7b9
- fix typo

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005 Canonical Ltd
2
 
#
 
1
#! /usr/bin/python2.4
 
2
 
 
3
# Copyright (C) 2005 by Canonical Ltd
 
4
 
3
5
# This program is free software; you can redistribute it and/or modify
4
6
# it under the terms of the GNU General Public License as published by
5
7
# the Free Software Foundation; either version 2 of the License, or
6
8
# (at your option) any later version.
7
 
#
 
9
 
8
10
# This program is distributed in the hope that it will be useful,
9
11
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
13
# GNU General Public License for more details.
12
 
#
 
14
 
13
15
# You should have received a copy of the GNU General Public License
14
16
# along with this program; if not, write to the Free Software
15
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
 
 
17
 
 
18
 
# TODO: tests regarding version names
19
 
# TODO: rbc 20050108 test that join does not leave an inconsistent weave
20
 
#       if it fails.
 
17
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
18
 
 
19
 
 
20
 
21
21
 
22
22
"""test suite for weave algorithm"""
23
23
 
 
24
 
 
25
import testsweet
 
26
from bzrlib.weave import Weave, WeaveFormatError
 
27
from bzrlib.weavefile import write_weave, read_weave
24
28
from pprint import pformat
25
29
 
26
 
from bzrlib import (
27
 
    errors,
28
 
    )
29
 
from bzrlib.osutils import sha_string
30
 
from bzrlib.tests import TestCase, TestCaseInTempDir
31
 
from bzrlib.weave import Weave, WeaveFormatError, WeaveError
32
 
from bzrlib.weavefile import write_weave, read_weave
 
30
 
 
31
 
 
32
try:
 
33
    set
 
34
    frozenset
 
35
except NameError:
 
36
    from sets import Set, ImmutableSet
 
37
    set = Set
 
38
    frozenset = ImmutableSet
 
39
    del Set, ImmutableSet
 
40
 
33
41
 
34
42
 
35
43
# texts for use in testing
38
46
          "A second line"]
39
47
 
40
48
 
41
 
class TestBase(TestCase):
42
49
 
 
50
class TestBase(testsweet.TestBase):
43
51
    def check_read_write(self, k):
44
52
        """Check the weave k can be written & re-read."""
45
53
        from tempfile import TemporaryFile
53
61
            tf.seek(0)
54
62
            self.log('serialized weave:')
55
63
            self.log(tf.read())
56
 
 
57
 
            self.log('')
58
 
            self.log('parents: %s' % (k._parents == k2._parents))
59
 
            self.log('         %r' % k._parents)
60
 
            self.log('         %r' % k2._parents)
61
 
            self.log('')
62
64
            self.fail('read/write check failed')
63
 
 
64
 
 
65
 
class WeaveContains(TestBase):
66
 
    """Weave __contains__ operator"""
67
 
    def runTest(self):
68
 
        k = Weave(get_scope=lambda:None)
69
 
        self.assertFalse('foo' in k)
70
 
        k.add_lines('foo', [], TEXT_1)
71
 
        self.assertTrue('foo' in k)
 
65
        
 
66
        
72
67
 
73
68
 
74
69
class Easy(TestBase):
76
71
        k = Weave()
77
72
 
78
73
 
 
74
class StoreText(TestBase):
 
75
    """Store and retrieve a simple text."""
 
76
    def runTest(self):
 
77
        k = Weave()
 
78
        idx = k.add([], TEXT_0)
 
79
        self.assertEqual(k.get(idx), TEXT_0)
 
80
        self.assertEqual(idx, 0)
 
81
 
 
82
 
 
83
 
79
84
class AnnotateOne(TestBase):
80
85
    def runTest(self):
81
86
        k = Weave()
82
 
        k.add_lines('text0', [], TEXT_0)
83
 
        self.assertEqual(k.annotate('text0'),
84
 
                         [('text0', TEXT_0[0])])
 
87
        k.add([], TEXT_0)
 
88
        self.assertEqual(k.annotate(0),
 
89
                         [(0, TEXT_0[0])])
 
90
 
 
91
 
 
92
class StoreTwo(TestBase):
 
93
    def runTest(self):
 
94
        k = Weave()
 
95
 
 
96
        idx = k.add([], TEXT_0)
 
97
        self.assertEqual(idx, 0)
 
98
 
 
99
        idx = k.add([], TEXT_1)
 
100
        self.assertEqual(idx, 1)
 
101
 
 
102
        self.assertEqual(k.get(0), TEXT_0)
 
103
        self.assertEqual(k.get(1), TEXT_1)
 
104
 
 
105
        k.dump(self.TEST_LOG)
 
106
 
 
107
 
 
108
 
 
109
class DeltaAdd(TestBase):
 
110
    """Detection of changes prior to inserting new revision."""
 
111
    def runTest(self):
 
112
        k = Weave()
 
113
        k.add([], ['line 1'])
 
114
 
 
115
        self.assertEqual(k._l,
 
116
                         [('{', 0),
 
117
                          'line 1',
 
118
                          ('}', 0),
 
119
                          ])
 
120
 
 
121
        changes = list(k._delta(set([0]),
 
122
                                ['line 1',
 
123
                                 'new line']))
 
124
 
 
125
        self.log('raw changes: ' + pformat(changes))
 
126
 
 
127
        # currently there are 3 lines in the weave, and we insert after them
 
128
        self.assertEquals(changes,
 
129
                          [(3, 3, ['new line'])])
 
130
 
 
131
        changes = k._delta(set([0]),
 
132
                           ['top line',
 
133
                            'line 1'])
 
134
        
 
135
        self.assertEquals(list(changes),
 
136
                          [(1, 1, ['top line'])])
 
137
 
 
138
        self.check_read_write(k)
85
139
 
86
140
 
87
141
class InvalidAdd(TestBase):
89
143
    def runTest(self):
90
144
        k = Weave()
91
145
 
92
 
        self.assertRaises(errors.RevisionNotPresent,
93
 
                          k.add_lines,
94
 
                          'text0',
95
 
                          ['69'],
 
146
        self.assertRaises(ValueError,
 
147
                          k.add,
 
148
                          [69],
96
149
                          ['new text!'])
97
150
 
98
151
 
99
 
class RepeatedAdd(TestBase):
100
 
    """Add the same version twice; harmless."""
101
 
 
102
 
    def test_duplicate_add(self):
103
 
        k = Weave()
104
 
        idx = k.add_lines('text0', [], TEXT_0)
105
 
        idx2 = k.add_lines('text0', [], TEXT_0)
106
 
        self.assertEqual(idx, idx2)
107
 
 
108
 
 
109
 
class InvalidRepeatedAdd(TestBase):
110
 
    def runTest(self):
111
 
        k = Weave()
112
 
        k.add_lines('basis', [], TEXT_0)
113
 
        idx = k.add_lines('text0', [], TEXT_0)
114
 
        self.assertRaises(errors.RevisionAlreadyPresent,
115
 
                          k.add_lines,
116
 
                          'text0',
117
 
                          [],
118
 
                          ['not the same text'])
119
 
        self.assertRaises(errors.RevisionAlreadyPresent,
120
 
                          k.add_lines,
121
 
                          'text0',
122
 
                          ['basis'],         # not the right parents
123
 
                          TEXT_0)
124
 
 
125
 
 
126
152
class InsertLines(TestBase):
127
153
    """Store a revision that adds one line to the original.
128
154
 
131
157
    def runTest(self):
132
158
        k = Weave()
133
159
 
134
 
        k.add_lines('text0', [], ['line 1'])
135
 
        k.add_lines('text1', ['text0'], ['line 1', 'line 2'])
136
 
 
137
 
        self.assertEqual(k.annotate('text0'),
138
 
                         [('text0', 'line 1')])
139
 
 
140
 
        self.assertEqual(k.get_lines(1),
 
160
        k.add([], ['line 1'])
 
161
        k.add([0], ['line 1', 'line 2'])
 
162
 
 
163
        self.assertEqual(k.annotate(0),
 
164
                         [(0, 'line 1')])
 
165
 
 
166
        self.assertEqual(k.get(1),
141
167
                         ['line 1',
142
168
                          'line 2'])
143
169
 
144
 
        self.assertEqual(k.annotate('text1'),
145
 
                         [('text0', 'line 1'),
146
 
                          ('text1', 'line 2')])
147
 
 
148
 
        k.add_lines('text2', ['text0'], ['line 1', 'diverged line'])
149
 
 
150
 
        self.assertEqual(k.annotate('text2'),
151
 
                         [('text0', 'line 1'),
152
 
                          ('text2', 'diverged line')])
 
170
        self.assertEqual(k.annotate(1),
 
171
                         [(0, 'line 1'),
 
172
                          (1, 'line 2')])
 
173
 
 
174
        k.add([0], ['line 1', 'diverged line'])
 
175
 
 
176
        self.assertEqual(k.annotate(2),
 
177
                         [(0, 'line 1'),
 
178
                          (2, 'diverged line')])
153
179
 
154
180
        text3 = ['line 1', 'middle line', 'line 2']
155
 
        k.add_lines('text3',
156
 
              ['text0', 'text1'],
 
181
        k.add([0, 1],
157
182
              text3)
158
183
 
159
 
        # self.log("changes to text3: " + pformat(list(k._delta(set([0, 1]), text3))))
160
 
 
161
 
        self.log("k._weave=" + pformat(k._weave))
162
 
 
163
 
        self.assertEqual(k.annotate('text3'),
164
 
                         [('text0', 'line 1'),
165
 
                          ('text3', 'middle line'),
166
 
                          ('text1', 'line 2')])
 
184
        self.log("changes to text3: " + pformat(list(k._delta(set([0, 1]), text3))))
 
185
 
 
186
        self.log("k._l=" + pformat(k._l))
 
187
 
 
188
        self.assertEqual(k.annotate(3),
 
189
                         [(0, 'line 1'),
 
190
                          (3, 'middle line'),
 
191
                          (1, 'line 2')])
167
192
 
168
193
        # now multiple insertions at different places
169
 
        k.add_lines('text4',
170
 
              ['text0', 'text1', 'text3'],
 
194
        k.add([0, 1, 3],
171
195
              ['line 1', 'aaa', 'middle line', 'bbb', 'line 2', 'ccc'])
172
196
 
173
 
        self.assertEqual(k.annotate('text4'),
174
 
                         [('text0', 'line 1'),
175
 
                          ('text4', 'aaa'),
176
 
                          ('text3', 'middle line'),
177
 
                          ('text4', 'bbb'),
178
 
                          ('text1', 'line 2'),
179
 
                          ('text4', 'ccc')])
 
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')])
 
204
 
180
205
 
181
206
 
182
207
class DeleteLines(TestBase):
188
213
 
189
214
        base_text = ['one', 'two', 'three', 'four']
190
215
 
191
 
        k.add_lines('text0', [], base_text)
192
 
 
 
216
        k.add([], base_text)
 
217
        
193
218
        texts = [['one', 'two', 'three'],
194
219
                 ['two', 'three', 'four'],
195
220
                 ['one', 'four'],
196
221
                 ['one', 'two', 'three', 'four'],
197
222
                 ]
198
223
 
199
 
        i = 1
200
224
        for t in texts:
201
 
            ver = k.add_lines('text%d' % i,
202
 
                        ['text0'], t)
203
 
            i += 1
 
225
            ver = k.add([0], t)
204
226
 
205
227
        self.log('final weave:')
206
 
        self.log('k._weave=' + pformat(k._weave))
 
228
        self.log('k._l=' + pformat(k._l))
207
229
 
208
230
        for i in range(len(texts)):
209
 
            self.assertEqual(k.get_lines(i+1),
 
231
            self.assertEqual(k.get(i+1),
210
232
                             texts[i])
 
233
            
 
234
 
211
235
 
212
236
 
213
237
class SuicideDelete(TestBase):
215
239
    def runTest(self):
216
240
        k = Weave()
217
241
 
218
 
        k._parents = [(),
 
242
        k._v = [(),
219
243
                ]
220
 
        k._weave = [('{', 0),
 
244
        k._l = [('{', 0),
221
245
                'first line',
222
246
                ('[', 0),
223
247
                'deleted in 0',
224
248
                (']', 0),
225
249
                ('}', 0),
226
250
                ]
227
 
        ################################### SKIPPED
228
 
        # Weave.get doesn't trap this anymore
229
 
        return
230
251
 
231
252
        self.assertRaises(WeaveFormatError,
232
 
                          k.get_lines,
233
 
                          0)
 
253
                          k.get,
 
254
                          0)        
 
255
 
234
256
 
235
257
 
236
258
class CannedDelete(TestBase):
238
260
    def runTest(self):
239
261
        k = Weave()
240
262
 
241
 
        k._parents = [(),
 
263
        k._v = [(),
242
264
                frozenset([0]),
243
265
                ]
244
 
        k._weave = [('{', 0),
 
266
        k._l = [('{', 0),
245
267
                'first line',
246
268
                ('[', 1),
247
269
                'line to be deleted',
249
271
                'last line',
250
272
                ('}', 0),
251
273
                ]
252
 
        k._sha1s = [sha_string('first lineline to be deletedlast line')
253
 
                  , sha_string('first linelast line')]
254
274
 
255
 
        self.assertEqual(k.get_lines(0),
 
275
        self.assertEqual(k.get(0),
256
276
                         ['first line',
257
277
                          'line to be deleted',
258
278
                          'last line',
259
279
                          ])
260
280
 
261
 
        self.assertEqual(k.get_lines(1),
 
281
        self.assertEqual(k.get(1),
262
282
                         ['first line',
263
283
                          'last line',
264
284
                          ])
265
285
 
266
286
 
 
287
 
267
288
class CannedReplacement(TestBase):
268
289
    """Unpack canned weave with deleted lines."""
269
290
    def runTest(self):
270
291
        k = Weave()
271
292
 
272
 
        k._parents = [frozenset(),
 
293
        k._v = [frozenset(),
273
294
                frozenset([0]),
274
295
                ]
275
 
        k._weave = [('{', 0),
 
296
        k._l = [('{', 0),
276
297
                'first line',
277
298
                ('[', 1),
278
299
                'line to be deleted',
279
300
                (']', 1),
280
301
                ('{', 1),
281
 
                'replacement line',
 
302
                'replacement line',                
282
303
                ('}', 1),
283
304
                'last line',
284
305
                ('}', 0),
285
306
                ]
286
 
        k._sha1s = [sha_string('first lineline to be deletedlast line')
287
 
                  , sha_string('first linereplacement linelast line')]
288
307
 
289
 
        self.assertEqual(k.get_lines(0),
 
308
        self.assertEqual(k.get(0),
290
309
                         ['first line',
291
310
                          'line to be deleted',
292
311
                          'last line',
293
312
                          ])
294
313
 
295
 
        self.assertEqual(k.get_lines(1),
 
314
        self.assertEqual(k.get(1),
296
315
                         ['first line',
297
316
                          'replacement line',
298
317
                          'last line',
299
318
                          ])
300
319
 
301
320
 
 
321
 
302
322
class BadWeave(TestBase):
303
323
    """Test that we trap an insert which should not occur."""
304
324
    def runTest(self):
305
325
        k = Weave()
306
326
 
307
 
        k._parents = [frozenset(),
 
327
        k._v = [frozenset(),
308
328
                ]
309
 
        k._weave = ['bad line',
 
329
        k._l = ['bad line',
310
330
                ('{', 0),
311
331
                'foo {',
312
332
                ('{', 1),
319
339
                '}',
320
340
                ('}', 0)]
321
341
 
322
 
        ################################### SKIPPED
323
 
        # Weave.get doesn't trap this anymore
324
 
        return
325
 
 
326
 
 
327
342
        self.assertRaises(WeaveFormatError,
328
343
                          k.get,
329
344
                          0)
334
349
    def runTest(self):
335
350
        k = Weave()
336
351
 
337
 
        k._parents = [frozenset(),
 
352
        k._v = [frozenset(),
338
353
                frozenset([0]),
339
354
                frozenset([0]),
340
355
                frozenset([0,1,2]),
341
356
                ]
342
 
        k._weave = [('{', 0),
 
357
        k._l = [('{', 0),
343
358
                'foo {',
344
359
                ('{', 1),
345
360
                '  added in version 1',
349
364
                ('}', 1),
350
365
                ('}', 0)]
351
366
 
352
 
 
353
 
        # this is not currently enforced by get
354
 
        return  ##########################################
355
 
 
356
367
        self.assertRaises(WeaveFormatError,
357
368
                          k.get,
358
369
                          0)
367
378
    def runTest(self):
368
379
        k = Weave()
369
380
 
370
 
        k._parents = [frozenset(),
 
381
        k._v = [frozenset(),
371
382
                frozenset([0]),
372
383
                frozenset([0]),
373
384
                frozenset([0,1,2]),
374
385
                ]
375
 
        k._weave = [('{', 0),
 
386
        k._l = [('{', 0),
376
387
                'foo {',
377
388
                ('{', 1),
378
389
                '  added in version 1',
384
395
                '}',
385
396
                ('}', 0)]
386
397
 
387
 
        k._sha1s = [sha_string('foo {}')
388
 
                  , sha_string('foo {  added in version 1  also from v1}')
389
 
                  , sha_string('foo {  added in v2}')
390
 
                  , sha_string('foo {  added in version 1  added in v2  also from v1}')
391
 
                  ]
392
 
 
393
 
        self.assertEqual(k.get_lines(0),
394
 
                         ['foo {',
395
 
                          '}'])
396
 
 
397
 
        self.assertEqual(k.get_lines(1),
398
 
                         ['foo {',
399
 
                          '  added in version 1',
400
 
                          '  also from v1',
401
 
                          '}'])
402
 
 
403
 
        self.assertEqual(k.get_lines(2),
404
 
                         ['foo {',
405
 
                          '  added in v2',
406
 
                          '}'])
407
 
 
408
 
        self.assertEqual(k.get_lines(3),
409
 
                         ['foo {',
410
 
                          '  added in version 1',
411
 
                          '  added in v2',
412
 
                          '  also from v1',
413
 
                          '}'])
 
398
        self.assertEqual(k.get(0),
 
399
                         ['foo {',
 
400
                          '}'])
 
401
 
 
402
        self.assertEqual(k.get(1),
 
403
                         ['foo {',
 
404
                          '  added in version 1',
 
405
                          '  also from v1',
 
406
                          '}'])
 
407
                       
 
408
        self.assertEqual(k.get(2),
 
409
                         ['foo {',
 
410
                          '  added in v2',
 
411
                          '}'])
 
412
 
 
413
        self.assertEqual(k.get(3),
 
414
                         ['foo {',
 
415
                          '  added in version 1',
 
416
                          '  added in v2',
 
417
                          '  also from v1',
 
418
                          '}'])
 
419
                         
414
420
 
415
421
 
416
422
class DeleteLines2(TestBase):
421
427
    def runTest(self):
422
428
        k = Weave()
423
429
 
424
 
        k.add_lines('text0', [], ["line the first",
 
430
        k.add([], ["line the first",
425
431
                   "line 2",
426
432
                   "line 3",
427
433
                   "fine"])
428
434
 
429
 
        self.assertEqual(len(k.get_lines(0)), 4)
 
435
        self.assertEqual(len(k.get(0)), 4)
430
436
 
431
 
        k.add_lines('text1', ['text0'], ["line the first",
 
437
        k.add([0], ["line the first",
432
438
                   "fine"])
433
439
 
434
 
        self.assertEqual(k.get_lines(1),
 
440
        self.assertEqual(k.get(1),
435
441
                         ["line the first",
436
442
                          "fine"])
437
443
 
438
 
        self.assertEqual(k.annotate('text1'),
439
 
                         [('text0', "line the first"),
440
 
                          ('text0', "fine")])
 
444
        self.assertEqual(k.annotate(1),
 
445
                         [(0, "line the first"),
 
446
                          (0, "fine")])
 
447
 
441
448
 
442
449
 
443
450
class IncludeVersions(TestBase):
453
460
    def runTest(self):
454
461
        k = Weave()
455
462
 
456
 
        k._parents = [frozenset(), frozenset([0])]
457
 
        k._weave = [('{', 0),
 
463
        k._v = [frozenset(), frozenset([0])]
 
464
        k._l = [('{', 0),
458
465
                "first line",
459
466
                ('}', 0),
460
467
                ('{', 1),
461
468
                "second line",
462
469
                ('}', 1)]
463
470
 
464
 
        k._sha1s = [sha_string('first line')
465
 
                  , sha_string('first linesecond line')]
466
 
 
467
 
        self.assertEqual(k.get_lines(1),
 
471
        self.assertEqual(k.get(1),
468
472
                         ["first line",
469
473
                          "second line"])
470
474
 
471
 
        self.assertEqual(k.get_lines(0),
 
475
        self.assertEqual(k.get(0),
472
476
                         ["first line"])
473
477
 
 
478
        k.dump(self.TEST_LOG)
 
479
 
474
480
 
475
481
class DivergedIncludes(TestBase):
476
482
    """Weave with two diverged texts based on version 0.
477
483
    """
478
484
    def runTest(self):
479
 
        # FIXME make the weave, dont poke at it.
480
485
        k = Weave()
481
486
 
482
 
        k._names = ['0', '1', '2']
483
 
        k._name_map = {'0':0, '1':1, '2':2}
484
 
        k._parents = [frozenset(),
 
487
        k._v = [frozenset(),
485
488
                frozenset([0]),
486
489
                frozenset([0]),
487
490
                ]
488
 
        k._weave = [('{', 0),
 
491
        k._l = [('{', 0),
489
492
                "first line",
490
493
                ('}', 0),
491
494
                ('{', 1),
493
496
                ('}', 1),
494
497
                ('{', 2),
495
498
                "alternative second line",
496
 
                ('}', 2),
 
499
                ('}', 2),                
497
500
                ]
498
501
 
499
 
        k._sha1s = [sha_string('first line')
500
 
                  , sha_string('first linesecond line')
501
 
                  , sha_string('first linealternative second line')]
502
 
 
503
 
        self.assertEqual(k.get_lines(0),
 
502
        self.assertEqual(k.get(0),
504
503
                         ["first line"])
505
504
 
506
 
        self.assertEqual(k.get_lines(1),
 
505
        self.assertEqual(k.get(1),
507
506
                         ["first line",
508
507
                          "second line"])
509
508
 
510
 
        self.assertEqual(k.get_lines('2'),
 
509
        self.assertEqual(k.get(2),
511
510
                         ["first line",
512
511
                          "alternative second line"])
513
512
 
514
 
        self.assertEqual(list(k.get_ancestry(['2'])),
515
 
                         ['0', '2'])
 
513
        self.assertEqual(k.inclusions([2]),
 
514
                         set([0, 2]))
 
515
 
516
516
 
517
517
 
518
518
class ReplaceLine(TestBase):
521
521
 
522
522
        text0 = ['cheddar', 'stilton', 'gruyere']
523
523
        text1 = ['cheddar', 'blue vein', 'neufchatel', 'chevre']
524
 
 
525
 
        k.add_lines('text0', [], text0)
526
 
        k.add_lines('text1', ['text0'], text1)
527
 
 
528
 
        self.log('k._weave=' + pformat(k._weave))
529
 
 
530
 
        self.assertEqual(k.get_lines(0), text0)
531
 
        self.assertEqual(k.get_lines(1), text1)
 
524
        
 
525
        k.add([], text0)
 
526
        k.add([0], text1)
 
527
 
 
528
        self.log('k._l=' + pformat(k._l))
 
529
 
 
530
        self.assertEqual(k.get(0), text0)
 
531
        self.assertEqual(k.get(1), text1)
 
532
 
532
533
 
533
534
 
534
535
class Merge(TestBase):
542
543
                 ['header', '', 'line from 1', 'fixup line', 'line from 2'],
543
544
                 ]
544
545
 
545
 
        k.add_lines('text0', [], texts[0])
546
 
        k.add_lines('text1', ['text0'], texts[1])
547
 
        k.add_lines('text2', ['text0'], texts[2])
548
 
        k.add_lines('merge', ['text0', 'text1', 'text2'], texts[3])
 
546
        k.add([], texts[0])
 
547
        k.add([0], texts[1])
 
548
        k.add([0], texts[2])
 
549
        k.add([0, 1, 2], texts[3])
549
550
 
550
551
        for i, t in enumerate(texts):
551
 
            self.assertEqual(k.get_lines(i), t)
 
552
            self.assertEqual(k.get(i), t)
552
553
 
553
 
        self.assertEqual(k.annotate('merge'),
554
 
                         [('text0', 'header'),
555
 
                          ('text1', ''),
556
 
                          ('text1', 'line from 1'),
557
 
                          ('merge', 'fixup line'),
558
 
                          ('text2', 'line from 2'),
 
554
        self.assertEqual(k.annotate(3),
 
555
                         [(0, 'header'),
 
556
                          (1, ''),
 
557
                          (1, 'line from 1'),
 
558
                          (3, 'fixup line'),
 
559
                          (2, 'line from 2'),
559
560
                          ])
560
561
 
561
 
        self.assertEqual(list(k.get_ancestry(['merge'])),
562
 
                         ['text0', 'text1', 'text2', 'merge'])
 
562
        self.assertEqual(k.inclusions([3]),
 
563
                         set([0, 1, 2, 3]))
563
564
 
564
 
        self.log('k._weave=' + pformat(k._weave))
 
565
        self.log('k._l=' + pformat(k._l))
565
566
 
566
567
        self.check_read_write(k)
567
568
 
576
577
        return  # NOT RUN
577
578
        k = Weave()
578
579
 
579
 
        k.add_lines([], ['aaa', 'bbb'])
580
 
        k.add_lines([0], ['aaa', '111', 'bbb'])
581
 
        k.add_lines([1], ['aaa', '222', 'bbb'])
 
580
        k.add([], ['aaa', 'bbb'])
 
581
        k.add([0], ['aaa', '111', 'bbb'])
 
582
        k.add([1], ['aaa', '222', 'bbb'])
582
583
 
583
584
        merged = k.merge([1, 2])
584
585
 
587
588
                           [['bbb']]])
588
589
 
589
590
 
 
591
 
590
592
class NonConflict(TestBase):
591
593
    """Two descendants insert compatible changes.
592
594
 
595
597
        return  # NOT RUN
596
598
        k = Weave()
597
599
 
598
 
        k.add_lines([], ['aaa', 'bbb'])
599
 
        k.add_lines([0], ['111', 'aaa', 'ccc', 'bbb'])
600
 
        k.add_lines([1], ['aaa', 'ccc', 'bbb', '222'])
 
600
        k.add([], ['aaa', 'bbb'])
 
601
        k.add([0], ['111', 'aaa', 'ccc', 'bbb'])
 
602
        k.add([1], ['aaa', 'ccc', 'bbb', '222'])
 
603
 
 
604
    
 
605
    
 
606
 
 
607
 
 
608
class AutoMerge(TestBase):
 
609
    def runTest(self):
 
610
        k = Weave()
 
611
 
 
612
        texts = [['header', 'aaa', 'bbb'],
 
613
                 ['header', 'aaa', 'line from 1', 'bbb'],
 
614
                 ['header', 'aaa', 'bbb', 'line from 2', 'more from 2'],
 
615
                 ]
 
616
 
 
617
        k.add([], texts[0])
 
618
        k.add([0], texts[1])
 
619
        k.add([0], texts[2])
 
620
 
 
621
        self.log('k._l=' + pformat(k._l))
 
622
 
 
623
        m = list(k.mash_iter([0, 1, 2]))
 
624
 
 
625
        self.assertEqual(m,
 
626
                         ['header', 'aaa',
 
627
                          'line from 1',
 
628
                          'bbb',
 
629
                          'line from 2', 'more from 2'])
 
630
        
601
631
 
602
632
 
603
633
class Khayyam(TestBase):
604
634
    """Test changes to multi-line texts, and read/write"""
605
 
 
606
 
    def test_multi_line_merge(self):
 
635
    def runTest(self):
607
636
        rawtexts = [
608
637
            """A Book of Verses underneath the Bough,
609
638
            A Jug of Wine, a Loaf of Bread, -- and Thou
610
639
            Beside me singing in the Wilderness --
611
640
            Oh, Wilderness were Paradise enow!""",
612
 
 
 
641
            
613
642
            """A Book of Verses underneath the Bough,
614
643
            A Jug of Wine, a Loaf of Bread, -- and Thou
615
644
            Beside me singing in the Wilderness --
633
662
 
634
663
        k = Weave()
635
664
        parents = set()
636
 
        i = 0
637
665
        for t in texts:
638
 
            ver = k.add_lines('text%d' % i,
639
 
                        list(parents), t)
640
 
            parents.add('text%d' % i)
641
 
            i += 1
 
666
            ver = k.add(list(parents), t)
 
667
            parents.add(ver)
642
668
 
643
 
        self.log("k._weave=" + pformat(k._weave))
 
669
        self.log("k._l=" + pformat(k._l))
644
670
 
645
671
        for i, t in enumerate(texts):
646
 
            self.assertEqual(k.get_lines(i), t)
 
672
            self.assertEqual(k.get(i), t)
647
673
 
648
674
        self.check_read_write(k)
649
675
 
650
676
 
651
 
class JoinWeavesTests(TestBase):
652
 
    def setUp(self):
653
 
        super(JoinWeavesTests, self).setUp()
654
 
        self.weave1 = Weave()
655
 
        self.lines1 = ['hello\n']
656
 
        self.lines3 = ['hello\n', 'cruel\n', 'world\n']
657
 
        self.weave1.add_lines('v1', [], self.lines1)
658
 
        self.weave1.add_lines('v2', ['v1'], ['hello\n', 'world\n'])
659
 
        self.weave1.add_lines('v3', ['v2'], self.lines3)
660
 
 
661
 
    def test_written_detection(self):
662
 
        # Test detection of weave file corruption.
663
 
        #
664
 
        # Make sure that we can detect if a weave file has
665
 
        # been corrupted. This doesn't test all forms of corruption,
666
 
        # but it at least helps verify the data you get, is what you want.
667
 
        from cStringIO import StringIO
668
 
 
669
 
        w = Weave()
670
 
        w.add_lines('v1', [], ['hello\n'])
671
 
        w.add_lines('v2', ['v1'], ['hello\n', 'there\n'])
672
 
 
673
 
        tmpf = StringIO()
674
 
        write_weave(w, tmpf)
675
 
 
676
 
        # Because we are corrupting, we need to make sure we have the exact text
677
 
        self.assertEquals('# bzr weave file v5\n'
678
 
                          'i\n1 f572d396fae9206628714fb2ce00f72e94f2258f\nn v1\n\n'
679
 
                          'i 0\n1 90f265c6e75f1c8f9ab76dcf85528352c5f215ef\nn v2\n\n'
680
 
                          'w\n{ 0\n. hello\n}\n{ 1\n. there\n}\nW\n',
681
 
                          tmpf.getvalue())
682
 
 
683
 
        # Change a single letter
684
 
        tmpf = StringIO('# bzr weave file v5\n'
685
 
                        'i\n1 f572d396fae9206628714fb2ce00f72e94f2258f\nn v1\n\n'
686
 
                        'i 0\n1 90f265c6e75f1c8f9ab76dcf85528352c5f215ef\nn v2\n\n'
687
 
                        'w\n{ 0\n. hello\n}\n{ 1\n. There\n}\nW\n')
688
 
 
689
 
        w = read_weave(tmpf)
690
 
 
691
 
        self.assertEqual('hello\n', w.get_text('v1'))
692
 
        self.assertRaises(errors.WeaveInvalidChecksum, w.get_text, 'v2')
693
 
        self.assertRaises(errors.WeaveInvalidChecksum, w.get_lines, 'v2')
694
 
        self.assertRaises(errors.WeaveInvalidChecksum, w.check)
695
 
 
696
 
        # Change the sha checksum
697
 
        tmpf = StringIO('# bzr weave file v5\n'
698
 
                        'i\n1 f572d396fae9206628714fb2ce00f72e94f2258f\nn v1\n\n'
699
 
                        'i 0\n1 f0f265c6e75f1c8f9ab76dcf85528352c5f215ef\nn v2\n\n'
700
 
                        'w\n{ 0\n. hello\n}\n{ 1\n. there\n}\nW\n')
701
 
 
702
 
        w = read_weave(tmpf)
703
 
 
704
 
        self.assertEqual('hello\n', w.get_text('v1'))
705
 
        self.assertRaises(errors.WeaveInvalidChecksum, w.get_text, 'v2')
706
 
        self.assertRaises(errors.WeaveInvalidChecksum, w.get_lines, 'v2')
707
 
        self.assertRaises(errors.WeaveInvalidChecksum, w.check)
708
 
 
709
 
 
710
 
class TestWeave(TestCase):
711
 
 
712
 
    def test_allow_reserved_false(self):
713
 
        w = Weave('name', allow_reserved=False)
714
 
        # Add lines is checked at the WeaveFile level, not at the Weave level
715
 
        w.add_lines('name:', [], TEXT_1)
716
 
        # But get_lines is checked at this level
717
 
        self.assertRaises(errors.ReservedId, w.get_lines, 'name:')
718
 
 
719
 
    def test_allow_reserved_true(self):
720
 
        w = Weave('name', allow_reserved=True)
721
 
        w.add_lines('name:', [], TEXT_1)
722
 
        self.assertEqual(TEXT_1, w.get_lines('name:'))
723
 
 
724
 
 
725
 
class InstrumentedWeave(Weave):
726
 
    """Keep track of how many times functions are called."""
727
 
 
728
 
    def __init__(self, weave_name=None):
729
 
        self._extract_count = 0
730
 
        Weave.__init__(self, weave_name=weave_name)
731
 
 
732
 
    def _extract(self, versions):
733
 
        self._extract_count += 1
734
 
        return Weave._extract(self, versions)
735
 
 
736
 
 
737
 
class TestNeedsReweave(TestCase):
738
 
    """Internal corner cases for when reweave is needed."""
739
 
 
740
 
    def test_compatible_parents(self):
741
 
        w1 = Weave('a')
742
 
        my_parents = set([1, 2, 3])
743
 
        # subsets are ok
744
 
        self.assertTrue(w1._compatible_parents(my_parents, set([3])))
745
 
        # same sets
746
 
        self.assertTrue(w1._compatible_parents(my_parents, set(my_parents)))
747
 
        # same empty corner case
748
 
        self.assertTrue(w1._compatible_parents(set(), set()))
749
 
        # other cannot contain stuff my_parents does not
750
 
        self.assertFalse(w1._compatible_parents(set(), set([1])))
751
 
        self.assertFalse(w1._compatible_parents(my_parents, set([1, 2, 3, 4])))
752
 
        self.assertFalse(w1._compatible_parents(my_parents, set([4])))
753
 
 
754
 
 
755
 
class TestWeaveFile(TestCaseInTempDir):
756
 
 
757
 
    def test_empty_file(self):
758
 
        f = open('empty.weave', 'wb+')
759
 
        try:
760
 
            self.assertRaises(errors.WeaveFormatError,
761
 
                              read_weave, f)
762
 
        finally:
763
 
            f.close()
 
677
def testweave():
 
678
    import testsweet
 
679
    from unittest import TestSuite, TestLoader
 
680
    import testweave
 
681
 
 
682
    tl = TestLoader()
 
683
    suite = TestSuite()
 
684
    suite.addTest(tl.loadTestsFromModule(testweave))
 
685
    
 
686
    return int(not testsweet.run_suite(suite)) # for shell 0=true
 
687
 
 
688
 
 
689
if __name__ == '__main__':
 
690
    import sys
 
691
    sys.exit(testweave())
 
692