/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
0.1.55 by Martin Pool
doc
1
#! /usr/bin/python2.4
2
0.1.2 by Martin Pool
Import testsweet module adapted from bzr.
3
# Copyright (C) 2005 by Canonical Ltd
4
5
# This program is free software; you can redistribute it and/or modify
6
# it under the terms of the GNU General Public License as published by
7
# the Free Software Foundation; either version 2 of the License, or
8
# (at your option) any later version.
9
10
# This program is distributed in the hope that it will be useful,
11
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
# GNU General Public License for more details.
14
15
# You should have received a copy of the GNU General Public License
16
# along with this program; if not, write to the Free Software
17
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
19
1083 by Martin Pool
- add space to store revision-id in weave files
20
# TODO: tests regarding version names
1185.13.4 by Robert Collins
make reweave visible as a weave method, and quickly integrate into fetch
21
# TODO: rbc 20050108 test that join does not leave an inconsistent weave 
22
#       if it fails.
0.1.2 by Martin Pool
Import testsweet module adapted from bzr.
23
0.1.38 by Martin Pool
Rename knit to weave. (I don't think there's an existing module called weave.)
24
"""test suite for weave algorithm"""
0.1.2 by Martin Pool
Import testsweet module adapted from bzr.
25
1323 by Martin Pool
- caller can pass SHA-1 to Weave.add for efficiency
26
from pprint import pformat
0.1.2 by Martin Pool
Import testsweet module adapted from bzr.
27
1185.13.4 by Robert Collins
make reweave visible as a weave method, and quickly integrate into fetch
28
import bzrlib.errors as errors
1393.1.68 by Martin Pool
- add reweave that joins with ghosts
29
from bzrlib.weave import Weave, WeaveFormatError, WeaveError, reweave
872 by Martin Pool
- update testweave
30
from bzrlib.weavefile import write_weave, read_weave
1185.31.25 by John Arbash Meinel
Renamed all of the tests from selftest/foo.py to tests/test_foo.py
31
from bzrlib.tests import TestCase
1323 by Martin Pool
- caller can pass SHA-1 to Weave.add for efficiency
32
from bzrlib.osutils import sha_string
0.1.66 by Martin Pool
Cope without set/frozenset classes
33
34
0.1.2 by Martin Pool
Import testsweet module adapted from bzr.
35
# texts for use in testing
0.1.3 by Martin Pool
Change storage of texts for testing
36
TEXT_0 = ["Hello world"]
37
TEXT_1 = ["Hello world",
38
          "A second line"]
0.1.2 by Martin Pool
Import testsweet module adapted from bzr.
39
40
1233 by Martin Pool
- fix up weave tests for new test framework
41
class TestBase(TestCase):
0.1.75 by Martin Pool
Remove VerInfo class; just store sets directly in the list of
42
    def check_read_write(self, k):
43
        """Check the weave k can be written & re-read."""
44
        from tempfile import TemporaryFile
45
        tf = TemporaryFile()
46
47
        write_weave(k, tf)
48
        tf.seek(0)
49
        k2 = read_weave(tf)
50
51
        if k != k2:
52
            tf.seek(0)
53
            self.log('serialized weave:')
54
            self.log(tf.read())
1083 by Martin Pool
- add space to store revision-id in weave files
55
56
            self.log('')
57
            self.log('parents: %s' % (k._parents == k2._parents))
58
            self.log('         %r' % k._parents)
59
            self.log('         %r' % k2._parents)
60
            self.log('')
0.1.75 by Martin Pool
Remove VerInfo class; just store sets directly in the list of
61
            self.fail('read/write check failed')
1185.16.125 by Martin Pool
Test for 'name in weave'
62
63
64
class WeaveContains(TestBase):
65
    """Weave __contains__ operator"""
66
    def runTest(self):
67
        k = Weave()
68
        self.assertFalse('foo' in k)
69
        k.add('foo', [], TEXT_1)
70
        self.assertTrue('foo' in k)
0.1.75 by Martin Pool
Remove VerInfo class; just store sets directly in the list of
71
72
0.1.2 by Martin Pool
Import testsweet module adapted from bzr.
73
class Easy(TestBase):
74
    def runTest(self):
0.1.38 by Martin Pool
Rename knit to weave. (I don't think there's an existing module called weave.)
75
        k = Weave()
0.1.2 by Martin Pool
Import testsweet module adapted from bzr.
76
77
78
class StoreText(TestBase):
79
    """Store and retrieve a simple text."""
80
    def runTest(self):
0.1.38 by Martin Pool
Rename knit to weave. (I don't think there's an existing module called weave.)
81
        k = Weave()
1083 by Martin Pool
- add space to store revision-id in weave files
82
        idx = k.add('text0', [], TEXT_0)
0.1.4 by Martin Pool
Start indexing knits by both integer and version string.
83
        self.assertEqual(k.get(idx), TEXT_0)
84
        self.assertEqual(idx, 0)
0.1.2 by Martin Pool
Import testsweet module adapted from bzr.
85
86
0.1.7 by Martin Pool
Add trivial annotate text
87
class AnnotateOne(TestBase):
88
    def runTest(self):
0.1.38 by Martin Pool
Rename knit to weave. (I don't think there's an existing module called weave.)
89
        k = Weave()
1083 by Martin Pool
- add space to store revision-id in weave files
90
        k.add('text0', [], TEXT_0)
0.1.7 by Martin Pool
Add trivial annotate text
91
        self.assertEqual(k.annotate(0),
92
                         [(0, TEXT_0[0])])
93
94
0.1.5 by Martin Pool
Add test for storing two text versions.
95
class StoreTwo(TestBase):
96
    def runTest(self):
0.1.38 by Martin Pool
Rename knit to weave. (I don't think there's an existing module called weave.)
97
        k = Weave()
0.1.5 by Martin Pool
Add test for storing two text versions.
98
1083 by Martin Pool
- add space to store revision-id in weave files
99
        idx = k.add('text0', [], TEXT_0)
0.1.5 by Martin Pool
Add test for storing two text versions.
100
        self.assertEqual(idx, 0)
101
1083 by Martin Pool
- add space to store revision-id in weave files
102
        idx = k.add('text1', [], TEXT_1)
0.1.5 by Martin Pool
Add test for storing two text versions.
103
        self.assertEqual(idx, 1)
104
105
        self.assertEqual(k.get(0), TEXT_0)
106
        self.assertEqual(k.get(1), TEXT_1)
107
0.1.13 by Martin Pool
Knit structure now allows for versions to include the lines present in other
108
1323 by Martin Pool
- caller can pass SHA-1 to Weave.add for efficiency
109
class AddWithGivenSha(TestBase):
110
    def runTest(self):
111
        """Add with caller-supplied SHA-1"""
112
        k = Weave()
113
114
        t = 'text0'
115
        k.add('text0', [], [t], sha1=sha_string(t))
