~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_versionedfile.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2007-09-06 03:41:24 UTC
  • mfrom: (2794.1.3 knits)
  • Revision ID: pqm@pqm.ubuntu.com-20070906034124-gf4re7orinpud4to
(robertc) Nuke VersionedFile add/get delta support which was never used, and reduce memory copies during commits of unannotated file such as inventory. (Robert Collins).

Show diffs side-by-side

added added

removed removed

Lines of Context:
137
137
        vf.add_lines('1', [], ['a\n'])
138
138
        vf.add_lines('2', ['1'], ['a\n', 'a\n', 'a\n'],
139
139
                     left_matching_blocks=[(0, 0, 1), (1, 3, 0)])
140
 
        self.assertEqual([(1, 1, 2, [('2', 'a\n'), ('2', 'a\n')])],
141
 
                         vf.get_delta('2')[3])
 
140
        self.assertEqual(['a\n', 'a\n', 'a\n'], vf.get_lines('2'))
142
141
        vf.add_lines('3', ['1'], ['a\n', 'a\n', 'a\n'],
143
142
                     left_matching_blocks=[(0, 2, 1), (1, 3, 0)])
144
 
        self.assertEqual([(0, 0, 2, [('3', 'a\n'), ('3', 'a\n')])],
145
 
                         vf.get_delta('3')[3])
 
143
        self.assertEqual(['a\n', 'a\n', 'a\n'], vf.get_lines('3'))
146
144
 
147
145
    def test_inline_newline_throws(self):
148
146
        # \r characters are not permitted in lines being added
164
162
        self.assertRaises(errors.ReservedId,
165
163
            vf.add_lines, 'a:', [], ['a\n', 'b\n', 'c\n'])
166
164
 
167
 
        self.assertRaises(errors.ReservedId,
168
 
            vf.add_delta, 'a:', [], None, 'sha1', False, ((0, 0, 0, []),))
 
165
    def test_add_lines_nostoresha(self):
 
166
        """When nostore_sha is supplied using old content raises."""
 
167
        vf = self.get_file()
 
168
        empty_text = ('a', [])
 
169
        sample_text_nl = ('b', ["foo\n", "bar\n"])
 
170
        sample_text_no_nl = ('c', ["foo\n", "bar"])
 
171
        shas = []
 
172
        for version, lines in (empty_text, sample_text_nl, sample_text_no_nl):
 
173
            sha, _, _ = vf.add_lines(version, [], lines)
 
174
            shas.append(sha)
 
175
        # we now have a copy of all the lines in the vf.
 
176
        for sha, (version, lines) in zip(
 
177
            shas, (empty_text, sample_text_nl, sample_text_no_nl)):
 
178
            self.assertRaises(errors.ExistingContent,
 
179
                vf.add_lines, version + "2", [], lines,
 
180
                nostore_sha=sha)
 
181
            # and no new version should have been added.
 
182
            self.assertRaises(errors.RevisionNotPresent, vf.get_lines,
 
183
                version + "2")
 
184
 
 
185
    def test_add_lines_nostoresha(self):
 
186
        """When nostore_sha is supplied using old content raises."""
 
187
        vf = self.get_file()
 
188
        empty_text = ('a', [])
 
189
        sample_text_nl = ('b', ["foo\n", "bar\n"])
 
190
        sample_text_no_nl = ('c', ["foo\n", "bar"])
 
191
        shas = []
 
192
        for version, lines in (empty_text, sample_text_nl, sample_text_no_nl):
 
193
            sha, _, _ = vf.add_lines(version, [], lines)
 
194
            shas.append(sha)
 
195
        # we now have a copy of all the lines in the vf.
 
196
        # is the test applicable to this vf implementation?
 
197
        try:
 
198
            vf.add_lines_with_ghosts('d', [], [])
 
199
        except NotImplementedError:
 
200
            raise TestSkipped("add_lines_with_ghosts is optional")
 
201
        for sha, (version, lines) in zip(
 
202
            shas, (empty_text, sample_text_nl, sample_text_no_nl)):
 
203
            self.assertRaises(errors.ExistingContent,
 
204
                vf.add_lines_with_ghosts, version + "2", [], lines,
 
205
                nostore_sha=sha)
 
206
            # and no new version should have been added.
 
207
            self.assertRaises(errors.RevisionNotPresent, vf.get_lines,
 
208
                version + "2")
169
209
 
170
210
    def test_add_lines_return_value(self):
171
211
        # add_lines should return the sha1 and the text size.
189
229
 
190
230
    def test_get_reserved(self):
191
231
        vf = self.get_file()
192
 
        self.assertRaises(errors.ReservedId, vf.get_delta, 'b:')
193
232
        self.assertRaises(errors.ReservedId, vf.get_texts, ['b:'])
194
233
        self.assertRaises(errors.ReservedId, vf.get_lines, 'b:')
195
234
        self.assertRaises(errors.ReservedId, vf.get_text, 'b:')
196
235
 
197
 
    def test_get_delta(self):
