168
165
node_content = content[73:]
169
166
node_bytes = zlib.decompress(node_content)
170
167
expected_node = (b"type=leaf\n"
171
b"0000000000000000000000000000000000000000\x00\x00value:0\n"
172
b"1111111111111111111111111111111111111111\x00\x00value:1\n"
173
b"2222222222222222222222222222222222222222\x00\x00value:2\n"
174
b"3333333333333333333333333333333333333333\x00\x00value:3\n"
175
b"4444444444444444444444444444444444444444\x00\x00value:4\n")
168
b"0000000000000000000000000000000000000000\x00\x00value:0\n"
169
b"1111111111111111111111111111111111111111\x00\x00value:1\n"
170
b"2222222222222222222222222222222222222222\x00\x00value:2\n"
171
b"3333333333333333333333333333333333333333\x00\x00value:3\n"
172
b"4444444444444444444444444444444444444444\x00\x00value:4\n")
176
173
self.assertEqual(expected_node, node_bytes)
178
175
def test_root_leaf_2_2(self):
407
404
# Test that memory and disk are both used for query methods; and that
408
405
# None is skipped over happily.
409
406
self.assertEqual([(builder,) + node for node in sorted(nodes[:13])],
410
list(builder.iter_all_entries()))
407
list(builder.iter_all_entries()))
411
408
# Two nodes - one memory one disk
412
409
self.assertEqual({(builder,) + node for node in nodes[11:13]},
413
set(builder.iter_entries([nodes[12][0], nodes[11][0]])))
410
set(builder.iter_entries([nodes[12][0], nodes[11][0]])))
414
411
self.assertEqual(13, builder.key_count())
415
412
self.assertEqual({(builder,) + node for node in nodes[11:13]},
416
set(builder.iter_entries_prefix([nodes[12][0], nodes[11][0]])))
413
set(builder.iter_entries_prefix([nodes[12][0], nodes[11][0]])))
417
414
builder.add_node(*nodes[13])
418
415
self.assertEqual(3, len(builder._backing_indices))
419
416
self.assertEqual(2, builder._backing_indices[0].key_count())
481
478
# Test that memory and disk are both used for query methods; and that
482
479
# None is skipped over happily.
483
480
self.assertEqual([(builder,) + node for node in sorted(nodes[:13])],
484
list(builder.iter_all_entries()))
481
list(builder.iter_all_entries()))
485
482
# Two nodes - one memory one disk
486
483
self.assertEqual({(builder,) + node for node in nodes[11:13]},
487
set(builder.iter_entries([nodes[12][0], nodes[11][0]])))
484
set(builder.iter_entries([nodes[12][0], nodes[11][0]])))
488
485
self.assertEqual(13, builder.key_count())
489
486
self.assertEqual({(builder,) + node for node in nodes[11:13]},
490
set(builder.iter_entries_prefix([nodes[12][0], nodes[11][0]])))
487
set(builder.iter_entries_prefix([nodes[12][0], nodes[11][0]])))
491
488
builder.add_node(*nodes[13])
492
489
builder.add_node(*nodes[14])
493
490
builder.add_node(*nodes[15])
582
578
# Test that memory and disk are both used for query methods; and that
583
579
# None is skipped over happily.
584
580
self.assertEqual([(builder,) + node for node in sorted(nodes[:13])],
585
list(builder.iter_all_entries()))
581
list(builder.iter_all_entries()))
586
582
# Two nodes - one memory one disk
587
583
self.assertEqual({(builder,) + node for node in nodes[11:13]},
588
set(builder.iter_entries([nodes[12][0], nodes[11][0]])))
584
set(builder.iter_entries([nodes[12][0], nodes[11][0]])))
589
585
self.assertEqual(13, builder.key_count())
590
586
self.assertEqual({(builder,) + node for node in nodes[11:13]},
591
set(builder.iter_entries_prefix([nodes[12][0], nodes[11][0]])))
587
set(builder.iter_entries_prefix([nodes[12][0], nodes[11][0]])))
592
588
builder.add_node(*nodes[13])
593
589
self.assertEqual(3, len(builder._backing_indices))
594
590
self.assertEqual(2, builder._backing_indices[0].key_count())
615
611
builder.add_node(*nodes[0])
616
612
builder.add_node(*nodes[1])
617
613
builder.add_node(*nodes[0])
618
self.assertRaises(_mod_index.BadIndexDuplicateKey, builder.finish)
614
self.assertRaises(errors.BadIndexDuplicateKey, builder.finish)
621
617
class TestBTreeIndex(BTreeTestCase):
623
619
def make_index(self, ref_lists=0, key_elements=1, nodes=[]):
624
620
builder = btree_index.BTreeBuilder(reference_lists=ref_lists,
625
key_elements=key_elements)
621
key_elements=key_elements)
626
622
for key, value, references in nodes:
627
623
builder.add_node(key, value, references)
628
624
stream = builder.finish()
717
713
self.assertEqual(70, index.key_count())
718
714
# The entire index should have been read, as it is one page long.
719
715
self.assertEqual([('readv', 'index', [(0, size)], False, None)],
721
717
self.assertEqualApproxCompressed(1173, size)
723
719
def test_with_offset_no_size(self):
724
720
index = self.make_index_with_offset(key_elements=1, ref_lists=1,
726
722
nodes=self.make_nodes(200, 1, 1))
727
index._size = None # throw away the size info
723
index._size = None # throw away the size info
728
724
self.assertEqual(200, index.key_count())
730
726
def test_with_small_offset(self):
820
816
t1 = transport.get_transport_from_url('trace+' + self.get_url(''))
821
817
t2 = self.get_transport()
823
btree_index.BTreeGraphIndex(t1, 'index', None)
824
== btree_index.BTreeGraphIndex(t1, 'index', None))
826
btree_index.BTreeGraphIndex(t1, 'index', 20)
827
== btree_index.BTreeGraphIndex(t1, 'index', 20))
829
btree_index.BTreeGraphIndex(t1, 'index', 20)
830
== btree_index.BTreeGraphIndex(t2, 'index', 20))
832
btree_index.BTreeGraphIndex(t1, 'inde1', 20)
833
== btree_index.BTreeGraphIndex(t1, 'inde2', 20))
835
btree_index.BTreeGraphIndex(t1, 'index', 10)
836
== btree_index.BTreeGraphIndex(t1, 'index', 20))
838
btree_index.BTreeGraphIndex(t1, 'index', None)
839
!= btree_index.BTreeGraphIndex(t1, 'index', None))
841
btree_index.BTreeGraphIndex(t1, 'index', 20)
842
!= btree_index.BTreeGraphIndex(t1, 'index', 20))
844
btree_index.BTreeGraphIndex(t1, 'index', 20)
845
!= btree_index.BTreeGraphIndex(t2, 'index', 20))
847
btree_index.BTreeGraphIndex(t1, 'inde1', 20)
848
!= btree_index.BTreeGraphIndex(t1, 'inde2', 20))
850
btree_index.BTreeGraphIndex(t1, 'index', 10)
851
!= btree_index.BTreeGraphIndex(t1, 'index', 20))
819
btree_index.BTreeGraphIndex(t1, 'index', None) ==
820
btree_index.BTreeGraphIndex(t1, 'index', None))
822
btree_index.BTreeGraphIndex(t1, 'index', 20) ==
823
btree_index.BTreeGraphIndex(t1, 'index', 20))
825
btree_index.BTreeGraphIndex(t1, 'index', 20) ==
826
btree_index.BTreeGraphIndex(t2, 'index', 20))
828
btree_index.BTreeGraphIndex(t1, 'inde1', 20) ==
829
btree_index.BTreeGraphIndex(t1, 'inde2', 20))
831
btree_index.BTreeGraphIndex(t1, 'index', 10) ==
832
btree_index.BTreeGraphIndex(t1, 'index', 20))
834
btree_index.BTreeGraphIndex(t1, 'index', None) !=
835
btree_index.BTreeGraphIndex(t1, 'index', None))
837
btree_index.BTreeGraphIndex(t1, 'index', 20) !=
838
btree_index.BTreeGraphIndex(t1, 'index', 20))
840
btree_index.BTreeGraphIndex(t1, 'index', 20) !=
841
btree_index.BTreeGraphIndex(t2, 'index', 20))
843
btree_index.BTreeGraphIndex(t1, 'inde1', 20) !=
844
btree_index.BTreeGraphIndex(t1, 'inde2', 20))
846
btree_index.BTreeGraphIndex(t1, 'index', 10) !=
847
btree_index.BTreeGraphIndex(t1, 'index', 20))
853
849
def test_key_too_big(self):
854
850
# the size that matters here is the _compressed_ size of the key, so we can't
855
851
# do a simple character repeat.
856
852
bigKey = b''.join(b'%d' % n for n in range(btree_index._PAGE_SIZE))
857
self.assertRaises(_mod_index.BadIndexKey,
853
self.assertRaises(errors.BadIndexKey,
859
855
nodes=[((bigKey,), b'value', ())])
940
936
self.assertEqual(nodes[30], bare_nodes[0])
941
937
# Should have read the root node, then one leaf page:
942
938
self.assertEqual([('readv', 'index', [(0, 4096)], False, None),
943
('readv', 'index', [(8192, 4096), ], False, None)],
939
('readv', 'index', [(8192, 4096), ], False, None)],
946
942
def test_iter_key_prefix_1_element_key_None(self):
947
943
index = self.make_index()
948
self.assertRaises(_mod_index.BadIndexKey, list,
949
index.iter_entries_prefix([(None, )]))
944
self.assertRaises(errors.BadIndexKey, list,
945
index.iter_entries_prefix([(None, )]))
951
947
def test_iter_key_prefix_wrong_length(self):
952
948
index = self.make_index()
953
self.assertRaises(_mod_index.BadIndexKey, list,
954
index.iter_entries_prefix([(b'foo', None)]))
949
self.assertRaises(errors.BadIndexKey, list,
950
index.iter_entries_prefix([(b'foo', None)]))
955
951
index = self.make_index(key_elements=2)
956
self.assertRaises(_mod_index.BadIndexKey, list,
957
index.iter_entries_prefix([(b'foo', )]))
958
self.assertRaises(_mod_index.BadIndexKey, list,
959
index.iter_entries_prefix([(b'foo', None, None)]))
952
self.assertRaises(errors.BadIndexKey, list,
953
index.iter_entries_prefix([(b'foo', )]))
954
self.assertRaises(errors.BadIndexKey, list,
955
index.iter_entries_prefix([(b'foo', None, None)]))
961
957
def test_iter_key_prefix_1_key_element_no_refs(self):
962
958
index = self.make_index(nodes=[
963
959
((b'name', ), b'data', ()),
964
960
((b'ref', ), b'refdata', ())])
965
961
self.assertEqual({(index, (b'name', ), b'data'),
966
(index, (b'ref', ), b'refdata')},
967
set(index.iter_entries_prefix([(b'name', ), (b'ref', )])))
962
(index, (b'ref', ), b'refdata')},
963
set(index.iter_entries_prefix([(b'name', ), (b'ref', )])))
969
965
def test_iter_key_prefix_1_key_element_refs(self):
970
966
index = self.make_index(1, nodes=[
971
967
((b'name', ), b'data', ([(b'ref', )], )),
972
968
((b'ref', ), b'refdata', ([], ))])
973
969
self.assertEqual({(index, (b'name', ), b'data', (((b'ref',),),)),
974
(index, (b'ref', ), b'refdata', ((), ))},
975
set(index.iter_entries_prefix([(b'name', ), (b'ref', )])))
970
(index, (b'ref', ), b'refdata', ((), ))},
971
set(index.iter_entries_prefix([(b'name', ), (b'ref', )])))
977
973
def test_iter_key_prefix_2_key_element_no_refs(self):
978
974
index = self.make_index(key_elements=2, nodes=[
980
976
((b'name', b'fin2'), b'beta', ()),
981
977
((b'ref', b'erence'), b'refdata', ())])
982
978
self.assertEqual({(index, (b'name', b'fin1'), b'data'),
983
(index, (b'ref', b'erence'), b'refdata')},
984
set(index.iter_entries_prefix(
985
[(b'name', b'fin1'), (b'ref', b'erence')])))
979
(index, (b'ref', b'erence'), b'refdata')},
980
set(index.iter_entries_prefix(
981
[(b'name', b'fin1'), (b'ref', b'erence')])))
986
982
self.assertEqual({(index, (b'name', b'fin1'), b'data'),
987
(index, (b'name', b'fin2'), b'beta')},
988
set(index.iter_entries_prefix([(b'name', None)])))
983
(index, (b'name', b'fin2'), b'beta')},
984
set(index.iter_entries_prefix([(b'name', None)])))
990
986
def test_iter_key_prefix_2_key_element_refs(self):
991
987
index = self.make_index(1, key_elements=2, nodes=[
1217
1212
def test_LeafNode_1_0(self):
1218
1213
node_bytes = (b"type=leaf\n"
1219
b"0000000000000000000000000000000000000000\x00\x00value:0\n"
1220
b"1111111111111111111111111111111111111111\x00\x00value:1\n"
1221
b"2222222222222222222222222222222222222222\x00\x00value:2\n"
1222
b"3333333333333333333333333333333333333333\x00\x00value:3\n"
1223
b"4444444444444444444444444444444444444444\x00\x00value:4\n")
1214
b"0000000000000000000000000000000000000000\x00\x00value:0\n"
1215
b"1111111111111111111111111111111111111111\x00\x00value:1\n"
1216
b"2222222222222222222222222222222222222222\x00\x00value:2\n"
1217
b"3333333333333333333333333333333333333333\x00\x00value:3\n"
1218
b"4444444444444444444444444444444444444444\x00\x00value:4\n")
1224
1219
node = btree_index._LeafNode(node_bytes, 1, 0)
1225
1220
# We do direct access, or don't care about order, to leaf nodes most of
1226
1221
# the time, so a dict is useful:
1235
1230
def test_LeafNode_2_2(self):
1236
1231
node_bytes = (b"type=leaf\n"
1237
b"00\x0000\x00\t00\x00ref00\x00value:0\n"
1238
b"00\x0011\x0000\x00ref00\t00\x00ref00\r01\x00ref01\x00value:1\n"
1239
b"11\x0033\x0011\x00ref22\t11\x00ref22\r11\x00ref22\x00value:3\n"
1240
b"11\x0044\x00\t11\x00ref00\x00value:4\n"
1232
b"00\x0000\x00\t00\x00ref00\x00value:0\n"
1233
b"00\x0011\x0000\x00ref00\t00\x00ref00\r01\x00ref01\x00value:1\n"
1234
b"11\x0033\x0011\x00ref22\t11\x00ref22\r11\x00ref22\x00value:3\n"
1235
b"11\x0044\x00\t11\x00ref00\x00value:4\n"
1243
1238
node = btree_index._LeafNode(node_bytes, 2, 2)
1244
1239
# We do direct access, or don't care about order, to leaf nodes most of
1245
1240
# the time, so a dict is useful:
1246
1241
self.assertEqual({
1247
1242
(b'00', b'00'): (b'value:0', ((), ((b'00', b'ref00'),))),
1248
1243
(b'00', b'11'): (b'value:1', (((b'00', b'ref00'),),
1249
((b'00', b'ref00'), (b'01', b'ref01')))),
1244
((b'00', b'ref00'), (b'01', b'ref01')))),
1250
1245
(b'11', b'33'): (b'value:3', (((b'11', b'ref22'),),
1251
((b'11', b'ref22'), (b'11', b'ref22')))),
1246
((b'11', b'ref22'), (b'11', b'ref22')))),
1252
1247
(b'11', b'44'): (b'value:4', ((), ((b'11', b'ref00'),)))
1253
1248
}, dict(node.all_items()))
1255
1250
def test_InternalNode_1(self):
1256
1251
node_bytes = (b"type=internal\n"
1258
b"0000000000000000000000000000000000000000\n"
1259
b"1111111111111111111111111111111111111111\n"
1260
b"2222222222222222222222222222222222222222\n"
1261
b"3333333333333333333333333333333333333333\n"
1262
b"4444444444444444444444444444444444444444\n"
1253
b"0000000000000000000000000000000000000000\n"
1254
b"1111111111111111111111111111111111111111\n"
1255
b"2222222222222222222222222222222222222222\n"
1256
b"3333333333333333333333333333333333333333\n"
1257
b"4444444444444444444444444444444444444444\n"
1264
1259
node = btree_index._InternalNode(node_bytes)
1265
1260
# We want to bisect to find the right children from this node, so a
1266
1261
# vector is most useful.
1276
1271
def test_LeafNode_2_2(self):
1277
1272
node_bytes = (b"type=leaf\n"
1278
b"00\x0000\x00\t00\x00ref00\x00value:0\n"
1279
b"00\x0011\x0000\x00ref00\t00\x00ref00\r01\x00ref01\x00value:1\n"
1280
b"11\x0033\x0011\x00ref22\t11\x00ref22\r11\x00ref22\x00value:3\n"
1281
b"11\x0044\x00\t11\x00ref00\x00value:4\n"
1273
b"00\x0000\x00\t00\x00ref00\x00value:0\n"
1274
b"00\x0011\x0000\x00ref00\t00\x00ref00\r01\x00ref01\x00value:1\n"
1275
b"11\x0033\x0011\x00ref22\t11\x00ref22\r11\x00ref22\x00value:3\n"
1276
b"11\x0044\x00\t11\x00ref00\x00value:4\n"
1284
1279
node = btree_index._LeafNode(node_bytes, 2, 2)
1285
1280
# We do direct access, or don't care about order, to leaf nodes most of
1286
1281
# the time, so a dict is useful:
1287
1282
self.assertEqual({
1288
1283
(b'00', b'00'): (b'value:0', ((), ((b'00', b'ref00'),))),
1289
1284
(b'00', b'11'): (b'value:1', (((b'00', b'ref00'),),
1290
((b'00', b'ref00'), (b'01', b'ref01')))),
1285
((b'00', b'ref00'), (b'01', b'ref01')))),
1291
1286
(b'11', b'33'): (b'value:3', (((b'11', b'ref22'),),
1292
((b'11', b'ref22'), (b'11', b'ref22')))),
1287
((b'11', b'ref22'), (b'11', b'ref22')))),
1293
1288
(b'11', b'44'): (b'value:4', ((), ((b'11', b'ref00'),)))
1294
1289
}, dict(node.all_items()))
1302
1297
def test__flatten_node(self):
1303
1298
self.assertFlattened(b'key\0\0value\n', (b'key',), b'value', [])
1304
1299
self.assertFlattened(b'key\0tuple\0\0value str\n',
1305
(b'key', b'tuple'), b'value str', [])
1300
(b'key', b'tuple'), b'value str', [])
1306
1301
self.assertFlattened(b'key\0tuple\0triple\0\0value str\n',
1307
(b'key', b'tuple', b'triple'), b'value str', [])
1302
(b'key', b'tuple', b'triple'), b'value str', [])
1308
1303
self.assertFlattened(b'k\0t\0s\0ref\0value str\n',
1309
(b'k', b't', b's'), b'value str', [[(b'ref',)]])
1304
(b'k', b't', b's'), b'value str', [[(b'ref',)]])
1310
1305
self.assertFlattened(b'key\0tuple\0ref\0key\0value str\n',
1311
(b'key', b'tuple'), b'value str', [[(b'ref', b'key')]])
1306
(b'key', b'tuple'), b'value str', [[(b'ref', b'key')]])
1312
1307
self.assertFlattened(b"00\x0000\x00\t00\x00ref00\x00value:0\n",
1313
(b'00', b'00'), b'value:0', ((), ((b'00', b'ref00'),)))
1308
(b'00', b'00'), b'value:0', ((), ((b'00', b'ref00'),)))
1314
1309
self.assertFlattened(
1315
1310
b"00\x0011\x0000\x00ref00\t00\x00ref00\r01\x00ref01\x00value:1\n",
1316
1311
(b'00', b'11'), b'value:1',
1317
(((b'00', b'ref00'),), ((b'00', b'ref00'), (b'01', b'ref01'))))
1312
(((b'00', b'ref00'),), ((b'00', b'ref00'), (b'01', b'ref01'))))
1318
1313
self.assertFlattened(
1319
1314
b"11\x0033\x0011\x00ref22\t11\x00ref22\r11\x00ref22\x00value:3\n",
1320
1315
(b'11', b'33'), b'value:3',
1321
(((b'11', b'ref22'),), ((b'11', b'ref22'), (b'11', b'ref22'))))
1316
(((b'11', b'ref22'),), ((b'11', b'ref22'), (b'11', b'ref22'))))
1322
1317
self.assertFlattened(
1323
1318
b"11\x0044\x00\t11\x00ref00\x00value:4\n",
1324
1319
(b'11', b'44'), b'value:4', ((), ((b'11', b'ref00'),)))
1352
1347
def test_exact(self):
1353
1348
self.assertMultiBisectRight([(1, ['a'])], ['a'], ['a'])
1354
self.assertMultiBisectRight(
1355
[(1, ['a']), (2, ['b'])], ['a', 'b'], ['a', 'b'])
1349
self.assertMultiBisectRight([(1, ['a']), (2, ['b'])], ['a', 'b'], ['a', 'b'])
1356
1350
self.assertMultiBisectRight([(1, ['a']), (3, ['c'])],
1357
1351
['a', 'c'], ['a', 'b', 'c'])
1456
1450
self.assertExpandOffsets([1, 4, 9], index, [1, 4, 9])
1458
1452
def test_more_than_recommended(self):
1459
index = self.make_index(4096 * 100, 2)
1453
index = self.make_index(4096*100, 2)
1460
1454
self.assertExpandOffsets([1, 10], index, [1, 10])
1461
1455
self.assertExpandOffsets([1, 10, 20], index, [1, 10, 20])
1463
1457
def test_read_all_from_root(self):
1464
index = self.make_index(4096 * 10, 20)
1458
index = self.make_index(4096*10, 20)
1465
1459
self.assertExpandOffsets(list(range(10)), index, [0])
1467
1461
def test_read_all_when_cached(self):
1468
1462
# We've read enough that we can grab all the rest in a single request
1469
index = self.make_index(4096 * 10, 5)
1463
index = self.make_index(4096*10, 5)
1470
1464
self.prepare_index(index, node_ref_lists=0, key_length=1,
1471
1465
key_count=1000, row_lengths=[1, 9],
1472
1466
cached_offsets=[0, 1, 2, 5, 6])