/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to brzlib/tests/test_weave.py

  • Committer: Jelmer Vernooij
  • Date: 2017-05-21 12:41:27 UTC
  • mto: This revision was merged to the branch mainline in revision 6623.
  • Revision ID: jelmer@jelmer.uk-20170521124127-iv8etg0vwymyai6y
s/bzr/brz/ in apport config.

Show diffs side-by-side

added added

removed removed

Lines of Context:
21
21
 
22
22
"""test suite for weave algorithm"""
23
23
 
24
 
from io import BytesIO
25
24
from pprint import pformat
26
25
 
27
 
from .. import (
 
26
from brzlib import (
28
27
    errors,
29
28
    )
30
 
from ..osutils import sha_string
31
 
from . import TestCase, TestCaseInTempDir
32
 
from ..bzr.weave import Weave, WeaveFormatError, WeaveInvalidChecksum
33
 
from ..bzr.weavefile import write_weave, read_weave
 
29
from brzlib.osutils import sha_string
 
30
from brzlib.tests import TestCase, TestCaseInTempDir
 
31
from brzlib.weave import Weave, WeaveFormatError
 
32
from brzlib.weavefile import write_weave, read_weave
34
33
 
35
34
 
36
35
# texts for use in testing
37
 
TEXT_0 = [b"Hello world"]
38
 
TEXT_1 = [b"Hello world",
39
 
          b"A second line"]
 
36
TEXT_0 = ["Hello world"]
 
37
TEXT_1 = ["Hello world",
 
38
          "A second line"]
40
39
 
41
40
 
42
41
class TestBase(TestCase):
67
66
    """Weave __contains__ operator"""
68
67
 
69
68
    def runTest(self):
70
 
        k = Weave(get_scope=lambda: None)
71
 
        self.assertFalse(b'foo' in k)
72
 
        k.add_lines(b'foo', [], TEXT_1)
73
 
        self.assertTrue(b'foo' in k)
 
69
        k = Weave(get_scope=lambda:None)
 
70
        self.assertFalse('foo' in k)
 
71
        k.add_lines('foo', [], TEXT_1)
 
72
        self.assertTrue('foo' in k)
74
73
 
75
74
 
76
75
class Easy(TestBase):
77
76
 
78
77
    def runTest(self):
79
 
        Weave()
 
78
        k = Weave()
80
79
 
81
80
 
82
81
class AnnotateOne(TestBase):
83
82
 
84
83
    def runTest(self):
85
84
        k = Weave()
86
 
        k.add_lines(b'text0', [], TEXT_0)
87
 
        self.assertEqual(k.annotate(b'text0'),
88
 
                         [(b'text0', TEXT_0[0])])
 
85
        k.add_lines('text0', [], TEXT_0)
 
86
        self.assertEqual(k.annotate('text0'),
 
87
                         [('text0', TEXT_0[0])])
89
88
 
90
89
 
91
90
class InvalidAdd(TestBase):
96
95
 
97
96
        self.assertRaises(errors.RevisionNotPresent,
98
97
                          k.add_lines,
99
 
                          b'text0',
100
 
                          [b'69'],
101
 
                          [b'new text!'])
 
98
                          'text0',
 
99
                          ['69'],
 
100
                          ['new text!'])
102
101
 
103
102
 
104
103
class RepeatedAdd(TestBase):
106
105
 
107
106
    def test_duplicate_add(self):
108
107
        k = Weave()
109
 
        idx = k.add_lines(b'text0', [], TEXT_0)
110
 
        idx2 = k.add_lines(b'text0', [], TEXT_0)
 
108
        idx = k.add_lines('text0', [], TEXT_0)
 
109
        idx2 = k.add_lines('text0', [], TEXT_0)
111
110
        self.assertEqual(idx, idx2)
112
111
 
113
112
 
115
114
 
116
115
    def runTest(self):
117
116
        k = Weave()
118
 
        k.add_lines(b'basis', [], TEXT_0)
119
 
        k.add_lines(b'text0', [], TEXT_0)
 
117
        k.add_lines('basis', [], TEXT_0)
 
118
        idx = k.add_lines('text0', [], TEXT_0)
120
119
        self.assertRaises(errors.RevisionAlreadyPresent,
121
120
                          k.add_lines,
122
 
                          b'text0',
 
121
                          'text0',
123
122
                          [],
124
 
                          [b'not the same text'])
 
123
                          ['not the same text'])
125
124
        self.assertRaises(errors.RevisionAlreadyPresent,
126
125
                          k.add_lines,
127
 
                          b'text0',
128
 
                          [b'basis'],         # not the right parents
 
126
                          'text0',
 
127
                          ['basis'],         # not the right parents
129
128
                          TEXT_0)
130
129
 
131
130
 
134
133
 
135
134
    Look at the annotations to make sure that the first line is matched
