100
100
self.overrideAttr(btree_index, '_PAGE_SIZE')
101
101
btree_index._PAGE_SIZE = 2048
103
def assertEqualsApproxCompressed(self, expected, actual, slop=6):
104
"""Check a count of compressed bytes is approximately as expected
106
Relying on compressed length being stable even with fixed inputs is
107
slightly bogus, but zlib is stable enough that this mostly works.
109
if not expected - slop < actual < expected + slop:
110
self.fail("Expected around %d bytes compressed but got %d" %
104
114
class TestBTreeBuilder(BTreeTestCase):
196
206
temp_file = builder.finish()
197
207
content = temp_file.read()
199
self.assertEqual(9283, len(content))
209
self.assertEqualsApproxCompressed(9283, len(content))
200
210
self.assertEqual(
201
211
"B+Tree Graph Index 2\nnode_ref_lists=0\nkey_elements=1\nlen=400\n"
202
212
"row_lengths=1,2\n",
230
240
temp_file = builder.finish()
231
241
content = temp_file.read()
233
self.assertEqual(155, len(content))
243
self.assertEqualsApproxCompressed(155, len(content))
234
244
self.assertEqual(
235
245
"B+Tree Graph Index 2\nnode_ref_lists=0\nkey_elements=1\nlen=10\n"
236
246
"row_lengths=1\n",
252
262
temp_file = builder.finish()
253
263
content = temp_file.read()
255
self.assertEqual(9283, len(content))
265
self.assertEqualsApproxCompressed(9283, len(content))
256
266
self.assertEqual(
257
267
"B+Tree Graph Index 2\nnode_ref_lists=0\nkey_elements=1\nlen=400\n"
258
268
"row_lengths=1,2\n",
311
321
temp_file = builder.finish()
312
322
content = temp_file.read()
314
self.assertEqual(12643, len(content))
324
self.assertEqualsApproxCompressed(12643, len(content))
315
325
self.assertEqual(
316
326
"B+Tree Graph Index 2\nnode_ref_lists=2\nkey_elements=2\nlen=200\n"
317
327
"row_lengths=1,3\n",
697
707
# The entire index should have been read, as it is one page long.
698
708
self.assertEqual([('readv', 'index', [(0, size)], False, None)],
700
self.assertEqual(1173, size)
710
self.assertEqualsApproxCompressed(1173, size)
702
712
def test_with_offset_no_size(self):
703
713
index = self.make_index_with_offset(key_elements=1, ref_lists=1,
747
757
builder.add_node(*node)
748
758
t = transport.get_transport('trace+' + self.get_url(''))
749
759
size = t.put_file('index', builder.finish())
750
self.assertEqual(17692, size)
760
self.assertEqualsApproxCompressed(17692, size)
751
761
index = btree_index.BTreeGraphIndex(t, 'index', size)
752
762
del t._activity[:]
753
763
self.assertEqual([], t._activity)
770
780
# The entire index should have been read linearly.
771
781
self.assertEqual([('readv', 'index', [(0, size)], False, None)],
773
self.assertEqual(1488, size)
783
self.assertEqualsApproxCompressed(1488, size)
775
785
def test_validate_two_pages(self):
776
786
builder = btree_index.BTreeBuilder(key_elements=2, reference_lists=2)
780
790
t = transport.get_transport('trace+' + self.get_url(''))
781
791
size = t.put_file('index', builder.finish())
782
792
# Root page, 2 leaf pages
783
self.assertEqual(9339, size)
793
self.assertEqualsApproxCompressed(9339, size)
784
794
index = btree_index.BTreeGraphIndex(t, 'index', size)
785
795
del t._activity[:]
786
796
self.assertEqual([], t._activity)
798
rem = size - 8192 # Number of remaining bytes after second block
788
799
# The entire index should have been read linearly.
789
800
self.assertEqual(
790
801
[('readv', 'index', [(0, 4096)], False, None),
791
('readv', 'index', [(4096, 4096), (8192, 1147)], False, None)],
802
('readv', 'index', [(4096, 4096), (8192, rem)], False, None)],
793
804
# XXX: TODO: write some badly-ordered nodes, and some pointers-to-wrong
794
805
# node and make validate find them.
849
860
builder.add_node(*node)
850
861
t = transport.get_transport('trace+' + self.get_url(''))
851
862
size = t.put_file('index', builder.finish())
852
self.assertEqual(1303220, size, 'number of expected bytes in the'
854
863
page_size = btree_index._PAGE_SIZE
856
865
index = btree_index.BTreeGraphIndex(t, 'index', size)
872
881
# The entire index should have been read
873
882
total_pages = sum(index._row_lengths)
874
883
self.assertEqual(total_pages, index._row_offsets[-1])
875
self.assertEqual(1303220, size)
884
self.assertEqualsApproxCompressed(1303220, size)
876
885
# The start of the leaves
877
886
first_byte = index._row_offsets[-2] * page_size
878
887
readv_request = []
879
888
for offset in range(first_byte, size, page_size):
880
889
readv_request.append((offset, page_size))
881
890
# The last page is truncated
882
readv_request[-1] = (readv_request[-1][0], 1303220 % page_size)
891
readv_request[-1] = (readv_request[-1][0], size % page_size)
883
892
expected = [('readv', 'index', [(0, page_size)], False, None),
884
893
('readv', 'index', readv_request, False, None)]
885
894
if expected != t._activity:
886
895
self.assertEqualDiff(pprint.pformat(expected),
887
pprint.pformat(transport._activity))
896
pprint.pformat(t._activity))
889
898
def _test_iter_entries_references_resolved(self):
890
899
index = self.make_index(1, nodes=[