/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: 2018-11-18 18:23:32 UTC
  • mto: This revision was merged to the branch mainline in revision 7197.
  • Revision ID: jelmer@jelmer.uk-20181118182332-viz1qvqese2mo9i6
Fix some more Bazaar references.

Show diffs side-by-side

added added

removed removed

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