136
135
    and not stored repeatedly."""
137
 
 
138
136
    def runTest(self):
139
137
        k = Weave()
140
138
 
141
 
        k.add_lines(b'text0', [], [b'line 1'])
142
 
        k.add_lines(b'text1', [b'text0'], [b'line 1', b'line 2'])
 
139
        k.add_lines('text0', [], ['line 1'])
 
140
        k.add_lines('text1', ['text0'], ['line 1', 'line 2'])
143
141
 
144
 
        self.assertEqual(k.annotate(b'text0'),
145
 
                         [(b'text0', b'line 1')])
 
142
        self.assertEqual(k.annotate('text0'),
 
143
                         [('text0', 'line 1')])
146
144
 
147
145
        self.assertEqual(k.get_lines(1),
148
 
                         [b'line 1',
149
 
                          b'line 2'])
150
 
 
151
 
        self.assertEqual(k.annotate(b'text1'),
152
 
                         [(b'text0', b'line 1'),
153
 
                          (b'text1', b'line 2')])
154
 
 
155
 
        k.add_lines(b'text2', [b'text0'], [b'line 1', b'diverged line'])
156
 
 
157
 
        self.assertEqual(k.annotate(b'text2'),
158
 
                         [(b'text0', b'line 1'),
159
 
                          (b'text2', b'diverged line')])
160
 
 
161
 
        text3 = [b'line 1', b'middle line', b'line 2']
162
 
        k.add_lines(b'text3',
163
 
                    [b'text0', b'text1'],
164
 
                    text3)
165
 
 
166
 
        # self.log("changes to text3: " + pformat(list(k._delta(set([0, 1]),
167
 
        # text3))))
 
146
                         ['line 1',
 
147
                          'line 2'])
 
148
 
 
149
        self.assertEqual(k.annotate('text1'),
 
150
                         [('text0', 'line 1'),
 
151
                          ('text1', 'line 2')])
 
152
 
 
153
        k.add_lines('text2', ['text0'], ['line 1', 'diverged line'])
 
154
 
 
155
        self.assertEqual(k.annotate('text2'),
 
156
                         [('text0', 'line 1'),
 
157
                          ('text2', 'diverged line')])
 
158
 
 
159
        text3 = ['line 1', 'middle line', 'line 2']
 
160
        k.add_lines('text3',
 
161
              ['text0', 'text1'],
 
162
              text3)
 
163
 
 
164
        # self.log("changes to text3: " + pformat(list(k._delta(set([0, 1]), text3))))
168
165
 
169
166
        self.log("k._weave=" + pformat(k._weave))
170
167
 
171
 
        self.assertEqual(k.annotate(b'text3'),
172
 
                         [(b'text0', b'line 1'),
173
 
                          (b'text3', b'middle line'),
174
 
                          (b'text1', b'line 2')])
 
168
        self.assertEqual(k.annotate('text3'),
 
169
                         [('text0', 'line 1'),
 
170
                          ('text3', 'middle line'),
 
171
                          ('text1', 'line 2')])
175
172
 
176
173
        # now multiple insertions at different places
177
 
        k.add_lines(
178
 
            b'text4', [b'text0', b'text1', b'text3'],
179
 
            [b'line 1', b'aaa', b'middle line', b'bbb', b'line 2', b'ccc'])
 
174
        k.add_lines('text4',
 
175
              ['text0', 'text1', 'text3'],
 
176
              ['line 1', 'aaa', 'middle line', 'bbb', 'line 2', 'ccc'])
180
177
 
181
 
        self.assertEqual(k.annotate(b'text4'),
182
 
                         [(b'text0', b'line 1'),
183
 
                          (b'text4', b'aaa'),
184
 
                          (b'text3', b'middle line'),
185
 
                          (b'text4', b'bbb'),
186
 
                          (b'text1', b'line 2'),
187
 
                          (b'text4', b'ccc')])
 
178
        self.assertEqual(k.annotate('text4'),
 
179
                         [('text0', 'line 1'),
 
180
                          ('text4', 'aaa'),
 
181
                          ('text3', 'middle line'),
 
182
                          ('text4', 'bbb'),
 
183
                          ('text1', 'line 2'),
 
184
                          ('text4', 'ccc')])
188
185
 
189
186
 
190
187
class DeleteLines(TestBase):
191
188
    """Deletion of lines from existing text.
192
189
 
