~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_knit.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2011-07-16 10:47:45 UTC
  • mfrom: (6027.1.7 deprecations)
  • Revision ID: pqm@pqm.ubuntu.com-20110716104745-8n8mgnn7ld7dcf8w
(vila) Remove commands, diff and trace deprecated stuff (Vincent Ladeuil)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006-2010 Canonical Ltd
 
1
# Copyright (C) 2006-2011 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
17
17
"""Tests for Knit data structure"""
18
18
 
19
19
from cStringIO import StringIO
 
20
import gzip
20
21
import sys
21
22
 
22
23
from bzrlib import (
27
28
    pack,
28
29
    tests,
29
30
    transport,
30
 
    tuned_gzip,
31
31
    )
32
32
from bzrlib.errors import (
33
33
    KnitHeaderError,
40
40
    KnitVersionedFiles,
41
41
    PlainKnitContent,
42
42
    _VFContentMapGenerator,
43
 
    _DirectPackAccess,
44
43
    _KndxIndex,
45
44
    _KnitGraphIndex,
46
45
    _KnitKeyAccess,
47
46
    make_file_factory,
48
47
    )
49
48
from bzrlib.patiencediff import PatienceSequenceMatcher
50
 
from bzrlib.repofmt import pack_repo
 
49
from bzrlib.repofmt import (
 
50
    knitpack_repo,
 
51
    pack_repo,
 
52
    )