116
117
1185.50.28 by John Arbash Meinel
Lots of updates for 'bzr check'
118
class GetSha1(TestBase):
119
    def test_get_sha1(self):
120
        k = Weave()
121
        k.add('text0', [], 'text0')
122
        self.assertEqual('34dc0e430c642a26c3dd1c2beb7a8b4f4445eb79',
123
                         k.get_sha1('text0'))
1563.2.1 by Robert Collins
Merge in a variation of the versionedfile api from versioned-file.
124
        self.assertRaises(errors.RevisionNotPresent,
1185.50.28 by John Arbash Meinel
Lots of updates for 'bzr check'
125
                          k.get_sha1, 0)
1563.2.1 by Robert Collins
Merge in a variation of the versionedfile api from versioned-file.
126
        self.assertRaises(errors.RevisionNotPresent,
1185.50.28 by John Arbash Meinel
Lots of updates for 'bzr check'
127
                          k.get_sha1, 'text1')
128
                        
1323 by Martin Pool
- caller can pass SHA-1 to Weave.add for efficiency
129
0.1.27 by Martin Pool
Check that version numbers passed in are reasonable
130
class InvalidAdd(TestBase):
131
    """Try to use invalid version number during add."""
132
    def runTest(self):
0.1.38 by Martin Pool
Rename knit to weave. (I don't think there's an existing module called weave.)
133
        k = Weave()
0.1.27 by Martin Pool
Check that version numbers passed in are reasonable
134
937 by Martin Pool
- weave raises IndexError when an invalid revision is given
135
        self.assertRaises(IndexError,
0.1.27 by Martin Pool
Check that version numbers passed in are reasonable
136
                          k.add,
1083 by Martin Pool
- add space to store revision-id in weave files
137
                          'text0',
0.1.27 by Martin Pool
Check that version numbers passed in are reasonable
138
                          [69],
139
                          ['new text!'])
140
141
1237 by Martin Pool
- allow the same version to be repeatedly added to a weave
142
class RepeatedAdd(TestBase):
143
    """Add the same version twice; harmless."""
144
    def runTest(self):
145
        k = Weave()
146
        idx = k.add('text0', [], TEXT_0)
147
        idx2 = k.add('text0', [], TEXT_0)
148
        self.assertEqual(idx, idx2)
149
150
151
class InvalidRepeatedAdd(TestBase):
152
    def runTest(self):
153
        k = Weave()
154
        idx = k.add('text0', [], TEXT_0)
1563.2.1 by Robert Collins
Merge in a variation of the versionedfile api from versioned-file.
155
        self.assertRaises(errors.RevisionAlreadyPresent,
1237 by Martin Pool
- allow the same version to be repeatedly added to a weave
156
                          k.add,
157
                          'text0',
158
                          [],
159
                          ['not the same text'])
1563.2.1 by Robert Collins
Merge in a variation of the versionedfile api from versioned-file.
160
        self.assertRaises(errors.RevisionAlreadyPresent,
1237 by Martin Pool
- allow the same version to be repeatedly added to a weave
161
                          k.add,
162
                          'text0',
163
                          [12],         # not the right parents
164
                          TEXT_0)
165
        
166
0.1.26 by Martin Pool
Refactor parameters to add command
167
class InsertLines(TestBase):
0.1.13 by Martin Pool
Knit structure now allows for versions to include the lines present in other
168
    """Store a revision that adds one line to the original.
169
170
    Look at the annotations to make sure that the first line is matched
171
    and not stored repeatedly."""
172
    def runTest(self):
0.1.38 by Martin Pool
Rename knit to weave. (I don't think there's an existing module called weave.)
173
        k = Weave()
0.1.13 by Martin Pool
Knit structure now allows for versions to include the lines present in other
174
1083 by Martin Pool
- add space to store revision-id in weave files
175
        k.add('text0', [], ['line 1'])
176
        k.add('text1', [0], ['line 1', 'line 2'])
0.1.13 by Martin Pool
Knit structure now allows for versions to include the lines present in other
177
178
        self.assertEqual(k.annotate(0),
179
                         [(0, 'line 1')])
180
0.1.25 by Martin Pool
Handle insertion of new weave layers that insert text on top of the basis
181
        self.assertEqual(k.get(1),
182
                         ['line 1',
183
                          'line 2'])
184
0.1.13 by Martin Pool
Knit structure now allows for versions to include the lines present in other
185
        self.assertEqual(k.annotate(1),
186
                         [(0, 'line 1'),
187
                          (1, 'line 2')])
188
1083 by Martin Pool
- add space to store revision-id in weave files
189
        k.add('text2', [0], ['line 1', 'diverged line'])
0.1.28 by Martin Pool
More tests for insertion of lines in new versions.
190
191
        self.assertEqual(k.annotate(2),
192
                         [(0, 'line 1'),
193
                          (2, 'diverged line')])
194
0.1.54 by Martin Pool
Fix weave line calculation when making deltas
195
        text3 = ['line 1', 'middle line', 'line 2']
1083 by Martin Pool
- add space to store revision-id in weave files
196
        k.add('text3',
197
              [0, 1],
0.1.54 by Martin Pool
Fix weave line calculation when making deltas
198
              text3)
199
937 by Martin Pool
- weave raises IndexError when an invalid revision is given
200
        # self.log("changes to text3: " + pformat(list(k._delta(set([0, 1]), text3))))
0.1.54 by Martin Pool
Fix weave line calculation when making deltas
201
944 by Martin Pool
- refactor member names in Weave code
202
        self.log("k._weave=" + pformat(k._weave))
0.1.28 by Martin Pool
More tests for insertion of lines in new versions.
203
204
        self.assertEqual(k.annotate(3),
205
                         [(0, 'line 1'),
206
                          (3, 'middle line'),
207
                          (1, 'line 2')])
208
0.1.31 by Martin Pool
Fix insertion of multiple regions, calculating the right line offset as we go.
209
        # now multiple insertions at different places
1083 by Martin Pool
- add space to store revision-id in weave files
210
        k.add('text4',
211
              [0, 1, 3],
0.1.31 by Martin Pool
Fix insertion of multiple regions, calculating the right line offset as we go.
212
              ['line 1', 'aaa', 'middle line', 'bbb', 'line 2', 'ccc'])
213
214
        self.assertEqual(k.annotate(4), 
215
                         [(0, 'line 1'),
216
                          (4, 'aaa'),
217
                          (3, 'middle line'),
218
                          (4, 'bbb'),
219
                          (1, 'line 2'),
220
                          (4, 'ccc')])
0.1.13 by Martin Pool
Knit structure now allows for versions to include the lines present in other
221
0.1.40 by Martin Pool
Add test for extracting from weave with nested insertions
222
0.1.56 by Martin Pool
Handle deletion of lines by marking the region with a deletion
223
class DeleteLines(TestBase):
224
    """Deletion of lines from existing text.
225
226
    Try various texts all based on a common ancestor."""