193
190
    Try various texts all based on a common ancestor."""
194
 
 
195
191
    def runTest(self):
196
192
        k = Weave()
197
193
 
198
 
        base_text = [b'one', b'two', b'three', b'four']
199
 
 
200
 
        k.add_lines(b'text0', [], base_text)
201
 
 
202
 
        texts = [[b'one', b'two', b'three'],
203
 
                 [b'two', b'three', b'four'],
204
 
                 [b'one', b'four'],
205
 
                 [b'one', b'two', b'three', b'four'],
 
194
        base_text = ['one', 'two', 'three', 'four']
 
195
 
 
196
        k.add_lines('text0', [], base_text)
 
197
 
 
198
        texts = [['one', 'two', 'three'],
 
199
                 ['two', 'three', 'four'],
 
200
                 ['one', 'four'],
 
201
                 ['one', 'two', 'three', 'four'],
206
202
                 ]
207
203
 
208
204
        i = 1
209
205
        for t in texts:
210
 
            k.add_lines(b'text%d' % i, [b'text0'], t)
 
206
            ver = k.add_lines('text%d' % i,
 
207
                        ['text0'], t)
211
208
            i += 1
212
209
 
213
210
        self.log('final weave:')
214
211
        self.log('k._weave=' + pformat(k._weave))
215
212
 
216
213
        for i in range(len(texts)):
217
 
            self.assertEqual(k.get_lines(i + 1),
 
214
            self.assertEqual(k.get_lines(i+1),
218
215
                             texts[i])
219
216
 
220
217
 
221
218
class SuicideDelete(TestBase):
222
219
    """Invalid weave which tries to add and delete simultaneously."""
223
 
 
224
220
    def runTest(self):
225
221
        k = Weave()
226
222
 
227
223
        k._parents = [(),
228
 
                      ]
229
 
        k._weave = [(b'{', 0),
230
 
                    b'first line',
231
 
                    (b'[', 0),
232
 
                    b'deleted in 0',
233
 
                    (b']', 0),
234
 
                    (b'}', 0),
235
 
                    ]
236
 
        # SKIPPED
 
224
                ]
 
225
        k._weave = [('{', 0),
 
226
                'first line',
 
227
                ('[', 0),
 
228
                'deleted in 0',
 
229
                (']', 0),
 
230
                ('}', 0),
 
231
                ]
 
232
        ################################### SKIPPED
237
233
        # Weave.get doesn't trap this anymore
238
234
        return
239
235
 
244
240
 
245
241
class CannedDelete(TestBase):
246
242
    """Unpack canned weave with deleted lines."""
247
 
 
248
243
    def runTest(self):
249
244
        k = Weave()
250
245
 
251
246
        k._parents = [(),
252
 
                      frozenset([0]),
253
 
                      ]
254
 
        k._weave = [(b'{', 0),
255
 
                    b'first line',
256
 
                    (b'[', 1),
257
 
                    b'line to be deleted',
258
 
                    (b']', 1),
259
 
                    b'last line',
260
 
                    (b'}', 0),
261
 
                    ]
262
 
        k._sha1s = [
263
 
            sha_string(b'first lineline to be deletedlast line'),
264
 
            sha_string(b'first linelast line')]
 
247
                frozenset([0]),
 
248
                ]
 
249
        k._weave = [('{', 0),
 
250
                'first line',
 
251
                ('[', 1),
 
252
                'line to be deleted',
 
253
                (']', 1),
 
254
                'last line',
 
255
                ('}', 0),
 
256
                ]
 
257
        k._sha1s = [sha_string('first lineline to be deletedlast line')
 
258
                  , sha_string('first linelast line')]
265
259
 
266
260
        self.assertEqual(k.get_lines(0),
267
 
                         [b'first line',
268
 
                          b'line to be deleted',
269
 
                          b'last line',
 
261
                         ['first line',
 
262
                          'line to be deleted',
 
263
                          'last line',
270
264
                          ])
271
265
 
272
266
        self.assertEqual(k.get_lines(1),
273
 
                         [b'first line',
274
 
                          b'last line',
 
267
                         ['first line',
 
268
                          'last line',
275
269
                          ])
276
270
 
277
271
 
278
272
class CannedReplacement(TestBase):
279
273
    """Unpack canned weave with deleted lines."""
280
 
 
281
274
    def runTest(self):
282
275
        k = Weave()
283
276
 
284
277
        k._parents = [frozenset(),
285
 
                      frozenset([0]),
286
 
                      ]
287
 
        k._weave = [(b'{', 0),
288
 
                    b'first line',
289
 
                    (b'[', 1),
290
 
                    b'line to be deleted',
291
 
                    (b']', 1),
292
 
                    (b'{', 1),
293
 
                    b'replacement line',
294
 
                    (b'}', 1),
295
 
                    b'last line',
296
 
                    (b'}', 0),
297
 
                    ]
298
 
        k._sha1s = [
299
 
            sha_string(b'first lineline to be deletedlast line'),
300
 
            sha_string(b'first linereplacement linelast line')]
 
278
                frozenset([0]),
 
279
                ]
 
280
        k._weave = [('{', 0),
 
281
                'first line',
 
282
                ('[', 1),
 
283
                'line to be deleted',
 
284
                (']', 1),
 
285
                ('{', 1),
 
286
                'replacement line',
 
287
                ('}', 1),
 
288
                'last line',
 
289
                ('}', 0),
 
290
                ]
 
291
        k._sha1s = [sha_string('first lineline to be deletedlast line')
 
292
                  , sha_string('first linereplacement linelast line')]
301
293
 
302
294
        self.assertEqual(k.get_lines(0),
303
 
                         [b'first line',
304
 
                          b'line to be deleted',
305
 
                          b'last line',
 
295
                         ['first line',
 
296
                          'line to be deleted',
 
297
                          'last line',
306
298
                          ])
307
299
 
308
300
        self.assertEqual(k.get_lines(1),
309
 
                         [b'first line',
310
 
                          b'replacement line',
311
 
                          b'last line',
 
301
                         ['first line',
 
302
                          'replacement line',
 
303
                          'last line',
312
304
                          ])
313
305
 
314
306
 
315
307
class BadWeave(TestBase):
316
308
    """Test that we trap an insert which should not occur."""
317
 
 
318
309
    def runTest(self):
319
310
        k = Weave()
320
311
 
321
312
        k._parents = [frozenset(),
322
 
                      ]
323
 
        k._weave = [b'bad line',
324
 
                    (b'{', 0),
325
 
                    b'foo {',
326
 
                    (b'{', 1),
327
 
                    b'  added in version 1',
328
 
                    (b'{', 2),
329
 
                    b'  added in v2',
330
 
                    (b'}', 2),
331
 
                    b'  also from v1',
332
 
                    (b'}', 1),
333
 
                    b'}',
334
 
                    (b'}', 0)]
 
313
                ]
 
314
        k._weave = ['bad line',
 
315
                ('{', 0),
 
316
                'foo {',
 
317
                ('{', 1),
 
318
                '  added in version 1',
 
319
                ('{', 2),
 
320
                '  added in v2',
 
321
                ('}', 2),
 
322
                '  also from v1',
 
323
                ('}', 1),
 
324
                '}',
 
325
                ('}', 0)]
335
326
 
336
 
        # SKIPPED
 
327
        ################################### SKIPPED
337
328
        # Weave.get doesn't trap this anymore
338
329
        return
339
330
 
 
331
 
340
332
        self.assertRaises(WeaveFormatError,
341
333
                          k.get,
342
334
                          0)
344
336
 
345
337
class BadInsert(TestBase):
346
338
    """Test that we trap an insert which should not occur."""
347
 
 
348
339
    def runTest(self):
349
340
        k = Weave()
350
341
 
351
342
        k._parents = [frozenset(),
352
 
                      frozenset([0]),
353
 
                      frozenset([0]),
354
 
                      frozenset([0, 1, 2]),
355
 
                      ]
356
 
        k._weave = [(b'{', 0),
357
 
                    b'foo {',
358
 
                    (b'{', 1),
359
 
                    b'  added in version 1',
360
 
                    (b'{', 1),
361
 
                    b'  more in 1',
362
 
                    (b'}', 1),
363
 
                    (b'}', 1),
364
 
                    (b'}', 0)]
 
343
                frozenset([0]),
 
344
                frozenset([0]),
 
345
                frozenset([0,1,2]),
 
346
                ]
 
347
        k._weave = [('{', 0),
 
348
                'foo {',
 
349
                ('{', 1),
 
350
                '  added in version 1',
 
351
                ('{', 1),
 
352
                '  more in 1',
 
353
                ('}', 1),
 
354
                ('}', 1),
 
355
                ('}', 0)]
 
356
 
365
357
 
366
358
        # this is not currently enforced by get
367
 
        return
 
359
        return  ##########################################
368
360
 
369
361
        self.assertRaises(WeaveFormatError,
370
362
                          k.get,
377
369
 
378
370
class InsertNested(TestBase):
379
371
    """Insertion with nested instructions."""
380
 
 
381
372
    def runTest(self):
382
373
        k = Weave()
383
374
 
384
375
        k._parents = [frozenset(),
385
 
                      frozenset([0]),
386
 
                      frozenset([0]),
387
 
                      frozenset([0, 1, 2]),
388
 
                      ]
389
 
        k._weave = [(b'{', 0),
390
 
                    b'foo {',
391
 
                    (b'{', 1),
392
 
                    b'  added in version 1',
393
 
                    (b'{', 2),
394
 
                    b'  added in v2',
395
 
                    (b'}', 2),
396
 
                    b'  also from v1',
397
 
                    (b'}', 1),
398
 
                    b'}',
399
 
                    (b'}', 0)]
 
376
                frozenset([0]),
 
377
                frozenset([0]),
 
378
                frozenset([0,1,2]),
 
379
                ]
 
380
        k._weave = [('{', 0),
 
381
                'foo {',
 
382
                ('{', 1),
 
383
                '  added in version 1',
 
384
                ('{', 2),
 
385
                '  added in v2',
 
386
                ('}', 2),
 
387
                '  also from v1',
 
388
                ('}', 1),
 
389
                '}',
 
390
                ('}', 0)]
400
391
 
401
 
        k._sha1s = [
402
 
            sha_string(b'foo {}'),
403
 
            sha_string(b'foo {  added in version 1  also from v1}'),
404
 
            sha_string(b'foo {  added in v2}'),
405
 
            sha_string(
406
 
                b'foo {  added in version 1  added in v2  also from v1}')
407
 
            ]
 
392
        k._sha1s = [sha_string('foo {}')
 
393
                  , sha_string('foo {  added in version 1  also from v1}')
 
394
                  , sha_string('foo {  added in v2}')
 
395
                  , sha_string('foo {  added in version 1  added in v2  also from v1}')
 
396
                  ]
408
397
 
409
398
        self.assertEqual(k.get_lines(0),
410
 
                         [b'foo {',
411
 
                          b'}'])
 
399
                         ['foo {',
 
400
                          '}'])
412
401
 
413
402
        self.assertEqual(k.get_lines(1),
414
 
                         [b'foo {',
415
 
                          b'  added in version 1',
416
 
                          b'  also from v1',
417
 
                          b'}'])
 
403
                         ['foo {',
 
404
                          '  added in version 1',
 
405
                          '  also from v1',
 
406
                          '}'])
418
407
 
419
408
        self.assertEqual(k.get_lines(2),
420
 
                         [b'foo {',
421
 
                          b'  added in v2',
422
 
                          b'}'])
 
409
                         ['foo {',
 
410
                          '  added in v2',
 
411
                          '}'])
423
412
 
424
413
        self.assertEqual(k.get_lines(3),
425
 
                         [b'foo {',
426
 
                          b'  added in version 1',
427
 
                          b'  added in v2',
428
 
                          b'  also from v1',
429
 
                          b'}'])
 
414
                         ['foo {',
 
415
                          '  added in version 1',
 
416
                          '  added in v2',
 
417
                          '  also from v1',
 
418
                          '}'])
430
419
 
431
420
 
432
421
class DeleteLines2(TestBase):
434
423
 
435
424
    This relies on the weave having a way to represent lines knocked
436
425
    out by a later revision."""
