/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 breezy/tests/test_weave.py

  • Committer: Jelmer Vernooij
  • Date: 2017-06-08 23:30:31 UTC
  • mto: This revision was merged to the branch mainline in revision 6690.
  • Revision ID: jelmer@jelmer.uk-20170608233031-3qavls2o7a1pqllj
Update imports.

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