198
 
        f = self.get_file()
199
 
        sha1s = self._setup_for_deltas(f)
200
 
        expected_delta = (None, '6bfa09d82ce3e898ad4641ae13dd4fdb9cf0d76b', False, 
201
 
                          [(0, 0, 1, [('base', 'line\n')])])
202
 
        self.assertEqual(expected_delta, f.get_delta('base'))
203
 
        next_parent = 'base'
204
 
        text_name = 'chain1-'
205
 
        for depth in range(26):
206
 
            new_version = text_name + '%s' % depth
207
 
            expected_delta = (next_parent, sha1s[depth], 
208
 
                              False,
209
 
                              [(depth + 1, depth + 1, 1, [(new_version, 'line\n')])])
210
 
            self.assertEqual(expected_delta, f.get_delta(new_version))
211
 
            next_parent = new_version
212
 
        next_parent = 'base'
213
 
        text_name = 'chain2-'
214
 
        for depth in range(26):
215
 
            new_version = text_name + '%s' % depth
216
 
            expected_delta = (next_parent, sha1s[depth], False,
217
 
                              [(depth + 1, depth + 1, 1, [(new_version, 'line\n')])])
218
 
            self.assertEqual(expected_delta, f.get_delta(new_version))
219
 
            next_parent = new_version
220
 
        # smoke test for eol support
221
 
        expected_delta = ('base', '264f39cab871e4cfd65b3a002f7255888bb5ed97', True, [])
222
 
        self.assertEqual(['line'], f.get_lines('noeol'))
223
 
        self.assertEqual(expected_delta, f.get_delta('noeol'))
224
 
 
225
 
    def test_get_deltas(self):
226
 
        f = self.get_file()
227
 
        sha1s = self._setup_for_deltas(f)
228
 
        deltas = f.get_deltas(f.versions())
229
 
        expected_delta = (None, '6bfa09d82ce3e898ad4641ae13dd4fdb9cf0d76b', False, 
230
 
                          [(0, 0, 1, [('base', 'line\n')])])
231
 
        self.assertEqual(expected_delta, deltas['base'])
232
 
        next_parent = 'base'
233
 
        text_name = 'chain1-'
234
 
        for depth in range(26):
235
 
            new_version = text_name + '%s' % depth
236
 
            expected_delta = (next_parent, sha1s[depth], 
237
 
                              False,
238
 
                              [(depth + 1, depth + 1, 1, [(new_version, 'line\n')])])
239
 
            self.assertEqual(expected_delta, deltas[new_version])
240
 
            next_parent = new_version
241
 
        next_parent = 'base'
242
 
        text_name = 'chain2-'
243
 
        for depth in range(26):
244
 
            new_version = text_name + '%s' % depth
245
 
            expected_delta = (next_parent, sha1s[depth], False,
246
 
                              [(depth + 1, depth + 1, 1, [(new_version, 'line\n')])])
247
 
            self.assertEqual(expected_delta, deltas[new_version])
248
 
            next_parent = new_version
249
 
        # smoke tests for eol support
250
 
        expected_delta = ('base', '264f39cab871e4cfd65b3a002f7255888bb5ed97', True, [])
251
 
        self.assertEqual(['line'], f.get_lines('noeol'))
252
 
        self.assertEqual(expected_delta, deltas['noeol'])
253
 
        # smoke tests for eol support - two noeol in a row same content
254
 
        expected_deltas = (('noeol', '3ad7ee82dbd8f29ecba073f96e43e414b3f70a4d', True, 
255
 
                          [(0, 1, 2, [('noeolsecond', 'line\n'), ('noeolsecond', 'line\n')])]),
256
 
                          ('noeol', '3ad7ee82dbd8f29ecba073f96e43e414b3f70a4d', True, 
257
 
                           [(0, 0, 1, [('noeolsecond', 'line\n')]), (1, 1, 0, [])]))
258
 
        self.assertEqual(['line\n', 'line'], f.get_lines('noeolsecond'))
259
 
        self.assertTrue(deltas['noeolsecond'] in expected_deltas)
260
 
        # two no-eol in a row, different content
261
 
        expected_delta = ('noeolsecond', '8bb553a84e019ef1149db082d65f3133b195223b', True, 
262
 
                          [(1, 2, 1, [('noeolnotshared', 'phone\n')])])
263
 
        self.assertEqual(['line\n', 'phone'], f.get_lines('noeolnotshared'))
264
 
        self.assertEqual(expected_delta, deltas['noeolnotshared'])
265
 
        # eol folling a no-eol with content change
266
 
        expected_delta = ('noeol', 'a61f6fb6cfc4596e8d88c34a308d1e724caf8977', False, 
267
 
                          [(0, 1, 1, [('eol', 'phone\n')])])
268
 
        self.assertEqual(['phone\n'], f.get_lines('eol'))
269
 
        self.assertEqual(expected_delta, deltas['eol'])
270
 
        # eol folling a no-eol with content change