437
 
 
438
426
    def runTest(self):
439
427
        k = Weave()
440
428
 
441
 
        k.add_lines(b'text0', [], [b"line the first",
442
 
                                   b"line 2",
443
 
                                   b"line 3",
444
 
                                   b"fine"])
 
429
        k.add_lines('text0', [], ["line the first",
 
430
                   "line 2",
 
431
                   "line 3",
 
432
                   "fine"])
445
433
 
446
434
        self.assertEqual(len(k.get_lines(0)), 4)
447
435
 
448
 
        k.add_lines(b'text1', [b'text0'], [b"line the first",
449
 
                                           b"fine"])
 
436
        k.add_lines('text1', ['text0'], ["line the first",
 
437
                   "fine"])
450
438
 
451
439
        self.assertEqual(k.get_lines(1),
452
 
                         [b"line the first",
453
 
                          b"fine"])
 
440
                         ["line the first",
 
441
                          "fine"])
454
442
 
455
 
        self.assertEqual(k.annotate(b'text1'),
456
 
                         [(b'text0', b"line the first"),
457
 
                          (b'text0', b"fine")])
 
443
        self.assertEqual(k.annotate('text1'),
 
444
                         [('text0', "line the first"),
 
445
                          ('text0', "fine")])
458
446
 
459
447
 
