~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 06:58:16 UTC
  • Revision ID: mbp@sourcefrog.net-20050711065816-a9c5ed61078e5708
- more selftest external-command fixes

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',
226
250
                ]
227
251
        ################################### SKIPPED
228
252
        # Weave.get doesn't trap this anymore
229
 
        return
 
253
        return 
230
254
 
231
255
        self.assertRaises(WeaveFormatError,
232
 
                          k.get_lines,
233
 
                          0)
 
256
                          k.get,
 
257
                          0)        
 
258
 
234
259
 
235
260
 
236
261
class CannedDelete(TestBase):
238
263
    def runTest(self):
239
264
        k = Weave()
240
265
 
241
 
        k._parents = [(),
 
266
        k._v = [(),
242
267
                frozenset([0]),
243
268
                ]
244
 
        k._weave = [('{', 0),
 
269
        k._l = [('{', 0),
245
270
                'first line',
246
271
                ('[', 1),
247
272
                'line to be deleted',
249
274
                'last line',
250
275
                ('}', 0),
251
276
                ]
252
 
        k._sha1s = [sha_string('first lineline to be deletedlast line')
253
 
                  , sha_string('first linelast line')]
254
277
 
255
 
        self.assertEqual(k.get_lines(0),
 
278
        self.assertEqual(k.get(0),
256
279
                         ['first line',
257
280
                          'line to be deleted',
258
281
                          'last line',
259
282
                          ])
260
283
 
261
 
        self.assertEqual(k.get_lines(1),
 
284
        self.assertEqual(k.get(1),
262
285
                         ['first line',
263
286
                          'last line',
264
287
                          ])
265
288
 
266
289
 
 
290
 
267
291
class CannedReplacement(TestBase):
268
292
    """Unpack canned weave with deleted lines."""
269
293
    def runTest(self):
270
294
        k = Weave()
271
295
 
272
 
        k._parents = [frozenset(),
 
296
        k._v = [frozenset(),
273
297
                frozenset([0]),
274
298
                ]
275
 
        k._weave = [('{', 0),
 
299
        k._l = [('{', 0),
276
300
                'first line',
277
301
                ('[', 1),
278
302
                'line to be deleted',
279
303
                (']', 1),
280
304
                ('{', 1),
281
 
                'replacement line',
 
305
                'replacement line',                
282
306
                ('}', 1),
283
307
                'last line',
284
308
                ('}', 0),
285
309
                ]
286
 
        k._sha1s = [sha_string('first lineline to be deletedlast line')
287
 
                  , sha_string('first linereplacement linelast line')]
288
310
 
289
 
        self.assertEqual(k.get_lines(0),
 
311
        self.assertEqual(k.get(0),
290
312
                         ['first line',
291
313
                          'line to be deleted',
292
314
                          'last line',
293
315
                          ])
294
316
 
295
 
        self.assertEqual(k.get_lines(1),
 
317
        self.assertEqual(k.get(1),
296
318
                         ['first line',
297
319
                          'replacement line',
298
320
                          'last line',
299
321
                          ])
300
322
 
301
323
 
 
324
 
302
325
class BadWeave(TestBase):
303
326
    """Test that we trap an insert which should not occur."""
304
327
    def runTest(self):
305
328
        k = Weave()
306
329
 
307
 
        k._parents = [frozenset(),
 
330
        k._v = [frozenset(),
308
331
                ]
309
 
        k._weave = ['bad line',
 
332
        k._l = ['bad line',
310
333
                ('{', 0),
311
334
                'foo {',
312
335
                ('{', 1),
321
344
 
322
345
        ################################### SKIPPED
323
346
        # Weave.get doesn't trap this anymore
324
 
        return
 
347
        return 
325
348
 
326
349
 
327
350
        self.assertRaises(WeaveFormatError,
334
357
    def runTest(self):
335
358
        k = Weave()
336
359
 
337
 
        k._parents = [frozenset(),
 
360
        k._v = [frozenset(),
338
361
                frozenset([0]),
339
362
                frozenset([0]),
340
363
                frozenset([0,1,2]),
341
364
                ]
342
 
        k._weave = [('{', 0),
 
365
        k._l = [('{', 0),
343
366
                'foo {',
344
367
                ('{', 1),
345
368
                '  added in version 1',
367
390
    def runTest(self):
368
391
        k = Weave()
369
392
 
370
 
        k._parents = [frozenset(),
 
393
        k._v = [frozenset(),
371
394
                frozenset([0]),
372
395
                frozenset([0]),
373
396
                frozenset([0,1,2]),
374
397
                ]
375
 
        k._weave = [('{', 0),
 
398
        k._l = [('{', 0),
376
399
                'foo {',
377
400
                ('{', 1),
378
401
                '  added in version 1',
384
407
                '}',
385
408
                ('}', 0)]
386
409
 
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
 
                          '}'])
 
410
        self.assertEqual(k.get(0),
 
411
                         ['foo {',
 
412
                          '}'])
 
413
 
 
414
        self.assertEqual(k.get(1),
 
415
                         ['foo {',
 
416
                          '  added in version 1',
 
417
                          '  also from v1',
 
418
                          '}'])
 
419
                       
 
420
        self.assertEqual(k.get(2),
 
421
                         ['foo {',
 
422
                          '  added in v2',
 
423
                          '}'])
 
424
 
 
425
        self.assertEqual(k.get(3),
 
426
                         ['foo {',
 
427
                          '  added in version 1',
 
428
                          '  added in v2',
 
429
                          '  also from v1',
 
430
                          '}'])
 
431
                         
414
432
 
415
433
 
416
434
class DeleteLines2(TestBase):
421
439
    def runTest(self):
422
440
        k = Weave()
423
441
 
424
 
        k.add_lines('text0', [], ["line the first",
 
442
        k.add([], ["line the first",
425
443
                   "line 2",
426
444
                   "line 3",
427
445
                   "fine"])
428
446
 
429
 
        self.assertEqual(len(k.get_lines(0)), 4)
 
447
        self.assertEqual(len(k.get(0)), 4)
430
448
 
431
 
        k.add_lines('text1', ['text0'], ["line the first",
 
449
        k.add([0], ["line the first",
432
450
                   "fine"])
433
451
 
434
 
        self.assertEqual(k.get_lines(1),
 
452
        self.assertEqual(k.get(1),
435
453
                         ["line the first",
436
454
                          "fine"])
437
455
 
438
 
        self.assertEqual(k.annotate('text1'),
439
 
                         [('text0', "line the first"),
440
 
                          ('text0', "fine")])
 
456
        self.assertEqual(k.annotate(1),
 
457
                         [(0, "line the first"),
 
458
                          (0, "fine")])
 
459
 
441
460
 
442
461
 
443
462
class IncludeVersions(TestBase):
453
472
    def runTest(self):
454
473
        k = Weave()
455
474
 
456
 
        k._parents = [frozenset(), frozenset([0])]
457
 
        k._weave = [('{', 0),
 
475
        k._v = [frozenset(), frozenset([0])]
 
476
        k._l = [('{', 0),
458
477
                "first line",
459
478
                ('}', 0),
460
479
                ('{', 1),
461
480
                "second line",
462
481
                ('}', 1)]
463
482
 
464
 
        k._sha1s = [sha_string('first line')
465
 
                  , sha_string('first linesecond line')]
466
 
 
467
 
        self.assertEqual(k.get_lines(1),
 
483
        self.assertEqual(k.get(1),
468
484
                         ["first line",
469
485
                          "second line"])
470
486
 
471
 
        self.assertEqual(k.get_lines(0),
 
487
        self.assertEqual(k.get(0),
472
488
                         ["first line"])
473
489
 
 
490
        k.dump(self.TEST_LOG)
 
491
 
474
492
 
475
493
class DivergedIncludes(TestBase):
476
494
    """Weave with two diverged texts based on version 0.
477
495
    """
478
496
    def runTest(self):
479
 
        # FIXME make the weave, dont poke at it.
480
497
        k = Weave()
481
498
 
482
 
        k._names = ['0', '1', '2']
483
 
        k._name_map = {'0':0, '1':1, '2':2}
484
 
        k._parents = [frozenset(),
 
499
        k._v = [frozenset(),
485
500
                frozenset([0]),
486
501
                frozenset([0]),
487
502
                ]
488
 
        k._weave = [('{', 0),
 
503
        k._l = [('{', 0),
489
504
                "first line",
490
505
                ('}', 0),
491
506
                ('{', 1),
493
508
                ('}', 1),
494
509
                ('{', 2),
495
510
                "alternative second line",
496
 
                ('}', 2),
 
511
                ('}', 2),                
497
512
                ]
498
513
 
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),
 
514
        self.assertEqual(k.get(0),
504
515
                         ["first line"])
505
516
 
506
 
        self.assertEqual(k.get_lines(1),
 
517
        self.assertEqual(k.get(1),
507
518
                         ["first line",
508
519
                          "second line"])
509
520
 
510
 
        self.assertEqual(k.get_lines('2'),
 
521
        self.assertEqual(k.get(2),
511
522
                         ["first line",
512
523
                          "alternative second line"])
513
524
 
514
 
        self.assertEqual(list(k.get_ancestry(['2'])),
515
 
                         ['0', '2'])
 
525
        self.assertEqual(k.inclusions([2]),
 
526
                         set([0, 2]))
 
527
 
516
528
 
517
529
 
518
530
class ReplaceLine(TestBase):
521
533
 
522
534
        text0 = ['cheddar', 'stilton', 'gruyere']
523
535
        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)
 
536
        
 
537
        k.add([], text0)
 
538
        k.add([0], text1)
 
539
 
 
540
        self.log('k._l=' + pformat(k._l))
 
541
 
 
542
        self.assertEqual(k.get(0), text0)
 
543
        self.assertEqual(k.get(1), text1)
 
544
 
532
545
 
533
546
 
534
547
class Merge(TestBase):
542
555
                 ['header', '', 'line from 1', 'fixup line', 'line from 2'],
543
556
                 ]
544
557
 
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])
 
558
        k.add([], texts[0])
 
559
        k.add([0], texts[1])
 
560
        k.add([0], texts[2])
 
561
        k.add([0, 1, 2], texts[3])
549
562
 
550
563
        for i, t in enumerate(texts):
551
 
            self.assertEqual(k.get_lines(i), t)
 
564
            self.assertEqual(k.get(i), t)
552
565
 
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'),
 
566
        self.assertEqual(k.annotate(3),
 
567
                         [(0, 'header'),
 
568
                          (1, ''),
 
569
                          (1, 'line from 1'),
 
570
                          (3, 'fixup line'),
 
571
                          (2, 'line from 2'),
559
572
                          ])
560
573
 
561
 
        self.assertEqual(list(k.get_ancestry(['merge'])),
562
 
                         ['text0', 'text1', 'text2', 'merge'])
 
574
        self.assertEqual(k.inclusions([3]),
 
575
                         set([0, 1, 2, 3]))
563
576
 
564
 
        self.log('k._weave=' + pformat(k._weave))
 
577
        self.log('k._l=' + pformat(k._l))
565
578
 
566
579
        self.check_read_write(k)
567
580
 
576
589
        return  # NOT RUN
577
590
        k = Weave()
578
591
 
579
 
        k.add_lines([], ['aaa', 'bbb'])
580
 
        k.add_lines([0], ['aaa', '111', 'bbb'])
581
 
        k.add_lines([1], ['aaa', '222', 'bbb'])
 
592
        k.add([], ['aaa', 'bbb'])
 
593
        k.add([0], ['aaa', '111', 'bbb'])
 
594
        k.add([1], ['aaa', '222', 'bbb'])
582
595
 
583
596
        merged = k.merge([1, 2])
584
597
 
587
600
                           [['bbb']]])
588
601
 
589
602
 
 
603
 
590
604
class NonConflict(TestBase):
591
605
    """Two descendants insert compatible changes.
592
606
 
595
609
        return  # NOT RUN
596
610
        k = Weave()
597
611
 
598
 
        k.add_lines([], ['aaa', 'bbb'])
599
 
        k.add_lines([0], ['111', 'aaa', 'ccc', 'bbb'])
600
 
        k.add_lines([1], ['aaa', 'ccc', 'bbb', '222'])
 
612
        k.add([], ['aaa', 'bbb'])
 
613
        k.add([0], ['111', 'aaa', 'ccc', 'bbb'])
 
614
        k.add([1], ['aaa', 'ccc', 'bbb', '222'])
 
615
 
 
616
    
 
617
    
 
618
 
 
619
 
 
620
class AutoMerge(TestBase):
 
621
    def runTest(self):
 
622
        k = Weave()
 
623
 
 
624
        texts = [['header', 'aaa', 'bbb'],
 
625
                 ['header', 'aaa', 'line from 1', 'bbb'],
 
626
                 ['header', 'aaa', 'bbb', 'line from 2', 'more from 2'],
 
627
                 ]
 
628
 
 
629
        k.add([], texts[0])
 
630
        k.add([0], texts[1])
 
631
        k.add([0], texts[2])
 
632
 
 
633
        self.log('k._l=' + pformat(k._l))
 
634
 
 
635
        m = list(k.mash_iter([0, 1, 2]))
 
636
 
 
637
        self.assertEqual(m,
 
638
                         ['header', 'aaa',
 
639
                          'line from 1',
 
640
                          'bbb',
 
641
                          'line from 2', 'more from 2'])
 
642
        
601
643
 
602
644
 
603
645
class Khayyam(TestBase):
604
646
    """Test changes to multi-line texts, and read/write"""
605
 
 
606
 
    def test_multi_line_merge(self):
 
647
    def runTest(self):
607
648
        rawtexts = [
608
649
            """A Book of Verses underneath the Bough,
609
650
            A Jug of Wine, a Loaf of Bread, -- and Thou
610
651
            Beside me singing in the Wilderness --
611
652
            Oh, Wilderness were Paradise enow!""",
612
 
 
 
653
            
613
654
            """A Book of Verses underneath the Bough,
614
655
            A Jug of Wine, a Loaf of Bread, -- and Thou
615
656
            Beside me singing in the Wilderness --
633
674
 
634
675
        k = Weave()
635
676
        parents = set()
636
 
        i = 0
637
677
        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
 
678
            ver = k.add(list(parents), t)
 
679
            parents.add(ver)
642
680
 
643
 
        self.log("k._weave=" + pformat(k._weave))
 
681
        self.log("k._l=" + pformat(k._l))
644
682
 
645
683
        for i, t in enumerate(texts):
646
 
            self.assertEqual(k.get_lines(i), t)
 
684
            self.assertEqual(k.get(i), t)
647
685
 
648
686
        self.check_read_write(k)
649
687
 
650
688
 
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()
 
689
def testweave():
 
690
    import testsweet
 
691
    from unittest import TestSuite, TestLoader
 
692
    import testweave
 
693
 
 
694
    tl = TestLoader()
 
695
    suite = TestSuite()
 
696
    suite.addTest(tl.loadTestsFromModule(testweave))
 
697
    
 
698
    return int(not testsweet.run_suite(suite)) # for shell 0=true
 
699
 
 
700
 
 
701
if __name__ == '__main__':
 
702
    import sys
 
703
    sys.exit(testweave())
 
704