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

  • Committer: Marius Kruger
  • Date: 2010-07-10 21:28:56 UTC
  • mto: (5384.1.1 integration)
  • mto: This revision was merged to the branch mainline in revision 5385.
  • Revision ID: marius.kruger@enerweb.co.za-20100710212856-uq4ji3go0u5se7hx
* Update documentation
* add NEWS

Show diffs side-by-side

added added

removed removed

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