460
448
class IncludeVersions(TestBase):
471
459
        k = Weave()
472
460
 
473
461
        k._parents = [frozenset(), frozenset([0])]
474
 
        k._weave = [(b'{', 0),
475
 
                    b"first line",
476
 
                    (b'}', 0),
477
 
                    (b'{', 1),
478
 
                    b"second line",
479
 
                    (b'}', 1)]
 
462
        k._weave = [('{', 0),
 
463
                "first line",
 
464
                ('}', 0),
 
465
                ('{', 1),
 
466
                "second line",
 
467
                ('}', 1)]
480
468
 
481
 
        k._sha1s = [sha_string(b'first line'), sha_string(
482
 
            b'first linesecond line')]
 
469
        k._sha1s = [sha_string('first line')
 
470
                  , sha_string('first linesecond line')]
483
471
 
484
472
        self.assertEqual(k.get_lines(1),
485
 
                         [b"first line",
486
 
                          b"second line"])
 
473
                         ["first line",
 
474
                          "second line"])
487
475
 
488
476
        self.assertEqual(k.get_lines(0),
489
 
                         [b"first line"])
 
477
                         ["first line"])
490
478
 
491
479
 
492
480
class DivergedIncludes(TestBase):
493
481
    """Weave with two diverged texts based on version 0.
494
482
    """
495
 
 
496
483
    def runTest(self):
497
484
        # FIXME make the weave, dont poke at it.
498
485
        k = Weave()
499
486
 
500
 
        k._names = [b'0', b'1', b'2']
501
 
        k._name_map = {b'0': 0, b'1': 1, b'2': 2}
 
487
        k._names = ['0', '1', '2']
 
488
        k._name_map = {'0':0, '1':1, '2':2}
502
489
        k._parents = [frozenset(),
503
 
                      frozenset([0]),
504
 
                      frozenset([0]),
505
 
                      ]
506
 
        k._weave = [(b'{', 0),
507
 
                    b"first line",
508
 
                    (b'}', 0),
509
 
                    (b'{', 1),
510
 
                    b"second line",
511
 
                    (b'}', 1),
512
 
                    (b'{', 2),
513
 
                    b"alternative second line",
514
 
                    (b'}', 2),
515
 
                    ]
 
490
                frozenset([0]),
 
491
                frozenset([0]),
 
492
                ]
 
493
        k._weave = [('{', 0),
 
494
                "first line",
 
495
                ('}', 0),
 
496
                ('{', 1),
 
497
                "second line",
 
498
                ('}', 1),
 
499
                ('{', 2),
 
500
                "alternative second line",
 
501
                ('}', 2),
 
502
                ]
516
503
 
517
 
        k._sha1s = [
518
 
            sha_string(b'first line'),
519
 
            sha_string(b'first linesecond line'),
520
 
            sha_string(b'first linealternative second line')]
 
504
        k._sha1s = [sha_string('first line')
 
505
                  , sha_string('first linesecond line')
 
506
                  , sha_string('first linealternative second line')]
521
507
 
522
508
        self.assertEqual(k.get_lines(0),
523
 
                         [b"first line"])
 
509
                         ["first line"])
524
510
 
525
511
        self.assertEqual(k.get_lines(1),
526
 
                         [b"first line",
527
 
                          b"second line"])
528
 
 
529
 
        self.assertEqual(k.get_lines(b'2'),
530
 
                         [b"first line",
531
 
                          b"alternative second line"])
532
 
 
533
 
        self.assertEqual(list(k.get_ancestry([b'2'])),
534
 
                         [b'0', b'2'])
 
512
                         ["first line",
 
513
                          "second line"])
 
514
 
 
515
        self.assertEqual(k.get_lines('2'),
 
516
                         ["first line",
 
517
                          "alternative second line"])
 
518
 
 
519
        self.assertEqual(list(k.get_ancestry(['2'])),
 
520
                         ['0', '2'])
535
521
 
536
522
 
537
523
class ReplaceLine(TestBase):
538
524
    def runTest(self):
