103
103
self.overrideAttr(btree_index, '_PAGE_SIZE')
104
104
btree_index._PAGE_SIZE = 2048
106
def assertEqualsApproxCompressed(self, expected, actual, slop=6):
107
"""Check a count of compressed bytes is approximately as expected
109
Relying on compressed length being stable even with fixed inputs is
110
slightly bogus, but zlib is stable enough that this mostly works.
112
if not expected - slop < actual < expected + slop:
113
self.fail("Expected around %d bytes compressed but got %d" %
107
117
class TestBTreeBuilder(BTreeTestCase):
199
209
temp_file = builder.finish()
200
210
content = temp_file.read()
202
self.assertEqual(9283, len(content))
212
self.assertEqualsApproxCompressed(9283, len(content))
203
213
self.assertEqual(
204
214
"B+Tree Graph Index 2\nnode_ref_lists=0\nkey_elements=1\nlen=400\n"
205
215
"row_lengths=1,2\n",
233
243
temp_file = builder.finish()
234
244
content = temp_file.read()
236
self.assertEqual(155, len(content))
246
self.assertEqualsApproxCompressed(155, len(content))
237
247
self.assertEqual(
238
248
"B+Tree Graph Index 2\nnode_ref_lists=0\nkey_elements=1\nlen=10\n"
239
249
"row_lengths=1\n",
255
265
temp_file = builder.finish()
256
266
content = temp_file.read()
258
self.assertEqual(9283, len(content))
268
self.assertEqualsApproxCompressed(9283, len(content))
259
269
self.assertEqual(
260
270
"B+Tree Graph Index 2\nnode_ref_lists=0\nkey_elements=1\nlen=400\n"
261
271
"row_lengths=1,2\n",
314
324
temp_file = builder.finish()
315
325
content = temp_file.read()
317
self.assertEqual(12643, len(content))
327
self.assertEqualsApproxCompressed(12643, len(content))
318
328
self.assertEqual(
319
329
"B+Tree Graph Index 2\nnode_ref_lists=2\nkey_elements=2\nlen=200\n"
320
330
"row_lengths=1,3\n",
700
710
# The entire index should have been read, as it is one page long.
701
711
self.assertEqual([('readv', 'index', [(0, size)], False, None)],
703
self.assertEqual(1173, size)
713
self.assertEqualsApproxCompressed(1173, size)
705
715
def test_with_offset_no_size(self):
706
716
index = self.make_index_with_offset(key_elements=1, ref_lists=1,
750
760
builder.add_node(*node)
751
761
t = transport.get_transport_from_url('trace+' + self.get_url(''))
752
762
size = t.put_file('index', builder.finish())
753
self.assertEqual(17692, size)
763
self.assertEqualsApproxCompressed(17692, size)
754
764
index = btree_index.BTreeGraphIndex(t, 'index', size)
755
765
del t._activity[:]
756
766
self.assertEqual([], t._activity)
773
783
# The entire index should have been read linearly.
774
784
self.assertEqual([('readv', 'index', [(0, size)], False, None)],
776
self.assertEqual(1488, size)
786
self.assertEqualsApproxCompressed(1488, size)
778
788
def test_validate_two_pages(self):
779
789
builder = btree_index.BTreeBuilder(key_elements=2, reference_lists=2)
783
793
t = transport.get_transport_from_url('trace+' + self.get_url(''))
784
794
size = t.put_file('index', builder.finish())
785
795
# Root page, 2 leaf pages
786
self.assertEqual(9339, size)
796
self.assertEqualsApproxCompressed(9339, size)
787
797
index = btree_index.BTreeGraphIndex(t, 'index', size)
788
798
del t._activity[:]
789
799
self.assertEqual([], t._activity)
801
rem = size - 8192 # Number of remaining bytes after second block
791
802
# The entire index should have been read linearly.
792
803
self.assertEqual(
793
804
[('readv', 'index', [(0, 4096)], False, None),
794
('readv', 'index', [(4096, 4096), (8192, 1147)], False, None)],
805
('readv', 'index', [(4096, 4096), (8192, rem)], False, None)],
796
807
# XXX: TODO: write some badly-ordered nodes, and some pointers-to-wrong
797
808
# node and make validate find them.
860
871
builder.add_node(*node)
861
872
t = transport.get_transport_from_url('trace+' + self.get_url(''))
862
873
size = t.put_file('index', builder.finish())
863
self.assertEqual(1303220, size, 'number of expected bytes in the'
865
874
page_size = btree_index._PAGE_SIZE
867
876
index = btree_index.BTreeGraphIndex(t, 'index', size)
883
892
# The entire index should have been read
884
893
total_pages = sum(index._row_lengths)
885
894
self.assertEqual(total_pages, index._row_offsets[-1])
886
self.assertEqual(1303220, size)
895
self.assertEqualsApproxCompressed(1303220, size)
887
896
# The start of the leaves
888
897
first_byte = index._row_offsets[-2] * page_size
889
898
readv_request = []
890
899
for offset in range(first_byte, size, page_size):
891
900
readv_request.append((offset, page_size))
892
901
# The last page is truncated
893
readv_request[-1] = (readv_request[-1][0], 1303220 % page_size)
902
readv_request[-1] = (readv_request[-1][0], size % page_size)
894
903
expected = [('readv', 'index', [(0, page_size)], False, None),
895
904
('readv', 'index', readv_request, False, None)]
896
905
if expected != t._activity:
897
906
self.assertEqualDiff(pprint.pformat(expected),
898
pprint.pformat(transport._activity))
907
pprint.pformat(t._activity))
900
909
def _test_iter_entries_references_resolved(self):
901
910
index = self.make_index(1, nodes=[