271
 
        expected_delta = ('noeol', '6bfa09d82ce3e898ad4641ae13dd4fdb9cf0d76b', False, 
272
 
                          [(0, 1, 1, [('eolline', 'line\n')])])
273
 
        self.assertEqual(['line\n'], f.get_lines('eolline'))
274
 
        self.assertEqual(expected_delta, deltas['eolline'])
275
 
        # eol with no parents
276
 
        expected_delta = (None, '264f39cab871e4cfd65b3a002f7255888bb5ed97', True, 
277
 
                          [(0, 0, 1, [('noeolbase', 'line\n')])])
278
 
        self.assertEqual(['line'], f.get_lines('noeolbase'))
279
 
        self.assertEqual(expected_delta, deltas['noeolbase'])
280
 
        # eol with two parents, in inverse insertion order
281
 
        expected_deltas = (('noeolbase', '264f39cab871e4cfd65b3a002f7255888bb5ed97', True,
282
 
                            [(0, 1, 1, [('eolbeforefirstparent', 'line\n')])]),
283
 
                           ('noeolbase', '264f39cab871e4cfd65b3a002f7255888bb5ed97', True,
284
 
                            [(0, 1, 1, [('eolbeforefirstparent', 'line\n')])]))
285
 
        self.assertEqual(['line'], f.get_lines('eolbeforefirstparent'))
286
 
        #self.assertTrue(deltas['eolbeforefirstparent'] in expected_deltas)
287
 
 
288
236
    def test_make_mpdiffs(self):
289
237
        from bzrlib import multiparent
290
238
        vf = self.get_file('foo')
298
246
                                 new_vf.get_text(version))
299
247
 
300
248
    def _setup_for_deltas(self, f):
301
 
        self.assertRaises(errors.RevisionNotPresent, f.get_delta, 'base')
 
249
        self.assertFalse(f.has_version('base'))
302
250
        # add texts that should trip the knit maximum delta chain threshold
303
251
        # as well as doing parallel chains of data in knits.
304
252
        # this is done by two chains of 25 insertions
367
315
            next_parent = new_version
368
316
        return sha1s
369
317
 
370
 
    def test_add_delta(self):
371
 
        # tests for the add-delta facility.
372
 
        # at this point, optimising for speed, we assume no checks when deltas are inserted.
373
 
        # this may need to be revisited.
374
 
        source = self.get_file('source')
375
 
        source.add_lines('base', [], ['line\n'])
376
 
        next_parent = 'base'
377
 
        text_name = 'chain1-'
378
 
        text = ['line\n']
379
 
        for depth in range(26):
380
 
            new_version = text_name + '%s' % depth
381
 
            text = text + ['line\n']
382
 
            source.add_lines(new_version, [next_parent], text)
383
 
            next_parent = new_version
384
 
        next_parent = 'base'
385
 
        text_name = 'chain2-'
386
 
        text = ['line\n']
387
 
        for depth in range(26):
388
 
            new_version = text_name + '%s' % depth
389
 
            text = text + ['line\n']
390
 
            source.add_lines(new_version, [next_parent], text)
391
 
            next_parent = new_version
392
 
        source.add_lines('noeol', ['base'], ['line'])
393
 
        
394
 
        target = self.get_file('target')
395
 
        for version in source.versions():
396
 
            parent, sha1, noeol, delta = source.get_delta(version)
397
 
            target.add_delta(version,
398
 
                             source.get_parents(version),
399
 
                             parent,
400
 
                             sha1,
401
 
                             noeol,
402
 
                             delta)
403
 
        self.assertRaises(RevisionAlreadyPresent,
404
 
                          target.add_delta, 'base', [], None, '', False, [])
405
 
        for version in source.versions():
406
 
            self.assertEqual(source.get_lines(version),
407
 
                             target.get_lines(version))
408
 
 
409
318
    def test_ancestry(self):
410
319
        f = self.get_file()
411
320
        self.assertEqual([], f.get_ancestry([]))
440
349
    def test_mutate_after_finish(self):
441
350
        f = self.get_file()
442
351
        f.transaction_finished()
443
 
        self.assertRaises(errors.OutSideTransaction, f.add_delta, '', [], '', '', False, [])
444
352
        self.assertRaises(errors.OutSideTransaction, f.add_lines, '', [], [])
445
353
        self.assertRaises(errors.OutSideTransaction, f.add_lines_with_ghosts, '', [], [])
446
354
        self.assertRaises(errors.OutSideTransaction, f.fix_parents, '', [])
812
720
        factory = self.get_factory()
813
721
        vf = factory('id', transport, 0777, create=True, access_mode='w')
814
722
        vf = factory('id', transport, access_mode='r')
815
 
        self.assertRaises(errors.ReadOnlyError, vf.add_delta, '', [], '', '', False, [])
816
723
        self.assertRaises(errors.ReadOnlyError, vf.add_lines, 'base', [], [])
817
724
        self.assertRaises(errors.ReadOnlyError,
818
725
                          vf.add_lines_with_ghosts,