539
525
        k = Weave()
540
526
 
541
 
        text0 = [b'cheddar', b'stilton', b'gruyere']
542
 
        text1 = [b'cheddar', b'blue vein', b'neufchatel', b'chevre']
 
527
        text0 = ['cheddar', 'stilton', 'gruyere']
 
528
        text1 = ['cheddar', 'blue vein', 'neufchatel', 'chevre']
543
529
 
544
 
        k.add_lines(b'text0', [], text0)
545
 
        k.add_lines(b'text1', [b'text0'], text1)
 
530
        k.add_lines('text0', [], text0)
 
531
        k.add_lines('text1', ['text0'], text1)
546
532
 
547
533
        self.log('k._weave=' + pformat(k._weave))
548
534
 
556
542
    def runTest(self):
557
543
        k = Weave()
558
544
 
559
 
        texts = [
560
 
            [b'header'],
561
 
            [b'header', b'', b'line from 1'],
562
 
            [b'header', b'', b'line from 2', b'more from 2'],
563
 
            [b'header', b'', b'line from 1', b'fixup line', b'line from 2'],
564
 
            ]
 
545
        texts = [['header'],
 
546
                 ['header', '', 'line from 1'],
 
547
                 ['header', '', 'line from 2', 'more from 2'],
 
548
                 ['header', '', 'line from 1', 'fixup line', 'line from 2'],
 
549
                 ]
565
550
 
566
 
        k.add_lines(b'text0', [], texts[0])
567
 
        k.add_lines(b'text1', [b'text0'], texts[1])
568
 
        k.add_lines(b'text2', [b'text0'], texts[2])
569
 
        k.add_lines(b'merge', [b'text0', b'text1', b'text2'], texts[3])
 
551
        k.add_lines('text0', [], texts[0])
 
552
        k.add_lines('text1', ['text0'], texts[1])
 
553
        k.add_lines('text2', ['text0'], texts[2])
 
554
        k.add_lines('merge', ['text0', 'text1', 'text2'], texts[3])
570
555
 
571
556
        for i, t in enumerate(texts):
572
557
            self.assertEqual(k.get_lines(i), t)
573
558
 