227
    def runTest(self):
228
        k = Weave()
229
230
        base_text = ['one', 'two', 'three', 'four']
231
1083 by Martin Pool
- add space to store revision-id in weave files
232
        k.add('text0', [], base_text)
0.1.56 by Martin Pool
Handle deletion of lines by marking the region with a deletion
233
        
234
        texts = [['one', 'two', 'three'],
235
                 ['two', 'three', 'four'],
236
                 ['one', 'four'],
237
                 ['one', 'two', 'three', 'four'],
238
                 ]
239
1083 by Martin Pool
- add space to store revision-id in weave files
240
        i = 1
0.1.56 by Martin Pool
Handle deletion of lines by marking the region with a deletion
241
        for t in texts:
1083 by Martin Pool
- add space to store revision-id in weave files
242
            ver = k.add('text%d' % i,
243
                        [0], t)
244
            i += 1
0.1.56 by Martin Pool
Handle deletion of lines by marking the region with a deletion
245
246
        self.log('final weave:')
944 by Martin Pool
- refactor member names in Weave code
247
        self.log('k._weave=' + pformat(k._weave))
0.1.56 by Martin Pool
Handle deletion of lines by marking the region with a deletion
248
249
        for i in range(len(texts)):
250
            self.assertEqual(k.get(i+1),
251
                             texts[i])
252
253
0.1.49 by Martin Pool
Add another constraint: revisions should not delete text that they
254
class SuicideDelete(TestBase):
0.1.55 by Martin Pool
doc
255
    """Invalid weave which tries to add and delete simultaneously."""
0.1.49 by Martin Pool
Add another constraint: revisions should not delete text that they
256
    def runTest(self):
257
        k = Weave()
258
944 by Martin Pool
- refactor member names in Weave code
259
        k._parents = [(),
0.1.49 by Martin Pool
Add another constraint: revisions should not delete text that they
260
                ]
944 by Martin Pool
- refactor member names in Weave code
261
        k._weave = [('{', 0),
0.1.49 by Martin Pool
Add another constraint: revisions should not delete text that they
262
                'first line',
263
                ('[', 0),
264
                'deleted in 0',
265
                (']', 0),
266
                ('}', 0),
267
                ]
891 by Martin Pool
- fix up refactoring of weave
268
        ################################### SKIPPED
269
        # Weave.get doesn't trap this anymore
270
        return 
0.1.49 by Martin Pool
Add another constraint: revisions should not delete text that they
271
272
        self.assertRaises(WeaveFormatError,
273
                          k.get,
274
                          0)        
275
276
0.1.48 by Martin Pool
Basic parsing of delete instructions.
277
class CannedDelete(TestBase):
278
    """Unpack canned weave with deleted lines."""
279
    def runTest(self):
280
        k = Weave()
281
944 by Martin Pool
- refactor member names in Weave code
282
        k._parents = [(),
0.1.75 by Martin Pool
Remove VerInfo class; just store sets directly in the list of
283
                frozenset([0]),
0.1.48 by Martin Pool
Basic parsing of delete instructions.
284
                ]
944 by Martin Pool
- refactor member names in Weave code
285
        k._weave = [('{', 0),
0.1.48 by Martin Pool
Basic parsing of delete instructions.
286
                'first line',
287
                ('[', 1),
288
                'line to be deleted',
289
                (']', 1),
290
                'last line',
291
                ('}', 0),
292
                ]
1185.50.23 by John Arbash Meinel
Adding sha1 check when weave extracts a text.
293
        k._sha1s = [sha_string('first lineline to be deletedlast line')
294
                  , sha_string('first linelast line')]
0.1.48 by Martin Pool
Basic parsing of delete instructions.
295
296
        self.assertEqual(k.get(0),
297
                         ['first line',
298
                          'line to be deleted',
299
                          'last line',
300
                          ])
301
0.1.50 by Martin Pool
Basic implementation of deletion markers
302
        self.assertEqual(k.get(1),
303
                         ['first line',
304
                          'last line',
305
                          ])
306
0.1.48 by Martin Pool
Basic parsing of delete instructions.
307
0.1.51 by Martin Pool
Add test for replacement lines
308
class CannedReplacement(TestBase):
309
    """Unpack canned weave with deleted lines."""
310
    def runTest(self):
311
        k = Weave()
312
944 by Martin Pool
- refactor member names in Weave code
313
        k._parents = [frozenset(),
0.1.75 by Martin Pool
Remove VerInfo class; just store sets directly in the list of
314
                frozenset([0]),
0.1.51 by Martin Pool
Add test for replacement lines
315
                ]
944 by Martin Pool
- refactor member names in Weave code
316
        k._weave = [('{', 0),
0.1.51 by Martin Pool
Add test for replacement lines
317
                'first line',
318
                ('[', 1),
319
                'line to be deleted',
320
                (']', 1),
321
                ('{', 1),
322
                'replacement line',                
323
                ('}', 1),
324
                'last line',
325
                ('}', 0),
326
                ]
1185.50.23 by John Arbash Meinel
Adding sha1 check when weave extracts a text.
327
        k._sha1s = [sha_string('first lineline to be deletedlast line')
328
                  , sha_string('first linereplacement linelast line')]
0.1.51 by Martin Pool
Add test for replacement lines
329
330
        self.assertEqual(k.get(0),
331
                         ['first line',
332
                          'line to be deleted',
333
                          'last line',
334
                          ])
335
336
        self.assertEqual(k.get(1),
337
                         ['first line',
338
                          'replacement line',
339
                          'last line',
340
                          ])
341
342
0.1.46 by Martin Pool
More constraints on structure of weave, and checks that they work
343
class BadWeave(TestBase):
344
    """Test that we trap an insert which should not occur."""
345
    def runTest(self):
346
        k = Weave()
347
944 by Martin Pool
- refactor member names in Weave code
348
        k._parents = [frozenset(),
0.1.46 by Martin Pool
More constraints on structure of weave, and checks that they work
349
                ]
944 by Martin Pool
- refactor member names in Weave code
350
        k._weave = ['bad line',
0.1.46 by Martin Pool
More constraints on structure of weave, and checks that they work
351
                ('{', 0),
352
                'foo {',
353
                ('{', 1),
354
                '  added in version 1',
355
                ('{', 2),
356
                '  added in v2',
357
                ('}', 2),
358
                '  also from v1',
359
                ('}', 1),
360
                '}',
361
                ('}', 0)]
362
891 by Martin Pool
- fix up refactoring of weave
363
        ################################### SKIPPED
364
        # Weave.get doesn't trap this anymore
365
        return 
366
367
0.1.47 by Martin Pool
New WeaveError and WeaveFormatError rather than assertions.
368
        self.assertRaises(WeaveFormatError,
0.1.46 by Martin Pool
More constraints on structure of weave, and checks that they work
369
                          k.get,
370
                          0)
