~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_btree_index.py

  • Committer: Jelmer Vernooij
  • Date: 2016-04-03 16:32:31 UTC
  • mto: This revision was merged to the branch mainline in revision 6617.
  • Revision ID: jelmer@jelmer.uk-20160403163231-h72bo0uyek2gikw0
Don't put French text in doc/en/user-reference when LANGUAGE=fr_CH.UTF_8.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2008-2011 Canonical Ltd
 
1
# Copyright (C) 2008-2012, 2016 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
33
33
    TestCaseWithTransport,
34
34
    scenarios,
35
35
    )
 
36
from bzrlib.tests import (
 
37
    features,
 
38
    )
36
39
 
37
40
 
38
41
load_tests = scenarios.load_tests_apply_scenarios
47
50
    return scenarios
48
51
 
49
52
 
50
 
compiled_btreeparser_feature = tests.ModuleAvailableFeature(
 
53
compiled_btreeparser_feature = features.ModuleAvailableFeature(
51
54
    'bzrlib._btree_serializer_pyx')
52
55
 
53
56
 
56
59
    # that they test.
57
60
 
58
61
    def setUp(self):
59
 
        TestCaseWithTransport.setUp(self)
 
62
        super(BTreeTestCase, self).setUp()
60
63
        self.overrideAttr(btree_index, '_RESERVED_HEADER_BYTES', 100)
61
64
 
62
65
    def make_nodes(self, count, key_elements, reference_lists):
100
103
        self.overrideAttr(btree_index, '_PAGE_SIZE')
101
104
        btree_index._PAGE_SIZE = 2048
102
105
 
103
 
    def assertEqualsApproxCompressed(self, expected, actual, slop=6):
 
106
    def assertEqualApproxCompressed(self, expected, actual, slop=6):
104
107
        """Check a count of compressed bytes is approximately as expected
105
108
 
106
109
        Relying on compressed length being stable even with fixed inputs is
206
209
        temp_file = builder.finish()
207
210
        content = temp_file.read()
208
211
        del temp_file
209
 
        self.assertEqualsApproxCompressed(9283, len(content))
 
212
        self.assertEqualApproxCompressed(9283, len(content))
210
213
        self.assertEqual(
211
214
            "B+Tree Graph Index 2\nnode_ref_lists=0\nkey_elements=1\nlen=400\n"
212
215
            "row_lengths=1,2\n",
240
243
        temp_file = builder.finish()
241
244
        content = temp_file.read()
242
245
        del temp_file
243
 
        self.assertEqualsApproxCompressed(155, len(content))
 
246
        self.assertEqualApproxCompressed(155, len(content))
244
247
        self.assertEqual(
245
248
            "B+Tree Graph Index 2\nnode_ref_lists=0\nkey_elements=1\nlen=10\n"
246
249
            "row_lengths=1\n",
262
265
        temp_file = builder.finish()
263
266
        content = temp_file.read()
264
267
        del temp_file
265
 
        self.assertEqualsApproxCompressed(9283, len(content))
 
268
        self.assertEqualApproxCompressed(9283, len(content))
266
269
        self.assertEqual(
267
270
            "B+Tree Graph Index 2\nnode_ref_lists=0\nkey_elements=1\nlen=400\n"
268
271
            "row_lengths=1,2\n",
288
291
 
289
292
        for node in nodes:
290
293
            builder.add_node(*node)
291
 
        t = transport.get_transport('trace+' + self.get_url(''))
 
294
        t = transport.get_transport_from_url('trace+' + self.get_url(''))
292
295
        size = t.put_file('index', self.time(builder.finish))
293
296
        del builder
294
297
        index = btree_index.BTreeGraphIndex(t, 'index', size)
321
324
        temp_file = builder.finish()
322
325
        content = temp_file.read()
323
326
        del temp_file
324
 
        self.assertEqualsApproxCompressed(12643, len(content))
 
327
        self.assertEqualApproxCompressed(12643, len(content))
325
328
        self.assertEqual(
326
329
            "B+Tree Graph Index 2\nnode_ref_lists=2\nkey_elements=2\nlen=200\n"
327
330
            "row_lengths=1,3\n",
615
618
        for key, value, references in nodes:
616
619
            builder.add_node(key, value, references)
617
620
        stream = builder.finish()
618
 
        trans = transport.get_transport('trace+' + self.get_url())
 
621
        trans = transport.get_transport_from_url('trace+' + self.get_url())
619
622
        size = trans.put_file('index', stream)
620
623
        return btree_index.BTreeGraphIndex(trans, 'index', size)
621
624
 
656
659
        self.assertEqual(0, len(index._leaf_node_cache))
657
660
 
658
661
    def test_trivial_constructor(self):
659
 
        t = transport.get_transport('trace+' + self.get_url(''))
 
662
        t = transport.get_transport_from_url('trace+' + self.get_url(''))
660
663
        index = btree_index.BTreeGraphIndex(t, 'index', None)
661
664
        # Checks the page size at load, but that isn't logged yet.
662
665
        self.assertEqual([], t._activity)
663
666
 
664
667
    def test_with_size_constructor(self):
665
 
        t = transport.get_transport('trace+' + self.get_url(''))
 
668
        t = transport.get_transport_from_url('trace+' + self.get_url(''))
666
669
        index = btree_index.BTreeGraphIndex(t, 'index', 1)
667
670
        # Checks the page size at load, but that isn't logged yet.
668
671
        self.assertEqual([], t._activity)
669
672
 
670
673
    def test_empty_key_count_no_size(self):
671
674
        builder = btree_index.BTreeBuilder(key_elements=1, reference_lists=0)
672
 
        t = transport.get_transport('trace+' + self.get_url(''))
 
675
        t = transport.get_transport_from_url('trace+' + self.get_url(''))
673
676
        t.put_file('index', builder.finish())
674
677
        index = btree_index.BTreeGraphIndex(t, 'index', None)
675
678
        del t._activity[:]
682
685
 
683
686
    def test_empty_key_count(self):
684
687
        builder = btree_index.BTreeBuilder(key_elements=1, reference_lists=0)
685
 
        t = transport.get_transport('trace+' + self.get_url(''))
 
688
        t = transport.get_transport_from_url('trace+' + self.get_url(''))
686
689
        size = t.put_file('index', builder.finish())
687
690
        self.assertEqual(72, size)
688
691
        index = btree_index.BTreeGraphIndex(t, 'index', size)
698
701
        nodes = self.make_nodes(35, 2, 2)
699
702
        for node in nodes:
700
703
            builder.add_node(*node)
701
 
        t = transport.get_transport('trace+' + self.get_url(''))
 
704
        t = transport.get_transport_from_url('trace+' + self.get_url(''))
702
705
        size = t.put_file('index', builder.finish())
703
706
        index = btree_index.BTreeGraphIndex(t, 'index', size)
704
707
        del t._activity[:]
707
710
        # The entire index should have been read, as it is one page long.
708
711
        self.assertEqual([('readv', 'index', [(0, size)], False, None)],
709
712
            t._activity)
710
 
        self.assertEqualsApproxCompressed(1173, size)
 
713
        self.assertEqualApproxCompressed(1173, size)
711
714
 
712
715
    def test_with_offset_no_size(self):
713
716
        index = self.make_index_with_offset(key_elements=1, ref_lists=1,
730
733
 
731
734
    def test__read_nodes_no_size_one_page_reads_once(self):
732
735
        self.make_index(nodes=[(('key',), 'value', ())])
733
 
        trans = transport.get_transport('trace+' + self.get_url())
 
736
        trans = transport.get_transport_from_url('trace+' + self.get_url())
734
737
        index = btree_index.BTreeGraphIndex(trans, 'index', None)
735
738
        del trans._activity[:]
736
739
        nodes = dict(index._read_nodes([0]))
744
747
        index.key_count()
745
748
        num_pages = index._row_offsets[-1]
746
749
        # Reopen with a traced transport and no size
747
 
        trans = transport.get_transport('trace+' + self.get_url())
 
750
        trans = transport.get_transport_from_url('trace+' + self.get_url())
748
751
        index = btree_index.BTreeGraphIndex(trans, 'index', None)
749
752
        del trans._activity[:]
750
753
        nodes = dict(index._read_nodes([0]))
755
758
        nodes = self.make_nodes(160, 2, 2)
756
759
        for node in nodes:
757
760
            builder.add_node(*node)
758
 
        t = transport.get_transport('trace+' + self.get_url(''))
 
761
        t = transport.get_transport_from_url('trace+' + self.get_url(''))
759
762
        size = t.put_file('index', builder.finish())
760
 
        self.assertEqualsApproxCompressed(17692, size)
 
763
        self.assertEqualApproxCompressed(17692, size)
761
764
        index = btree_index.BTreeGraphIndex(t, 'index', size)
762
765
        del t._activity[:]
763
766
        self.assertEqual([], t._activity)
771
774
        nodes = self.make_nodes(45, 2, 2)
772
775
        for node in nodes:
773
776
            builder.add_node(*node)
774
 
        t = transport.get_transport('trace+' + self.get_url(''))
 
777
        t = transport.get_transport_from_url('trace+' + self.get_url(''))
775
778
        size = t.put_file('index', builder.finish())
776
779
        index = btree_index.BTreeGraphIndex(t, 'index', size)
777
780
        del t._activity[:]
780
783
        # The entire index should have been read linearly.
781
784
        self.assertEqual([('readv', 'index', [(0, size)], False, None)],
782
785
                         t._activity)
783
 
        self.assertEqualsApproxCompressed(1488, size)
 
786
        self.assertEqualApproxCompressed(1488, size)
784
787
 
785
788
    def test_validate_two_pages(self):
786
789
        builder = btree_index.BTreeBuilder(key_elements=2, reference_lists=2)
787
790
        nodes = self.make_nodes(80, 2, 2)
788
791
        for node in nodes:
789
792
            builder.add_node(*node)
790
 
        t = transport.get_transport('trace+' + self.get_url(''))
 
793
        t = transport.get_transport_from_url('trace+' + self.get_url(''))
791
794
        size = t.put_file('index', builder.finish())
792
795
        # Root page, 2 leaf pages
793
 
        self.assertEqualsApproxCompressed(9339, size)
 
796
        self.assertEqualApproxCompressed(9339, size)
794
797
        index = btree_index.BTreeGraphIndex(t, 'index', size)
795
798
        del t._activity[:]
796
799
        self.assertEqual([], t._activity)
806
809
 
807
810
    def test_eq_ne(self):
808
811
        # two indices are equal when constructed with the same parameters:
809
 
        t1 = transport.get_transport('trace+' + self.get_url(''))
 
812
        t1 = transport.get_transport_from_url('trace+' + self.get_url(''))
810
813
        t2 = self.get_transport()
811
814
        self.assertTrue(
812
815
            btree_index.BTreeGraphIndex(t1, 'index', None) ==
839
842
            btree_index.BTreeGraphIndex(t1, 'index', 10) !=
840
843
            btree_index.BTreeGraphIndex(t1, 'index', 20))
841
844
 
 
845
    def test_key_too_big(self):
 
846
        # the size that matters here is the _compressed_ size of the key, so we can't
 
847
        # do a simple character repeat.
 
848
        bigKey = ''.join(map(repr, xrange(btree_index._PAGE_SIZE)))
 
849
        self.assertRaises(errors.BadIndexKey,
 
850
                          self.make_index,
 
851
                          nodes=[((bigKey,), 'value', ())])
 
852
        
842
853
    def test_iter_all_only_root_no_size(self):
843
854
        self.make_index(nodes=[(('key',), 'value', ())])
844
 
        t = transport.get_transport('trace+' + self.get_url(''))
 
855
        t = transport.get_transport_from_url('trace+' + self.get_url(''))
845
856
        index = btree_index.BTreeGraphIndex(t, 'index', None)
846
857
        del t._activity[:]
847
858
        self.assertEqual([(('key',), 'value')],
858
869
        nodes = self.make_nodes(10000, 2, 2)
859
870
        for node in nodes:
860
871
            builder.add_node(*node)
861
 
        t = transport.get_transport('trace+' + self.get_url(''))
 
872
        t = transport.get_transport_from_url('trace+' + self.get_url(''))
862
873
        size = t.put_file('index', builder.finish())
863
874
        page_size = btree_index._PAGE_SIZE
864
875
        del builder
881
892
        # The entire index should have been read
882
893
        total_pages = sum(index._row_lengths)
883
894
        self.assertEqual(total_pages, index._row_offsets[-1])
884
 
        self.assertEqualsApproxCompressed(1303220, size)
 
895
        self.assertEqualApproxCompressed(1303220, size)
885
896
        # The start of the leaves
886
897
        first_byte = index._row_offsets[-2] * page_size
887
898
        readv_request = []
911
922
        nodes = self.make_nodes(160, 2, 2)
912
923
        for node in nodes:
913
924
            builder.add_node(*node)
914
 
        t = transport.get_transport('trace+' + self.get_url(''))
 
925
        t = transport.get_transport_from_url('trace+' + self.get_url(''))
915
926
        size = t.put_file('index', builder.finish())
916
927
        del builder
917
928
        index = btree_index.BTreeGraphIndex(t, 'index', size)
1195
1206
    scenarios = btreeparser_scenarios()
1196
1207
 
1197
1208
    def setUp(self):
1198
 
        BTreeTestCase.setUp(self)
 
1209
        super(TestBTreeNodes, self).setUp()
1199
1210
        self.overrideAttr(btree_index, '_btree_serializer', self.parse_btree)
1200
1211
 
1201
1212
    def test_LeafNode_1_0(self):
1360
1371
        BTreeGraphIndex with the recommended information.
1361
1372
        """
1362
1373
        index = btree_index.BTreeGraphIndex(
1363
 
            transport.get_transport('memory:///'), 'test-index', size=size)
 
1374
            transport.get_transport_from_url('memory:///'),
 
1375
            'test-index', size=size)
1364
1376
        if recommended_pages is not None:
1365
1377
            index._recommended_pages = recommended_pages
1366
1378
        return index