574
 
        self.assertEqual(k.annotate(b'merge'),
575
 
                         [(b'text0', b'header'),
576
 
                          (b'text1', b''),
577
 
                          (b'text1', b'line from 1'),
578
 
                          (b'merge', b'fixup line'),
579
 
                          (b'text2', b'line from 2'),
 
559
        self.assertEqual(k.annotate('merge'),
 
560
                         [('text0', 'header'),
 
561
                          ('text1', ''),
 
562
                          ('text1', 'line from 1'),
 
563
                          ('merge', 'fixup line'),
 
564
                          ('text2', 'line from 2'),
580
565
                          ])
581
566
 
582
 
        self.assertEqual(list(k.get_ancestry([b'merge'])),
583
 
                         [b'text0', b'text1', b'text2', b'merge'])
 
567
        self.assertEqual(list(k.get_ancestry(['merge'])),
 
568
                         ['text0', 'text1', 'text2', 'merge'])
584
569
 
585
570
        self.log('k._weave=' + pformat(k._weave))
586
571
 
593
578
    A base version is inserted, then two descendents try to
594
579
    insert different lines in the same place.  These should be
595
580
    reported as a possible conflict and forwarded to the user."""
596
 
 
597
581
    def runTest(self):
598
582
        return  # NOT RUN
599
583
        k = Weave()
600
584
 
601
 
        k.add_lines([], [b'aaa', b'bbb'])
602
 
        k.add_lines([0], [b'aaa', b'111', b'bbb'])
603
 
        k.add_lines([1], [b'aaa', b'222', b'bbb'])
604
 
 
605
 
        k.merge([1, 2])
606
 
 
607
 
        self.assertEqual([[[b'aaa']],
608
 
                          [[b'111'], [b'222']],
609
 
                          [[b'bbb']]])
 
585
        k.add_lines([], ['aaa', 'bbb'])
 
586
        k.add_lines([0], ['aaa', '111', 'bbb'])
 
587
        k.add_lines([1], ['aaa', '222', 'bbb'])
 
588
 
 
589
        merged = k.merge([1, 2])
 
590
 
 
591
        self.assertEqual([[['aaa']],
 
592
                           [['111'], ['222']],
 
593
                           [['bbb']]])
610
594
 
611
595
 
612
596
class NonConflict(TestBase):
613
597
    """Two descendants insert compatible changes.
614
598
 
615
599
    No conflict should be reported."""
616
 
 
617
600
    def runTest(self):
618
601
        return  # NOT RUN
619
602
        k = Weave()
620
603
 
621
 
        k.add_lines([], [b'aaa', b'bbb'])
622
 
        k.add_lines([0], [b'111', b'aaa', b'ccc', b'bbb'])
623
 
        k.add_lines([1], [b'aaa', b'ccc', b'bbb', b'222'])
 
604
        k.add_lines([], ['aaa', 'bbb'])
 
605
        k.add_lines([0], ['111', 'aaa', 'ccc', 'bbb'])
 
606
        k.add_lines([1], ['aaa', 'ccc', 'bbb', '222'])
624
607
 
625
608
 
626
609
class Khayyam(TestBase):
628
611
 
629
612
    def test_multi_line_merge(self):
630
613
        rawtexts = [
631
 
            b"""A Book of Verses underneath the Bough,
 
614
            """A Book of Verses underneath the Bough,
632
615
            A Jug of Wine, a Loaf of Bread, -- and Thou
633
616
            Beside me singing in the Wilderness --
634
617
            Oh, Wilderness were Paradise enow!""",
635
618
 
636
 
            b"""A Book of Verses underneath the Bough,
 
619
            """A Book of Verses underneath the Bough,
637
620
            A Jug of Wine, a Loaf of Bread, -- and Thou
638
621
            Beside me singing in the Wilderness --
639
622
            Oh, Wilderness were Paradise now!""",
640
623
 
641
 
            b"""A Book of poems underneath the tree,
 
624
            """A Book of poems underneath the tree,
642
625
            A Jug of Wine, a Loaf of Bread,
643
626
            and Thou
644
627
            Beside me singing in the Wilderness --
646
629
 
647
630
            -- O. Khayyam""",
648
631
 
649
 
            b"""A Book of Verses underneath the Bough,
 
632
            """A Book of Verses underneath the Bough,
650
633
            A Jug of Wine, a Loaf of Bread,
651
634
            and Thou
652
635
            Beside me singing in the Wilderness --
653
636
            Oh, Wilderness were Paradise now!""",
654
637
            ]
655
 
        texts = [[l.strip() for l in t.split(b'\n')] for t in rawtexts]
 
638
        texts = [[l.strip() for l in t.split('\n')] for t in rawtexts]
656
639
 
657
640
        k = Weave()
658
641
        parents = set()
659
642
        i = 0
660
643
        for t in texts:
661
 
            k.add_lines(b'text%d' % i, list(parents), t)
662
 
            parents.add(b'text%d' % i)
 
644
            ver = k.add_lines('text%d' % i,
 
645
                        list(parents), t)
 
646
            parents.add('text%d' % i)
663
647
            i += 1
664
648
 
665
649
        self.log("k._weave=" + pformat(k._weave))
675
659
    def setUp(self):
676
660
        super(JoinWeavesTests, self).setUp()
677
661
        self.weave1 = Weave()
678
 
        self.lines1 = [b'hello\n']
679
 
        self.lines3 = [b'hello\n', b'cruel\n', b'world\n']
680
 
        self.weave1.add_lines(b'v1', [], self.lines1)
681
 
        self.weave1.add_lines(b'v2', [b'v1'], [b'hello\n', b'world\n'])
682
 
        self.weave1.add_lines(b'v3', [b'v2'], self.lines3)
 
662
        self.lines1 = ['hello\n']
 
663
        self.lines3 = ['hello\n', 'cruel\n', 'world\n']
 
664
        self.weave1.add_lines('v1', [], self.lines1)
 
665
        self.weave1.add_lines('v2', ['v1'], ['hello\n', 'world\n'])
 
666
        self.weave1.add_lines('v3', ['v2'], self.lines3)
683
667
 
684
668
    def test_written_detection(self):
685
669
        # Test detection of weave file corruption.
687
671
        # Make sure that we can detect if a weave file has
688
672
        # been corrupted. This doesn't test all forms of corruption,
689
673
        # but it at least helps verify the data you get, is what you want.
 
674
        from cStringIO import StringIO
690
675
 
691
676
        w = Weave()
692
 
        w.add_lines(b'v1', [], [b'hello\n'])
693
 
        w.add_lines(b'v2', [b'v1'], [b'hello\n', b'there\n'])
 
677
        w.add_lines('v1', [], ['hello\n'])
 
678
        w.add_lines('v2', ['v1'], ['hello\n', 'there\n'])
694
679
 
695
 
        tmpf = BytesIO()
 
680
        tmpf = StringIO()
696
681
        write_weave(w, tmpf)
697
682
 
698
 
        # Because we are corrupting, we need to make sure we have the exact
699
 
        # text
700
 
        self.assertEqual(
701
 
            b'# bzr weave file v5\n'
702
 
            b'i\n1 f572d396fae9206628714fb2ce00f72e94f2258f\nn v1\n\n'
703
 
            b'i 0\n1 90f265c6e75f1c8f9ab76dcf85528352c5f215ef\nn v2\n\n'
704
 
            b'w\n{ 0\n. hello\n}\n{ 1\n. there\n}\nW\n',
705
 
            tmpf.getvalue())
 
683
        # Because we are corrupting, we need to make sure we have the exact text
 
684
        self.assertEqual('# 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
                          tmpf.getvalue())
706
689
 
707
690
        # Change a single letter
708
 
        tmpf = BytesIO(
709
 
            b'# bzr weave file v5\n'
710
 
            b'i\n1 f572d396fae9206628714fb2ce00f72e94f2258f\nn v1\n\n'
711
 
            b'i 0\n1 90f265c6e75f1c8f9ab76dcf85528352c5f215ef\nn v2\n\n'
712
 
            b'w\n{ 0\n. hello\n}\n{ 1\n. There\n}\nW\n')
 
691
        tmpf = StringIO('# bzr weave file v5\n'
 
692
                        'i\n1 f572d396fae9206628714fb2ce00f72e94f2258f\nn v1\n\n'
 
693
                        'i 0\n1 90f265c6e75f1c8f9ab76dcf85528352c5f215ef\nn v2\n\n'
 
694
                        'w\n{ 0\n. hello\n}\n{ 1\n. There\n}\nW\n')
713
695
 
714
696
        w = read_weave(tmpf)
715
697
 
716
 
        self.assertEqual(b'hello\n', w.get_text(b'v1'))
717
 
        self.assertRaises(WeaveInvalidChecksum, w.get_text, b'v2')
718
 
        self.assertRaises(WeaveInvalidChecksum, w.get_lines, b'v2')
719
 
        self.assertRaises(WeaveInvalidChecksum, w.check)
 
698
        self.assertEqual('hello\n', w.get_text('v1'))
 
699
        self.assertRaises(errors.WeaveInvalidChecksum, w.get_text, 'v2')
 
700
        self.assertRaises(errors.WeaveInvalidChecksum, w.get_lines, 'v2')
 
701
        self.assertRaises(errors.WeaveInvalidChecksum, w.check)
720
702
 
721
703
        # Change the sha checksum
722
 
        tmpf = BytesIO(
723
 
            b'# bzr weave file v5\n'
724
 
            b'i\n1 f572d396fae9206628714fb2ce00f72e94f2258f\nn v1\n\n'
725
 
            b'i 0\n1 f0f265c6e75f1c8f9ab76dcf85528352c5f215ef\nn v2\n\n'
726
 
            b'w\n{ 0\n. hello\n}\n{ 1\n. there\n}\nW\n')
 
704
        tmpf = StringIO('# bzr weave file v5\n'
 
705
                        'i\n1 f572d396fae9206628714fb2ce00f72e94f2258f\nn v1\n\n'
 
706
                        'i 0\n1 f0f265c6e75f1c8f9ab76dcf85528352c5f215ef\nn v2\n\n'
 
707
                        'w\n{ 0\n. hello\n}\n{ 1\n. there\n}\nW\n')
727
708
 
728
709
        w = read_weave(tmpf)
729
710
 
730
 
        self.assertEqual(b'hello\n', w.get_text(b'v1'))
731
 
        self.assertRaises(WeaveInvalidChecksum, w.get_text, b'v2')
732
 
        self.assertRaises(WeaveInvalidChecksum, w.get_lines, b'v2')
733
 
        self.assertRaises(WeaveInvalidChecksum, w.check)
 
711
        self.assertEqual('hello\n', w.get_text('v1'))
 
712
        self.assertRaises(errors.WeaveInvalidChecksum, w.get_text, 'v2')
 
713
        self.assertRaises(errors.WeaveInvalidChecksum, w.get_lines, 'v2')
 
714
        self.assertRaises(errors.WeaveInvalidChecksum, w.check)
734
715
 
735
716
 
736
717
class TestWeave(TestCase):
738
719
    def test_allow_reserved_false(self):
739
720
        w = Weave('name', allow_reserved=False)
740
721
        # Add lines is checked at the WeaveFile level, not at the Weave level
741
 
        w.add_lines(b'name:', [], TEXT_1)
 
722
        w.add_lines('name:', [], TEXT_1)
742
723
        # But get_lines is checked at this level
743
 
        self.assertRaises(errors.ReservedId, w.get_lines, b'name:')
 
724
        self.assertRaises(errors.ReservedId, w.get_lines, 'name:')
744
725
 
745
726
    def test_allow_reserved_true(self):
746
727
        w = Weave('name', allow_reserved=True)
747
 
        w.add_lines(b'name:', [], TEXT_1)
748
 
        self.assertEqual(TEXT_1, w.get_lines(b'name:'))
 
728
        w.add_lines('name:', [], TEXT_1)
 
729
        self.assertEqual(TEXT_1, w.get_lines('name:'))
749
730
 
750
731
 
751
732
class InstrumentedWeave(Weave):
765
746
 
766
747
    def test_compatible_parents(self):
767
748
        w1 = Weave('a')
768
 
        my_parents = {1, 2, 3}
 
749
        my_parents = set([1, 2, 3])
769
750
        # subsets are ok
770
 
        self.assertTrue(w1._compatible_parents(my_parents, {3}))
 
751
        self.assertTrue(w1._compatible_parents(my_parents, set([3])))
771
752
        # same sets
772
753
        self.assertTrue(w1._compatible_parents(my_parents, set(my_parents)))
773
754
        # same empty corner case
774
755
        self.assertTrue(w1._compatible_parents(set(), set()))
775
756
        # other cannot contain stuff my_parents does not
776
 
        self.assertFalse(w1._compatible_parents(set(), {1}))
777
 
        self.assertFalse(w1._compatible_parents(my_parents, {1, 2, 3, 4}))
778
 
        self.assertFalse(w1._compatible_parents(my_parents, {4}))
 
757
        self.assertFalse(w1._compatible_parents(set(), set([1])))
 
758
        self.assertFalse(w1._compatible_parents(my_parents, set([1, 2, 3, 4])))
 
759
        self.assertFalse(w1._compatible_parents(my_parents, set([4])))
779
760
 
780
761
 
781
762
class TestWeaveFile(TestCaseInTempDir):
782
763
 
783
764
    def test_empty_file(self):
784
 
        with open('empty.weave', 'wb+') as f:
785
 
            self.assertRaises(WeaveFormatError, read_weave, f)
 
765
        f = open('empty.weave', 'wb+')
 
766
        try:
 
767
            self.assertRaises(errors.WeaveFormatError,
 
768
                              read_weave, f)
 
769
        finally:
 
770
            f.close()