371
372
373
class BadInsert(TestBase):
374
    """Test that we trap an insert which should not occur."""
375
    def runTest(self):
376
        k = Weave()
377
944 by Martin Pool
- refactor member names in Weave code
378
        k._parents = [frozenset(),
0.1.75 by Martin Pool
Remove VerInfo class; just store sets directly in the list of
379
                frozenset([0]),
380
                frozenset([0]),
381
                frozenset([0,1,2]),
0.1.46 by Martin Pool
More constraints on structure of weave, and checks that they work
382
                ]
944 by Martin Pool
- refactor member names in Weave code
383
        k._weave = [('{', 0),
0.1.46 by Martin Pool
More constraints on structure of weave, and checks that they work
384
                'foo {',
385
                ('{', 1),
386
                '  added in version 1',
387
                ('{', 1),
388
                '  more in 1',
389
                ('}', 1),
390
                ('}', 1),
391
                ('}', 0)]
392
891 by Martin Pool
- fix up refactoring of weave
393
394
        # this is not currently enforced by get
395
        return  ##########################################
396
0.1.47 by Martin Pool
New WeaveError and WeaveFormatError rather than assertions.
397
        self.assertRaises(WeaveFormatError,
0.1.46 by Martin Pool
More constraints on structure of weave, and checks that they work
398
                          k.get,
399
                          0)
400
0.1.47 by Martin Pool
New WeaveError and WeaveFormatError rather than assertions.
401
        self.assertRaises(WeaveFormatError,
0.1.46 by Martin Pool
More constraints on structure of weave, and checks that they work
402
                          k.get,
403
                          1)
404
0.1.40 by Martin Pool
Add test for extracting from weave with nested insertions
405
406
class InsertNested(TestBase):
407
    """Insertion with nested instructions."""
408
    def runTest(self):
409
        k = Weave()
410
944 by Martin Pool
- refactor member names in Weave code
411
        k._parents = [frozenset(),
0.1.75 by Martin Pool
Remove VerInfo class; just store sets directly in the list of
412
                frozenset([0]),
413
                frozenset([0]),
414
                frozenset([0,1,2]),
0.1.40 by Martin Pool
Add test for extracting from weave with nested insertions
415
                ]
944 by Martin Pool
- refactor member names in Weave code
416
        k._weave = [('{', 0),
0.1.40 by Martin Pool
Add test for extracting from weave with nested insertions
417
                'foo {',
418
                ('{', 1),
419
                '  added in version 1',
0.1.42 by Martin Pool
More tests for nested insert instructions
420
                ('{', 2),
421
                '  added in v2',
422
                ('}', 2),
423
                '  also from v1',
0.1.40 by Martin Pool
Add test for extracting from weave with nested insertions
424
                ('}', 1),
425
                '}',
426
                ('}', 0)]
427
1185.50.23 by John Arbash Meinel
Adding sha1 check when weave extracts a text.
428
        k._sha1s = [sha_string('foo {}')
429
                  , sha_string('foo {  added in version 1  also from v1}')
430
                  , sha_string('foo {  added in v2}')
431
                  , sha_string('foo {  added in version 1  added in v2  also from v1}')
432
                  ]
433
0.1.40 by Martin Pool
Add test for extracting from weave with nested insertions
434
        self.assertEqual(k.get(0),
435
                         ['foo {',
436
                          '}'])
437
438
        self.assertEqual(k.get(1),
439
                         ['foo {',
440
                          '  added in version 1',
0.1.42 by Martin Pool
More tests for nested insert instructions
441
                          '  also from v1',
0.1.40 by Martin Pool
Add test for extracting from weave with nested insertions
442
                          '}'])
443
                       
0.1.44 by Martin Pool
More tests for nested insert instructions
444
        self.assertEqual(k.get(2),
445
                         ['foo {',
446
                          '  added in v2',
447
                          '}'])
448
449
        self.assertEqual(k.get(3),
450
                         ['foo {',
451
                          '  added in version 1',
452
                          '  added in v2',
453
                          '  also from v1',
454
                          '}'])
455
                         
0.1.45 by Martin Pool
doc
456
0.1.56 by Martin Pool
Handle deletion of lines by marking the region with a deletion
457
class DeleteLines2(TestBase):
0.1.30 by Martin Pool
Start adding tests for line deletion
458
    """Test recording revisions that delete lines.
459
460
    This relies on the weave having a way to represent lines knocked
461
    out by a later revision."""
462
    def runTest(self):
0.1.38 by Martin Pool
Rename knit to weave. (I don't think there's an existing module called weave.)
463
        k = Weave()
0.1.30 by Martin Pool
Start adding tests for line deletion
464
1083 by Martin Pool
- add space to store revision-id in weave files
465
        k.add('text0', [], ["line the first",
0.1.30 by Martin Pool
Start adding tests for line deletion
466
                   "line 2",
467
                   "line 3",
468
                   "fine"])
469
470
        self.assertEqual(len(k.get(0)), 4)
471
1083 by Martin Pool
- add space to store revision-id in weave files
472
        k.add('text1', [0], ["line the first",
0.1.30 by Martin Pool
Start adding tests for line deletion
473
                   "fine"])
474
475
        self.assertEqual(k.get(1),
476
                         ["line the first",
477
                          "fine"])
478
0.1.56 by Martin Pool
Handle deletion of lines by marking the region with a deletion
479
        self.assertEqual(k.annotate(1),
480
                         [(0, "line the first"),
481
                          (0, "fine")])
482
0.1.30 by Martin Pool
Start adding tests for line deletion
483
0.1.13 by Martin Pool
Knit structure now allows for versions to include the lines present in other
484
class IncludeVersions(TestBase):
485
    """Check texts that are stored across multiple revisions.
486
0.1.38 by Martin Pool
Rename knit to weave. (I don't think there's an existing module called weave.)
487
    Here we manually create a weave with particular encoding and make
0.1.13 by Martin Pool
Knit structure now allows for versions to include the lines present in other
488
    sure it unpacks properly.
489
490
    Text 0 includes nothing; text 1 includes text 0 and adds some
491
    lines.
492
    """
493
494
    def runTest(self):
0.1.38 by Martin Pool
Rename knit to weave. (I don't think there's an existing module called weave.)
495
        k = Weave()
0.1.13 by Martin Pool
Knit structure now allows for versions to include the lines present in other
496
944 by Martin Pool
- refactor member names in Weave code
497
        k._parents = [frozenset(), frozenset([0])]
498
        k._weave = [('{', 0),
0.1.39 by Martin Pool
Change to a more realistic weave structure which can represent insertions and
499
                "first line",
500
                ('}', 0),
501
                ('{', 1),
502
                "second line",
503
                ('}', 1)]
0.1.13 by Martin Pool
Knit structure now allows for versions to include the lines present in other
504
1185.50.23 by John Arbash Meinel
Adding sha1 check when weave extracts a text.
505
        k._sha1s = [sha_string('first line')
506
                  , sha_string('first linesecond line')]