51
53
from bzrlib.tests import (
52
54
    TestCase,
53
55
    TestCaseWithMemoryTransport,
325
327
            transport.append_bytes(packname, bytes)
326
328
        writer = pack.ContainerWriter(write_data)
327
329
        writer.begin()
328
 
        access = _DirectPackAccess({})
 
330
        access = pack_repo._DirectPackAccess({})
329
331
        access.set_writer(writer, index, (transport, packname))
330
332
        return access, writer
331
333
 
338
340
        writer.end()
339
341
        return memos
340
342
 
 
343
    def test_pack_collection_pack_retries(self):
 
344
        """An explicit pack of a pack collection succeeds even when a
 
345
        concurrent pack happens.
 
346
        """
 
347
        builder = self.make_branch_builder('.')
 
348
        builder.start_series()
 
349
        builder.build_snapshot('rev-1', None, [
 
350
            ('add', ('', 'root-id', 'directory', None)),
 
351
            ('add', ('file', 'file-id', 'file', 'content\nrev 1\n')),
 
352
            ])
 
353
        builder.build_snapshot('rev-2', ['rev-1'], [
 
354
            ('modify', ('file-id', 'content\nrev 2\n')),
 
355
            ])
 
356
        builder.build_snapshot('rev-3', ['rev-2'], [
 
357
            ('modify', ('file-id', 'content\nrev 3\n')),
 
358
            ])
 
359
        self.addCleanup(builder.finish_series)
 
360
        b = builder.get_branch()
 
361
        self.addCleanup(b.lock_write().unlock)
 
362
        repo = b.repository
 
363
        collection = repo._pack_collection
 
364
        # Concurrently repack the repo.
 
365
        reopened_repo = repo.bzrdir.open_repository()
 
366
        reopened_repo.pack()
 
367
        # Pack the new pack.
 
368
        collection.pack()
 
369
 
341
370
    def make_vf_for_retrying(self):
342
371
        """Create 3 packs and a reload function.
343
372
 
370
399
        collection = repo._pack_collection
371
400
        collection.ensure_loaded()
372
401
        orig_packs = collection.packs
373
 
        packer = pack_repo.Packer(collection, orig_packs, '.testpack')
 
402
        packer = knitpack_repo.KnitPacker(collection, orig_packs, '.testpack')
374
403
        new_pack = packer.pack()
375
404
        # forget about the new pack
376
405
        collection.reset()
415
444
        except _TestException, e:
416
445
            retry_exc = errors.RetryWithNewPacks(None, reload_occurred=False,
417
446
                                                 exc_info=sys.exc_info())
 
447
        # GZ 2010-08-10: Cycle with exc_info affects 3 tests
418
448
        return retry_exc
419
449
 
420
450
    def test_read_from_several_packs(self):
429
459
        memos.extend(access.add_raw_records([('key', 5)], 'alpha'))
430
460
        writer.end()
431
461
        transport = self.get_transport()
432
 
        access = _DirectPackAccess({"FOO":(transport, 'packfile'),
 
462
        access = pack_repo._DirectPackAccess({"FOO":(transport, 'packfile'),
433
463
            "FOOBAR":(transport, 'pack2'),
434
464
            "BAZ":(transport, 'pack3')})
435
465
        self.assertEqual(['1234567890', '12345', 'alpha'],
445
475
 
446
476
    def test_set_writer(self):
447
477
        """The writer should be settable post construction."""
448
 
        access = _DirectPackAccess({})
 
478
        access = pack_repo._DirectPackAccess({})
449
479
        transport = self.get_transport()
450
480
        packname = 'packfile'
451
481
        index = 'foo'
463
493
        transport = self.get_transport()
464
494
        reload_called, reload_func = self.make_reload_func()
465
495
        # Note that the index key has changed from 'foo' to 'bar'
466
 
        access = _DirectPackAccess({'bar':(transport, 'packname')},
 
496
        access = pack_repo._DirectPackAccess({'bar':(transport, 'packname')},
467
497
                                   reload_func=reload_func)
468
498
        e = self.assertListRaises(errors.RetryWithNewPacks,
469
499
                                  access.get_raw_records, memos)
478
508
        memos = self.make_pack_file()
479
509
        transport = self.get_transport()
480
510
        # Note that the index key has changed from 'foo' to 'bar'
481
 
        access = _DirectPackAccess({'bar':(transport, 'packname')})
 
511
        access = pack_repo._DirectPackAccess({'bar':(transport, 'packname')})
482
512
        e = self.assertListRaises(KeyError, access.get_raw_records, memos)
483
513
 
484
514
    def test_missing_file_raises_retry(self):
486
516
        transport = self.get_transport()
487
517
        reload_called, reload_func = self.make_reload_func()
488
518
        # Note that the 'filename' has been changed to 'different-packname'
489
 
        access = _DirectPackAccess({'foo':(transport, 'different-packname')},
490
 
                                   reload_func=reload_func)
 
519
        access = pack_repo._DirectPackAccess(
 
520
            {'foo':(transport, 'different-packname')},
 
521
            reload_func=reload_func)
491
522
        e = self.assertListRaises(errors.RetryWithNewPacks,
492
523
                                  access.get_raw_records, memos)
493
524
        # The file has gone missing, so we assume we need to reload
501
532
        memos = self.make_pack_file()
502
533
        transport = self.get_transport()
503
534
        # Note that the 'filename' has been changed to 'different-packname'
504
 
        access = _DirectPackAccess({'foo':(transport, 'different-packname')})
 
535
        access = pack_repo._DirectPackAccess(
 
536
            {'foo': (transport, 'different-packname')})
505
537
        e = self.assertListRaises(errors.NoSuchFile,
506
538
                                  access.get_raw_records, memos)
507
539
 
511
543
        failing_transport = MockReadvFailingTransport(
512
544
                                [transport.get_bytes('packname')])
513
545
        reload_called, reload_func = self.make_reload_func()
514
 
        access = _DirectPackAccess({'foo':(failing_transport, 'packname')},
515
 
                                   reload_func=reload_func)
 
546
        access = pack_repo._DirectPackAccess(
 
547
            {'foo': (failing_transport, 'packname')},
 
548
            reload_func=reload_func)
516
549
        # Asking for a single record will not trigger the Mock failure
517
550
        self.assertEqual(['1234567890'],
518
551
            list(access.get_raw_records(memos[:1])))
534
567
        failing_transport = MockReadvFailingTransport(
535
568
                                [transport.get_bytes('packname')])
536
569
        reload_called, reload_func = self.make_reload_func()
537
 
        access = _DirectPackAccess({'foo':(failing_transport, 'packname')})
 
570
        access = pack_repo._DirectPackAccess(
 
571
            {'foo':(failing_transport, 'packname')})
538
572
        # Asking for a single record will not trigger the Mock failure
539
573
        self.assertEqual(['1234567890'],
540
574
            list(access.get_raw_records(memos[:1])))
545
579
                                  access.get_raw_records, memos)
546
580
 
547
581
    def test_reload_or_raise_no_reload(self):
548
 
        access = _DirectPackAccess({}, reload_func=None)
 
582
        access = pack_repo._DirectPackAccess({}, reload_func=None)
549
583
        retry_exc = self.make_retry_exception()
550
584
        # Without a reload_func, we will just re-raise the original exception
551
585
        self.assertRaises(_TestException, access.reload_or_raise, retry_exc)
552
586
 
553
587
    def test_reload_or_raise_reload_changed(self):
554
588
        reload_called, reload_func = self.make_reload_func(return_val=True)
555
 
        access = _DirectPackAccess({}, reload_func=reload_func)
 
589
        access = pack_repo._DirectPackAccess({}, reload_func=reload_func)
556
590
        retry_exc = self.make_retry_exception()
557
591
        access.reload_or_raise(retry_exc)
558
592
        self.assertEqual([1], reload_called)
562
596
 
563
597
    def test_reload_or_raise_reload_no_change(self):
564
598
        reload_called, reload_func = self.make_reload_func(return_val=False)
565
 
        access = _DirectPackAccess({}, reload_func=reload_func)
 
599
        access = pack_repo._DirectPackAccess({}, reload_func=reload_func)
566
600
        retry_exc = self.make_retry_exception()
567
601
        # If reload_occurred is False, then we consider it an error to have
568
602
        # reload_func() return False (no changes).
692
726
 
693
727
    def create_gz_content(self, text):
694
728
        sio = StringIO()
695
 
        gz_file = tuned_gzip.GzipFile(mode='wb', fileobj=sio)
 
729
        gz_file = gzip.GzipFile(mode='wb', fileobj=sio)
696
730
        gz_file.write(text)
697
731
        gz_file.close()
698
732
        return sio.getvalue()
699
733
 
700
734
    def make_multiple_records(self):
701
735
        """Create the content for multiple records."""
702
 
        sha1sum = osutils.sha('foo\nbar\n').hexdigest()
 
736
        sha1sum = osutils.sha_string('foo\nbar\n')
703
737
        total_txt = []
704
738
        gz_txt = self.create_gz_content('version rev-id-1 2 %s\n'
705
739
                                        'foo\n'
708
742
                                        % (sha1sum,))
709
743
        record_1 = (0, len(gz_txt), sha1sum)
710
744
        total_txt.append(gz_txt)
711
 
        sha1sum = osutils.sha('baz\n').hexdigest()
 
745
        sha1sum = osutils.sha_string('baz\n')
712
746
        gz_txt = self.create_gz_content('version rev-id-2 1 %s\n'
713
747
                                        'baz\n'
714
748
                                        'end rev-id-2\n'
718
752
        return total_txt, record_1, record_2
719
753
 
720
754
    def test_valid_knit_data(self):
721
 
        sha1sum = osutils.sha('foo\nbar\n').hexdigest()
 
755
        sha1sum = osutils.sha_string('foo\nbar\n')
722
756
        gz_txt = self.create_gz_content('version rev-id-1 2 %s\n'
723
757
                                        'foo\n'
724
758
                                        'bar\n'
755
789
                         raw_contents)
756
790
 
757
791
    def test_not_enough_lines(self):
758
 
        sha1sum = osutils.sha('foo\n').hexdigest()
 
792
        sha1sum = osutils.sha_string('foo\n')
759
793
        # record says 2 lines data says 1
760
794
        gz_txt = self.create_gz_content('version rev-id-1 2 %s\n'
761
795
                                        'foo\n'
773
807
        self.assertEqual([(('rev-id-1',),  gz_txt, sha1sum)], raw_contents)
774
808
 
775
809
    def test_too_many_lines(self):
776
 
        sha1sum = osutils.sha('foo\nbar\n').hexdigest()
 
810
        sha1sum = osutils.sha_string('foo\nbar\n')
777
811
        # record says 1 lines data says 2
778
812
        gz_txt = self.create_gz_content('version rev-id-1 1 %s\n'
779
813
                                        'foo\n'
792
826
        self.assertEqual([(('rev-id-1',), gz_txt, sha1sum)], raw_contents)
793
827
 
794
828
    def test_mismatched_version_id(self):
795
 
        sha1sum = osutils.sha('foo\nbar\n').hexdigest()
 
829
        sha1sum = osutils.sha_string('foo\nbar\n')
796
830
        gz_txt = self.create_gz_content('version rev-id-1 2 %s\n'
797
831
                                        'foo\n'
798
832
                                        'bar\n'
811
845
            knit._read_records_iter_raw(records))
812
846
 
813
847
    def test_uncompressed_data(self):
814
 
        sha1sum = osutils.sha('foo\nbar\n').hexdigest()
 
848
        sha1sum = osutils.sha_string('foo\nbar\n')
815
849
        txt = ('version rev-id-1 2 %s\n'
816
850
               'foo\n'
817
851
               'bar\n'
831
865
            knit._read_records_iter_raw(records))
832
866
 
833
867
    def test_corrupted_data(self):
834
 
        sha1sum = osutils.sha('foo\nbar\n').hexdigest()
 
868
        sha1sum = osutils.sha_string('foo\nbar\n')
835
869
        gz_txt = self.create_gz_content('version rev-id-1 2 %s\n'
836
870
                                        'foo\n'
837
871
                                        'bar\n'
1159
1193
            self.assertRaises(errors.KnitCorrupt, index.keys)
1160
1194
        except TypeError, e:
1161
1195
            if (str(e) == ('exceptions must be strings, classes, or instances,'
1162
 
                           ' not exceptions.IndexError')
1163
 
                and sys.version_info[0:2] >= (2,5)):
 
1196
                           ' not exceptions.IndexError')):
1164
1197
                self.knownFailure('Pyrex <0.9.5 fails with TypeError when'
1165
1198
                                  ' raising new style exceptions with python'
1166
1199
                                  ' >=2.5')
1179
1212
            self.assertRaises(errors.KnitCorrupt, index.keys)
1180
1213
        except TypeError, e:
1181
1214
            if (str(e) == ('exceptions must be strings, classes, or instances,'
1182
 
                           ' not exceptions.ValueError')
1183
 
                and sys.version_info[0:2] >= (2,5)):
 
1215
                           ' not exceptions.ValueError')):
1184
1216
                self.knownFailure('Pyrex <0.9.5 fails with TypeError when'
1185
1217
                                  ' raising new style exceptions with python'
1186
1218
                                  ' >=2.5')
1199
1231
            self.assertRaises(errors.KnitCorrupt, index.keys)
1200
1232
        except TypeError, e:
1201
1233
            if (str(e) == ('exceptions must be strings, classes, or instances,'
1202
 
                           ' not exceptions.ValueError')
1203
 
                and sys.version_info[0:2] >= (2,5)):
 
1234
                           ' not exceptions.ValueError')):
1204
1235
                self.knownFailure('Pyrex <0.9.5 fails with TypeError when'
1205
1236
                                  ' raising new style exceptions with python'
1206
1237
                                  ' >=2.5')
1217
1248
            self.assertRaises(errors.KnitCorrupt, index.keys)
1218
1249
        except TypeError, e:
1219
1250
            if (str(e) == ('exceptions must be strings, classes, or instances,'
1220
 
                           ' not exceptions.ValueError')
1221
 
                and sys.version_info[0:2] >= (2,5)):
 
1251
                           ' not exceptions.ValueError')):
1222
1252
                self.knownFailure('Pyrex <0.9.5 fails with TypeError when'
1223
1253
                                  ' raising new style exceptions with python'
1224
1254
                                  ' >=2.5')
1235
1265
            self.assertRaises(errors.KnitCorrupt, index.keys)
1236
1266
        except TypeError, e:
1237
1267
            if (str(e) == ('exceptions must be strings, classes, or instances,'
1238
 
                           ' not exceptions.ValueError')
1239
 
                and sys.version_info[0:2] >= (2,5)):
 
1268
                           ' not exceptions.ValueError')):
1240
1269
                self.knownFailure('Pyrex <0.9.5 fails with TypeError when'
1241
1270
                                  ' raising new style exceptions with python'
1242
1271
                                  ' >=2.5')
2411
2440
        key_basis = ('bar',)
2412
2441
        key_missing = ('missing',)
2413
2442
        test.add_lines(key, (), ['foo\n'])
2414
 
        key_sha1sum = osutils.sha('foo\n').hexdigest()
 
2443
        key_sha1sum = osutils.sha_string('foo\n')
2415
2444
        sha1s = test.get_sha1s([key])
2416
2445
        self.assertEqual({key: key_sha1sum}, sha1s)
2417
2446
        self.assertEqual([], basis.calls)
2419
2448
        # directly (rather than via text reconstruction) so that remote servers
2420
2449
        # etc don't have to answer with full content.
2421
2450
        basis.add_lines(key_basis, (), ['foo\n', 'bar\n'])
2422
 
        basis_sha1sum = osutils.sha('foo\nbar\n').hexdigest()
 
2451
        basis_sha1sum = osutils.sha_string('foo\nbar\n')
2423
2452
        basis.calls = []
2424
2453
        sha1s = test.get_sha1s([key, key_missing, key_basis])
2425
2454
        self.assertEqual({key: key_sha1sum,