/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: 2020-03-22 01:35:14 UTC
  • mfrom: (7490.7.6 work)
  • mto: This revision was merged to the branch mainline in revision 7499.
  • Revision ID: jelmer@jelmer.uk-20200322013514-7vw1ntwho04rcuj3
merge lp:brz/3.1.

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