507
0.1.13 by Martin Pool
Knit structure now allows for versions to include the lines present in other
508
        self.assertEqual(k.get(1),
509
                         ["first line",
510
                          "second line"])
511
512
        self.assertEqual(k.get(0),
513
                         ["first line"])
514
0.1.5 by Martin Pool
Add test for storing two text versions.
515
0.1.14 by Martin Pool
Another test for version inclusion
516
class DivergedIncludes(TestBase):
0.1.38 by Martin Pool
Rename knit to weave. (I don't think there's an existing module called weave.)
517
    """Weave with two diverged texts based on version 0.
0.1.14 by Martin Pool
Another test for version inclusion
518
    """
519
    def runTest(self):
1563.2.1 by Robert Collins
Merge in a variation of the versionedfile api from versioned-file.
520
        # FIXME make the weave, dont poke at it.
0.1.38 by Martin Pool
Rename knit to weave. (I don't think there's an existing module called weave.)
521
        k = Weave()
0.1.14 by Martin Pool
Another test for version inclusion
522
1563.2.1 by Robert Collins
Merge in a variation of the versionedfile api from versioned-file.
523
        k._names = ['0', '1', '2']
944 by Martin Pool
- refactor member names in Weave code
524
        k._parents = [frozenset(),
0.1.75 by Martin Pool
Remove VerInfo class; just store sets directly in the list of
525
                frozenset([0]),
526
                frozenset([0]),
0.1.17 by Martin Pool
Use objects rather than tuples for tracking VerInfo for
527
                ]
944 by Martin Pool
- refactor member names in Weave code
528
        k._weave = [('{', 0),
0.1.39 by Martin Pool
Change to a more realistic weave structure which can represent insertions and
529
                "first line",
530
                ('}', 0),
531
                ('{', 1),
532
                "second line",
533
                ('}', 1),
534
                ('{', 2),
535
                "alternative second line",
536
                ('}', 2),                
537
                ]
0.1.14 by Martin Pool
Another test for version inclusion
538
1185.50.23 by John Arbash Meinel
Adding sha1 check when weave extracts a text.
539
        k._sha1s = [sha_string('first line')
540
                  , sha_string('first linesecond line')
541
                  , sha_string('first linealternative second line')]
542
0.1.14 by Martin Pool
Another test for version inclusion
543
        self.assertEqual(k.get(0),
544
                         ["first line"])
545
546
        self.assertEqual(k.get(1),
547
                         ["first line",
548
                          "second line"])
549
550
        self.assertEqual(k.get(2),
551
                         ["first line",
552
                          "alternative second line"])
553
924 by Martin Pool
- Add IntSet class
554
        self.assertEqual(list(k.inclusions([2])),
1563.2.1 by Robert Collins
Merge in a variation of the versionedfile api from versioned-file.
555
                         ['0', '2'])
0.1.77 by Martin Pool
New Weave.get_included() does transitive expansion
556
0.1.57 by Martin Pool
Fix bug in an update edit that both deletes and inserts -- previously
557
558
class ReplaceLine(TestBase):
559
    def runTest(self):
560
        k = Weave()
561
562
        text0 = ['cheddar', 'stilton', 'gruyere']
563
        text1 = ['cheddar', 'blue vein', 'neufchatel', 'chevre']
564
        
1083 by Martin Pool
- add space to store revision-id in weave files
565
        k.add('text0', [], text0)
566
        k.add('text1', [0], text1)
0.1.57 by Martin Pool
Fix bug in an update edit that both deletes and inserts -- previously
567
944 by Martin Pool
- refactor member names in Weave code
568
        self.log('k._weave=' + pformat(k._weave))
0.1.57 by Martin Pool
Fix bug in an update edit that both deletes and inserts -- previously
569
0.1.59 by Martin Pool
More modification tests
570
        self.assertEqual(k.get(0), text0)
0.1.57 by Martin Pool
Fix bug in an update edit that both deletes and inserts -- previously
571
        self.assertEqual(k.get(1), text1)
572
0.1.64 by Martin Pool
Add test for merging versions
573
574
class Merge(TestBase):
0.1.95 by Martin Pool
- preliminary merge conflict detection
575
    """Storage of versions that merge diverged parents"""
0.1.64 by Martin Pool
Add test for merging versions
576
    def runTest(self):
577
        k = Weave()
578
579
        texts = [['header'],
580
                 ['header', '', 'line from 1'],
581
                 ['header', '', 'line from 2', 'more from 2'],
582
                 ['header', '', 'line from 1', 'fixup line', 'line from 2'],
583
                 ]
584
1083 by Martin Pool
- add space to store revision-id in weave files
585
        k.add('text0', [], texts[0])
586
        k.add('text1', [0], texts[1])
587
        k.add('text2', [0], texts[2])
588
        k.add('merge', [0, 1, 2], texts[3])
0.1.64 by Martin Pool
Add test for merging versions
589
590
        for i, t in enumerate(texts):
591
            self.assertEqual(k.get(i), t)
592
593
        self.assertEqual(k.annotate(3),
594
                         [(0, 'header'),
595
                          (1, ''),
596
                          (1, 'line from 1'),
597
                          (3, 'fixup line'),
598
                          (2, 'line from 2'),
599
                          ])
600
924 by Martin Pool
- Add IntSet class
601
        self.assertEqual(list(k.inclusions([3])),
1563.2.1 by Robert Collins
Merge in a variation of the versionedfile api from versioned-file.
602
                         ['text0', 'text1', 'text2', 'merge'])
0.1.77 by Martin Pool
New Weave.get_included() does transitive expansion
603
944 by Martin Pool
- refactor member names in Weave code
604
        self.log('k._weave=' + pformat(k._weave))
0.1.64 by Martin Pool
Add test for merging versions
605
0.1.75 by Martin Pool
Remove VerInfo class; just store sets directly in the list of
606
        self.check_read_write(k)
0.1.65 by Martin Pool
Add Weave.merge_iter to get automerged lines
607
608
0.1.95 by Martin Pool
- preliminary merge conflict detection
609
class Conflicts(TestBase):
610
    """Test detection of conflicting regions during a merge.
611
612
    A base version is inserted, then two descendents try to
613
    insert different lines in the same place.  These should be
614
    reported as a possible conflict and forwarded to the user."""
615
    def runTest(self):
616
        return  # NOT RUN
617
        k = Weave()
618
619
        k.add([], ['aaa', 'bbb'])
620
        k.add([0], ['aaa', '111', 'bbb'])
621
        k.add([1], ['aaa', '222', 'bbb'])
622
623
        merged = k.merge([1, 2])
624
625
        self.assertEquals([[['aaa']],
626
                           [['111'], ['222']],
627
                           [['bbb']]])
628
629
630
class NonConflict(TestBase):
631
    """Two descendants insert compatible changes.
632
633
    No conflict should be reported."""
634
    def runTest(self):
635
        return  # NOT RUN
636
        k = Weave()
637
638
        k.add([], ['aaa', 'bbb'])
639
        k.add([0], ['111', 'aaa', 'ccc', 'bbb'])
640
        k.add([1], ['aaa', 'ccc', 'bbb', '222'])
641
642
0.1.57 by Martin Pool
Fix bug in an update edit that both deletes and inserts -- previously
643
class Khayyam(TestBase):
0.1.75 by Martin Pool
Remove VerInfo class; just store sets directly in the list of
644
    """Test changes to multi-line texts, and read/write"""
1563.2.1 by Robert Collins
Merge in a variation of the versionedfile api from versioned-file.
645
646
    def test_multi_line_merge(self):
0.1.57 by Martin Pool
Fix bug in an update edit that both deletes and inserts -- previously
647
        rawtexts = [
648
            """A Book of Verses underneath the Bough,
649
            A Jug of Wine, a Loaf of Bread, -- and Thou
650
            Beside me singing in the Wilderness --
651
            Oh, Wilderness were Paradise enow!""",
652
            
653
            """A Book of Verses underneath the Bough,
654
            A Jug of Wine, a Loaf of Bread, -- and Thou
655
            Beside me singing in the Wilderness --
656
            Oh, Wilderness were Paradise now!""",
0.1.59 by Martin Pool
More modification tests
657
658
            """A Book of poems underneath the tree,
659
            A Jug of Wine, a Loaf of Bread,
660
            and Thou
661
            Beside me singing in the Wilderness --
662
            Oh, Wilderness were Paradise now!
663
664
            -- O. Khayyam""",
665
666
            """A Book of Verses underneath the Bough,
667
            A Jug of Wine, a Loaf of Bread,
668
            and Thou
669
            Beside me singing in the Wilderness --
0.1.75 by Martin Pool
Remove VerInfo class; just store sets directly in the list of
670
            Oh, Wilderness were Paradise now!""",
0.1.57 by Martin Pool
Fix bug in an update edit that both deletes and inserts -- previously
671
            ]
672
        texts = [[l.strip() for l in t.split('\n')] for t in rawtexts]
673
674
        k = Weave()
675
        parents = set()
1083 by Martin Pool
- add space to store revision-id in weave files
676
        i = 0
0.1.57 by Martin Pool
Fix bug in an update edit that both deletes and inserts -- previously
677
        for t in texts:
1083 by Martin Pool
- add space to store revision-id in weave files
678
            ver = k.add('text%d' % i,
679
                        list(parents), t)
0.1.57 by Martin Pool
Fix bug in an update edit that both deletes and inserts -- previously
680
            parents.add(ver)
1083 by Martin Pool
- add space to store revision-id in weave files
681
            i += 1
0.1.57 by Martin Pool
Fix bug in an update edit that both deletes and inserts -- previously
682
944 by Martin Pool
- refactor member names in Weave code
683
        self.log("k._weave=" + pformat(k._weave))
0.1.59 by Martin Pool
More modification tests
684
0.1.57 by Martin Pool
Fix bug in an update edit that both deletes and inserts -- previously
685
        for i, t in enumerate(texts):
0.1.75 by Martin Pool
Remove VerInfo class; just store sets directly in the list of
686
            self.assertEqual(k.get(i), t)
0.1.57 by Martin Pool
Fix bug in an update edit that both deletes and inserts -- previously
687
0.1.75 by Martin Pool
Remove VerInfo class; just store sets directly in the list of
688
        self.check_read_write(k)
0.1.57 by Martin Pool
Fix bug in an update edit that both deletes and inserts -- previously
689
690
920 by Martin Pool
- add more test cases for weave_merge
691
class MergeCases(TestBase):
692
    def doMerge(self, base, a, b, mp):
693
        from cStringIO import StringIO
694
        from textwrap import dedent
695
696
        def addcrlf(x):
697
            return x + '\n'
698
        
699
        w = Weave()
1083 by Martin Pool
- add space to store revision-id in weave files
700
        w.add('text0', [], map(addcrlf, base))
701
        w.add('text1', [0], map(addcrlf, a))
702
        w.add('text2', [0], map(addcrlf, b))
920 by Martin Pool
- add more test cases for weave_merge
703
935 by Martin Pool
- log weave for merge tests to help debugging
704
        self.log('weave is:')
705
        tmpf = StringIO()
706
        write_weave(w, tmpf)
707
        self.log(tmpf.getvalue())
708
920 by Martin Pool
- add more test cases for weave_merge
709
        self.log('merge plan:')
710
        p = list(w.plan_merge(1, 2))
711
        for state, line in p:
712
            if line:
713
                self.log('%12s | %s' % (state, line[:-1]))
714
715
        self.log('merge:')
716
        mt = StringIO()
717
        mt.writelines(w.weave_merge(p))
718
        mt.seek(0)
719
        self.log(mt.getvalue())
720
721
        mp = map(addcrlf, mp)
722
        self.assertEqual(mt.readlines(), mp)
723
        
724
        
725
    def testOneInsert(self):
726
        self.doMerge([],
727
                     ['aa'],
728
                     [],
729
                     ['aa'])
730
731
    def testSeparateInserts(self):
732
        self.doMerge(['aaa', 'bbb', 'ccc'],
733
                     ['aaa', 'xxx', 'bbb', 'ccc'],
734
                     ['aaa', 'bbb', 'yyy', 'ccc'],
735
                     ['aaa', 'xxx', 'bbb', 'yyy', 'ccc'])
736
737
    def testSameInsert(self):
738
        self.doMerge(['aaa', 'bbb', 'ccc'],
739
                     ['aaa', 'xxx', 'bbb', 'ccc'],
740
                     ['aaa', 'xxx', 'bbb', 'yyy', 'ccc'],
741
                     ['aaa', 'xxx', 'bbb', 'yyy', 'ccc'])
742
743
    def testOverlappedInsert(self):
744
        self.doMerge(['aaa', 'bbb'],
745
                     ['aaa', 'xxx', 'yyy', 'bbb'],
746
                     ['aaa', 'xxx', 'bbb'],
1534.7.186 by Aaron Bentley
Made weave conflict markers customizable, standardized defaults
747
                     ['aaa', '<<<<<<< ', 'xxx', 'yyy', '=======', 'xxx', 
748
                      '>>>>>>> ', 'bbb'])
920 by Martin Pool
- add more test cases for weave_merge
749
750
        # really it ought to reduce this to 
751
        # ['aaa', 'xxx', 'yyy', 'bbb']
752
753
754
    def testClashReplace(self):
755
        self.doMerge(['aaa'],
756
                     ['xxx'],
757
                     ['yyy', 'zzz'],
1534.7.186 by Aaron Bentley
Made weave conflict markers customizable, standardized defaults
758
                     ['<<<<<<< ', 'xxx', '=======', 'yyy', 'zzz', 
759
                      '>>>>>>> '])
920 by Martin Pool
- add more test cases for weave_merge
760
761
    def testNonClashInsert(self):
762
        self.doMerge(['aaa'],
763
                     ['xxx', 'aaa'],
764
                     ['yyy', 'zzz'],
1534.7.186 by Aaron Bentley
Made weave conflict markers customizable, standardized defaults
765
                     ['<<<<<<< ', 'xxx', 'aaa', '=======', 'yyy', 'zzz', 
766
                      '>>>>>>> '])
920 by Martin Pool
- add more test cases for weave_merge
767
768
        self.doMerge(['aaa'],
769
                     ['aaa'],
770
                     ['yyy', 'zzz'],
771
                     ['yyy', 'zzz'])
945 by Martin Pool
- add stubbed-out test for clashing replace and delete
772
773
774
    def testDeleteAndModify(self):
775
        """Clashing delete and modification.
776
777
        If one side modifies a region and the other deletes it then
778
        there should be a conflict with one side blank.
779
        """
780
781
        #######################################
782
        # skippd, not working yet
783
        return
784
        
785
        self.doMerge(['aaa', 'bbb', 'ccc'],
786
                     ['aaa', 'ddd', 'ccc'],
787
                     ['aaa', 'ccc'],
1534.7.186 by Aaron Bentley
Made weave conflict markers customizable, standardized defaults
788
                     ['<<<<<<<< ', 'aaa', '=======', '>>>>>>> ', 'ccc'])
1393.1.48 by Martin Pool
- Add stub Weave.join() method
789
790
791
class JoinWeavesTests(TestBase):
1393.1.50 by Martin Pool
- more development of Weave.join()
792
    def setUp(self):
793
        super(JoinWeavesTests, self).setUp()
794
        self.weave1 = Weave()
795
        self.lines1 = ['hello\n']
796
        self.lines3 = ['hello\n', 'cruel\n', 'world\n']
797
        self.weave1.add('v1', [], self.lines1)
798
        self.weave1.add('v2', [0], ['hello\n', 'world\n'])
799
        self.weave1.add('v3', [1], self.lines3)
800
        
1393.1.48 by Martin Pool
- Add stub Weave.join() method
801
    def test_join_empty(self):
802
        """Join two empty weaves."""
803
        eq = self.assertEqual
804
        w1 = Weave()
805
        w2 = Weave()
806
        w1.join(w2)
807
        eq(w1.numversions(), 0)
808
        
1393.1.50 by Martin Pool
- more development of Weave.join()
809
    def test_join_empty_to_nonempty(self):
810
        """Join empty weave onto nonempty."""
811
        self.weave1.join(Weave())
812
        self.assertEqual(len(self.weave1), 3)
813
814
    def test_join_unrelated(self):
815
        """Join two weaves with no history in common."""
816
        wb = Weave()
817
        wb.add('b1', [], ['line from b\n'])
818
        w1 = self.weave1
819
        w1.join(wb)
820
        eq = self.assertEqual
821
        eq(len(w1), 4)
822
        eq(sorted(list(w1.iter_names())),
823
           ['b1', 'v1', 'v2', 'v3'])
920 by Martin Pool
- add more test cases for weave_merge
824
1393.1.51 by Martin Pool
- new Weave.copy()
825
    def test_join_related(self):
826
        wa = self.weave1.copy()
827
        wb = self.weave1.copy()
828
        wa.add('a1', ['v3'], ['hello\n', 'sweet\n', 'world\n'])
829
        wb.add('b1', ['v3'], ['hello\n', 'pale blue\n', 'world\n'])
830
        eq = self.assertEquals
831
        eq(len(wa), 4)
832
        eq(len(wb), 4)
833
        wa.join(wb)
834
        eq(len(wa), 5)
835
        eq(wa.get_lines('b1'),
836
           ['hello\n', 'pale blue\n', 'world\n'])
837
1393.1.67 by Martin Pool
- test that we cannot join weaves with different ancestry
838
    def test_join_parent_disagreement(self):
1563.2.11 by Robert Collins
Consolidate reweave and join as we have no separate usage, make reweave tests apply to all versionedfile implementations and deprecate the old reweave apis.
839
        #join reconciles differening parents into a union.
1393.1.67 by Martin Pool
- test that we cannot join weaves with different ancestry
840
        wa = Weave()
841
        wb = Weave()
842
        wa.add('v1', [], ['hello\n'])
843
        wb.add('v0', [], [])
844
        wb.add('v1', ['v0'], ['hello\n'])
1563.2.11 by Robert Collins
Consolidate reweave and join as we have no separate usage, make reweave tests apply to all versionedfile implementations and deprecate the old reweave apis.
845
        wa.join(wb)
846
        self.assertEqual(['v0'], wa.get_parents('v1'))
1393.1.67 by Martin Pool
- test that we cannot join weaves with different ancestry
847
848
    def test_join_text_disagreement(self):
849
        """Cannot join weaves with different texts for a version."""
850
        wa = Weave()
851
        wb = Weave()
852
        wa.add('v1', [], ['hello\n'])
853
        wb.add('v1', [], ['not\n', 'hello\n'])
854
        self.assertRaises(WeaveError,
855
                          wa.join, wb)
856
1393.1.66 by Martin Pool
- fix join of weaves where parents occur at different offsets
857
    def test_join_unordered(self):
858
        """Join weaves where indexes differ.
859
        
860
        The source weave contains a different version at index 0."""
861
        wa = self.weave1.copy()
862
        wb = Weave()
863
        wb.add('x1', [], ['line from x1\n'])
864
        wb.add('v1', [], ['hello\n'])
865
        wb.add('v2', ['v1'], ['hello\n', 'world\n'])
866
        wa.join(wb)
867
        eq = self.assertEquals
868
        eq(sorted(wa.iter_names()), ['v1', 'v2', 'v3', 'x1',])
869
        eq(wa.get_text('x1'), 'line from x1\n')
1185.50.23 by John Arbash Meinel
Adding sha1 check when weave extracts a text.
870
871
    def test_written_detection(self):
1185.50.29 by John Arbash Meinel
Whitespace and other formatting cleanups suggested by Robert.
872
        # Test detection of weave file corruption.
873
        #
874
        # Make sure that we can detect if a weave file has
875
        # been corrupted. This doesn't test all forms of corruption,
876
        # but it at least helps verify the data you get, is what you want.
1185.50.23 by John Arbash Meinel
Adding sha1 check when weave extracts a text.
877
        from cStringIO import StringIO
878
879
        w = Weave()
880
        w.add('v1', [], ['hello\n'])
881
        w.add('v2', ['v1'], ['hello\n', 'there\n'])
882
883
        tmpf = StringIO()
884
        write_weave(w, tmpf)
885
886
        # Because we are corrupting, we need to make sure we have the exact text
887
        self.assertEquals('# bzr weave file v5\n'
888
                          'i\n1 f572d396fae9206628714fb2ce00f72e94f2258f\nn v1\n\n'
889
                          'i 0\n1 90f265c6e75f1c8f9ab76dcf85528352c5f215ef\nn v2\n\n'
890
                          'w\n{ 0\n. hello\n}\n{ 1\n. there\n}\nW\n',
891
                          tmpf.getvalue())
892
893
        # Change a single letter
894
        tmpf = StringIO('# bzr weave file v5\n'
895
                        'i\n1 f572d396fae9206628714fb2ce00f72e94f2258f\nn v1\n\n'
896
                        'i 0\n1 90f265c6e75f1c8f9ab76dcf85528352c5f215ef\nn v2\n\n'
897
                        'w\n{ 0\n. hello\n}\n{ 1\n. There\n}\nW\n')
898
899
        w = read_weave(tmpf)
900
901
        self.assertEqual('hello\n', w.get_text('v1'))
902
        self.assertRaises(errors.WeaveInvalidChecksum, w.get_text, 'v2')
903
        self.assertRaises(errors.WeaveInvalidChecksum, w.get_lines, 'v2')
904
        self.assertRaises(errors.WeaveInvalidChecksum, list, w.get_iter('v2'))
1185.50.26 by John Arbash Meinel
Change Weave.check() so that it checks all revisions in parallel.
905
        self.assertRaises(errors.WeaveInvalidChecksum, w.check)
1185.50.23 by John Arbash Meinel
Adding sha1 check when weave extracts a text.
906
907
        # Change the sha checksum
908
        tmpf = StringIO('# bzr weave file v5\n'
909
                        'i\n1 f572d396fae9206628714fb2ce00f72e94f2258f\nn v1\n\n'
910
                        'i 0\n1 f0f265c6e75f1c8f9ab76dcf85528352c5f215ef\nn v2\n\n'
911
                        'w\n{ 0\n. hello\n}\n{ 1\n. there\n}\nW\n')
912
913
        w = read_weave(tmpf)
914
915
        self.assertEqual('hello\n', w.get_text('v1'))
916
        self.assertRaises(errors.WeaveInvalidChecksum, w.get_text, 'v2')
917
        self.assertRaises(errors.WeaveInvalidChecksum, w.get_lines, 'v2')
918
        self.assertRaises(errors.WeaveInvalidChecksum, list, w.get_iter('v2'))
1185.50.26 by John Arbash Meinel
Change Weave.check() so that it checks all revisions in parallel.
919
        self.assertRaises(errors.WeaveInvalidChecksum, w.check)
1185.50.23 by John Arbash Meinel
Adding sha1 check when weave extracts a text.
920
921
1551.3.11 by Aaron Bentley
Merge from Robert
922
class InstrumentedWeave(Weave):
923
    """Keep track of how many times functions are called."""
924
    
925
    def __init__(self, weave_name=None):
926
        self._extract_count = 0
927
        Weave.__init__(self, weave_name=weave_name)
928
929
    def _extract(self, versions):
930
        self._extract_count += 1
931
        return Weave._extract(self, versions)
932
933
934
class JoinOptimization(TestCase):
935
    """Test that Weave.join() doesn't extract all texts, only what must be done."""
936
937
    def test_join(self):
938
        w1 = InstrumentedWeave()
939
        w2 = InstrumentedWeave()
940
941
        txt0 = ['a\n']
942
        txt1 = ['a\n', 'b\n']
943
        txt2 = ['a\n', 'c\n']
944
        txt3 = ['a\n', 'b\n', 'c\n']
945
946
        w1.add('txt0', [], txt0) # extract 1a
947
        w2.add('txt0', [], txt0) # extract 1b
948
        w1.add('txt1', [0], txt1)# extract 2a
949
        w2.add('txt2', [0], txt2)# extract 2b
950
        w1.join(w2) # extract 3a to add txt2 
951
        w2.join(w1) # extract 3b to add txt1 
952
953
        w1.add('txt3', [1, 2], txt3) # extract 4a 
954
        w2.add('txt3', [1, 2], txt3) # extract 4b
955
        # These secretly have inverted parents
956
957
        # This should not have to do any extractions
958
        w1.join(w2) # NO extract, texts already present with same parents
959
        w2.join(w1) # NO extract, texts already present with same parents
960
961
        self.assertEqual(4, w1._extract_count)
962
        self.assertEqual(4, w2._extract_count)
963
964
    def test_double_parent(self):
965
        # It should not be considered illegal to add
966
        # a revision with the same parent twice
967
        w1 = InstrumentedWeave()
968
        w2 = InstrumentedWeave()
969
970
        txt0 = ['a\n']
971
        txt1 = ['a\n', 'b\n']
972
        txt2 = ['a\n', 'c\n']
973
        txt3 = ['a\n', 'b\n', 'c\n']
974
975
        w1.add('txt0', [], txt0)
976
        w2.add('txt0', [], txt0)
977
        w1.add('txt1', [0], txt1)
978
        w2.add('txt1', [0,0], txt1)
979
        # Same text, effectively the same, because the
980
        # parent is only repeated
981
        w1.join(w2) # extract 3a to add txt2 
982
        w2.join(w1) # extract 3b to add txt1 
983
984
985
class MismatchedTexts(TestCase):
986
    """Test that merging two weaves with different texts fails."""
987
988
    def test_reweave(self):
989
        w1 = Weave('a')
990
        w2 = Weave('b')
991
992
        w1.add('txt0', [], ['a\n'])
993
        w2.add('txt0', [], ['a\n'])
994
        w1.add('txt1', [0], ['a\n', 'b\n'])
995
        w2.add('txt1', [0], ['a\n', 'c\n'])
996
997
        self.assertRaises(errors.WeaveTextDiffers, w1.reweave, w2)
998
999
1563.2.24 by Robert Collins
Make join cheaper for compatibly inconsistent parents.
1000
class TestNeedsRweave(TestCase):
1001
    """Internal corner cases for when reweave is needed."""
1002
1003
    def test_compatible_parents(self):
1004
        w1 = Weave('a')
1005
        my_parents = set([1, 2, 3])
1006
        # subsets are ok
1007
        self.assertTrue(w1._compatible_parents(my_parents, set([3])))
1008
        # same sets
1009
        self.assertTrue(w1._compatible_parents(my_parents, set(my_parents)))
1010
        # same empty corner case
1011
        self.assertTrue(w1._compatible_parents(set(), set()))
1012
        # other cannot contain stuff my_parents does not
1013
        self.assertFalse(w1._compatible_parents(set(), set([1])))
1014
        self.assertFalse(w1._compatible_parents(my_parents, set([1, 2, 3, 4])))
1015
        self.assertFalse(w1._compatible_parents(my_parents, set([4])))
1016
        
1017