~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_index.py

  • Committer: Vincent Ladeuil
  • Date: 2010-04-23 08:51:52 UTC
  • mfrom: (5131.2.6 support_OO_flag)
  • mto: This revision was merged to the branch mainline in revision 5179.
  • Revision ID: v.ladeuil+lp@free.fr-20100423085152-uoewc1vnkwqhw0pj
Manually assign docstrings to command objects, so that they work with python -OO

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2007 Canonical Ltd
 
1
# Copyright (C) 2007-2010 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
173
173
            "key\x00\x00\t\x00data\n"
174
174
            "\n", contents)
175
175
 
 
176
    def test_clear_cache(self):
 
177
        builder = GraphIndexBuilder(reference_lists=2)
 
178
        # This is a no-op, but the api should exist
 
179
        builder.clear_cache()
 
180
 
176
181
    def test_node_references_are_byte_offsets(self):
177
182
        builder = GraphIndexBuilder(reference_lists=1)
178
183
        builder.add_node(('reference', ), 'data', ([], ))
230
235
        builder.add_node(('2-key', ), '', (references, ))
231
236
        stream = builder.finish()
232
237
        contents = stream.read()
233
 
        self.assertEqual(
 
238
        self.assertEqualDiff(
234
239
            "Bazaar Graph Index 1\nnode_ref_lists=1\nkey_elements=1\nlen=1\n"
235
240
            "0\x00a\x00\x00\n"
236
241
            "1\x00a\x00\x00\n"
383
388
        size = trans.put_file('index', stream)
384
389
        return GraphIndex(trans, 'index', size)
385
390
 
 
391
    def make_index_with_offset(self, ref_lists=0, key_elements=1, nodes=[],
 
392
                               offset=0):
 
393
        builder = GraphIndexBuilder(ref_lists, key_elements=key_elements)
 
394
        for key, value, references in nodes:
 
395
            builder.add_node(key, value, references)
 
396
        content = builder.finish().read()
 
397
        size = len(content)
 
398
        trans = self.get_transport()
 
399
        trans.put_bytes('index', (' '*offset) + content)
 
400
        return GraphIndex(trans, 'index', size, offset=offset)
 
401
 
 
402
    def test_clear_cache(self):
 
403
        index = self.make_index()
 
404
        # For now, we just want to make sure the api is available. As this is
 
405
        # old code, we don't really worry if it *does* anything.
 
406
        index.clear_cache()
 
407
 
386
408
    def test_open_bad_index_no_error(self):
387
409
        trans = self.get_transport()
388
410
        trans.put_bytes('name', "not an index\n")
389
411
        index = GraphIndex(trans, 'name', 13)
390
412
 
 
413
    def test_with_offset(self):
 
414
        nodes = self.make_nodes(200)
 
415
        index = self.make_index_with_offset(offset=1234567, nodes=nodes)
 
416
        self.assertEqual(200, index.key_count())
 
417
 
 
418
    def test_buffer_all_with_offset(self):
 
419
        nodes = self.make_nodes(200)
 
420
        index = self.make_index_with_offset(offset=1234567, nodes=nodes)
 
421
        index._buffer_all()
 
422
        self.assertEqual(200, index.key_count())
 
423
 
 
424
    def test_side_effect_buffering_with_offset(self):
 
425
        nodes = self.make_nodes(20)
 
426
        index = self.make_index_with_offset(offset=1234567, nodes=nodes)
 
427
        index._transport.recommended_page_size = lambda:64*1024
 
428
        subset_nodes = [nodes[0][0], nodes[10][0], nodes[19][0]]
 
429
        entries = [n[1] for n in index.iter_entries(subset_nodes)]
 
430
        self.assertEqual(sorted(subset_nodes), sorted(entries))
 
431
        self.assertEqual(20, index.key_count())
 
432
 
391
433
    def test_open_sets_parsed_map_empty(self):
392
434
        index = self.make_index()
393
435
        self.assertEqual([], index._parsed_byte_map)
953
995
            ])
954
996
        self.assertEqual(set([]), index.external_references(0))
955
997
 
 
998
    def test__find_ancestors(self):
 
999
        key1 = ('key-1',)
 
1000
        key2 = ('key-2',)
 
1001
        index = self.make_index(ref_lists=1, key_elements=1, nodes=[
 
1002
            (key1, 'value', ([key2],)),
 
1003
            (key2, 'value', ([],)),
 
1004
            ])
 
1005
        parent_map = {}
 
1006
        missing_keys = set()
 
1007
        search_keys = index._find_ancestors([key1], 0, parent_map, missing_keys)
 
1008
        self.assertEqual({key1: (key2,)}, parent_map)
 
1009
        self.assertEqual(set(), missing_keys)
 
1010
        self.assertEqual(set([key2]), search_keys)
 
1011
        search_keys = index._find_ancestors(search_keys, 0, parent_map,
 
1012
                                            missing_keys)
 
1013
        self.assertEqual({key1: (key2,), key2: ()}, parent_map)
 
1014
        self.assertEqual(set(), missing_keys)
 
1015
        self.assertEqual(set(), search_keys)
 
1016
 
 
1017
    def test__find_ancestors_w_missing(self):
 
1018
        key1 = ('key-1',)
 
1019
        key2 = ('key-2',)
 
1020
        key3 = ('key-3',)
 
1021
        index = self.make_index(ref_lists=1, key_elements=1, nodes=[
 
1022
            (key1, 'value', ([key2],)),
 
1023
            (key2, 'value', ([],)),
 
1024
            ])
 
1025
        parent_map = {}
 
1026
        missing_keys = set()
 
1027
        search_keys = index._find_ancestors([key2, key3], 0, parent_map,
 
1028
                                            missing_keys)
 
1029
        self.assertEqual({key2: ()}, parent_map)
 
1030
        self.assertEqual(set([key3]), missing_keys)
 
1031
        self.assertEqual(set(), search_keys)
 
1032
 
 
1033
    def test__find_ancestors_dont_search_known(self):
 
1034
        key1 = ('key-1',)
 
1035
        key2 = ('key-2',)
 
1036
        key3 = ('key-3',)
 
1037
        index = self.make_index(ref_lists=1, key_elements=1, nodes=[
 
1038
            (key1, 'value', ([key2],)),
 
1039
            (key2, 'value', ([key3],)),
 
1040
            (key3, 'value', ([],)),
 
1041
            ])
 
1042
        # We already know about key2, so we won't try to search for key3
 
1043
        parent_map = {key2: (key3,)}
 
1044
        missing_keys = set()
 
1045
        search_keys = index._find_ancestors([key1], 0, parent_map,
 
1046
                                            missing_keys)
 
1047
        self.assertEqual({key1: (key2,), key2: (key3,)}, parent_map)
 
1048
        self.assertEqual(set(), missing_keys)
 
1049
        self.assertEqual(set(), search_keys)
 
1050
 
 
1051
    def test_supports_unlimited_cache(self):
 
1052
        builder = GraphIndexBuilder(0, key_elements=1)
 
1053
        stream = builder.finish()
 
1054
        trans = get_transport(self.get_url())
 
1055
        size = trans.put_file('index', stream)
 
1056
        # It doesn't matter what unlimited_cache does here, just that it can be
 
1057
        # passed
 
1058
        index = GraphIndex(trans, 'index', size, unlimited_cache=True)
 
1059
 
956
1060
 
957
1061
class TestCombinedGraphIndex(TestCaseWithMemoryTransport):
958
1062
 
1009
1113
        index.insert_index(0, index1)
1010
1114
        self.assertEqual([(index1, ('key', ), '')], list(index.iter_all_entries()))
1011
1115
 
 
1116
    def test_clear_cache(self):
 
1117
        log = []
 
1118
 
 
1119
        class ClearCacheProxy(object):
 
1120
 
 
1121
            def __init__(self, index):
 
1122
                self._index = index
 
1123
 
 
1124
            def __getattr__(self, name):
 
1125
                return getattr(self._index)
 
1126
 
 
1127
            def clear_cache(self):
 
1128
                log.append(self._index)
 
1129
                return self._index.clear_cache()
 
1130
 
 
1131
        index = CombinedGraphIndex([])
 
1132
        index1 = self.make_index('name', 0, nodes=[(('key', ), '', ())])
 
1133
        index.insert_index(0, ClearCacheProxy(index1))
 
1134
        index2 = self.make_index('name', 0, nodes=[(('key', ), '', ())])
 
1135
        index.insert_index(1, ClearCacheProxy(index2))
 
1136
        # CombinedGraphIndex should call 'clear_cache()' on all children
 
1137
        index.clear_cache()
 
1138
        self.assertEqual(sorted([index1, index2]), sorted(log))
 
1139
 
1012
1140
    def test_iter_all_entries_empty(self):
1013
1141
        index = CombinedGraphIndex([])
1014
1142
        self.assertEqual([], list(index.iter_all_entries()))
1252
1380
        self.assertListRaises(errors.NoSuchFile, index.iter_entries_prefix,
1253
1381
                                                 [('1',)])
1254
1382
 
 
1383
 
 
1384
    def make_index_with_simple_nodes(self, name, num_nodes=1):
 
1385
        """Make an index named after 'name', with keys named after 'name' too.
 
1386
 
 
1387
        Nodes will have a value of '' and no references.
 
1388
        """
 
1389
        nodes = [
 
1390
            (('index-%s-key-%s' % (name, n),), '', ())
 
1391
            for n in range(1, num_nodes+1)]
 
1392
        return self.make_index('index-%s' % name, 0, nodes=nodes)
 
1393
 
 
1394
    def test_reorder_after_iter_entries(self):
 
1395
        # Four indices: [key1] in index1, [key2,key3] in index2, [] in index3,
 
1396
        # [key4] in index4.
 
1397
        index = CombinedGraphIndex([])
 
1398
        index.insert_index(0, self.make_index_with_simple_nodes('1'), '1')
 
1399
        index.insert_index(1, self.make_index_with_simple_nodes('2'), '2')
 
1400
        index.insert_index(2, self.make_index_with_simple_nodes('3'), '3')
 
1401
        index.insert_index(3, self.make_index_with_simple_nodes('4'), '4')
 
1402
        index1, index2, index3, index4 = index._indices
 
1403
        # Query a key from index4 and index2.
 
1404
        self.assertLength(2, list(index.iter_entries(
 
1405
            [('index-4-key-1',), ('index-2-key-1',)])))
 
1406
        # Now index2 and index4 should be moved to the front (and index1 should
 
1407
        # still be before index3).
 
1408
        self.assertEqual([index2, index4, index1, index3], index._indices)
 
1409
        self.assertEqual(['2', '4', '1', '3'], index._index_names)
 
1410
 
 
1411
    def test_reorder_propagates_to_siblings(self):
 
1412
        # Two CombinedGraphIndex objects, with the same number of indicies with
 
1413
        # matching names.
 
1414
        cgi1 = CombinedGraphIndex([])
 
1415
        cgi2 = CombinedGraphIndex([])
 
1416
        cgi1.insert_index(0, self.make_index_with_simple_nodes('1-1'), 'one')
 
1417
        cgi1.insert_index(1, self.make_index_with_simple_nodes('1-2'), 'two')
 
1418
        cgi2.insert_index(0, self.make_index_with_simple_nodes('2-1'), 'one')
 
1419
        cgi2.insert_index(1, self.make_index_with_simple_nodes('2-2'), 'two')
 
1420
        index2_1, index2_2 = cgi2._indices
 
1421
        cgi1.set_sibling_indices([cgi2])
 
1422
        # Trigger a reordering in cgi1.  cgi2 will be reordered as well.
 
1423
        list(cgi1.iter_entries([('index-1-2-key-1',)]))
 
1424
        self.assertEqual([index2_2, index2_1], cgi2._indices)
 
1425
        self.assertEqual(['two', 'one'], cgi2._index_names)
 
1426
 
1255
1427
    def test_validate_reloads(self):
1256
1428
        index, reload_counter = self.make_combined_index_with_missing()
1257
1429
        index.validate()
1271
1443
                                    ['1', '2', '3'])
1272
1444
        self.assertRaises(errors.NoSuchFile, index.validate)
1273
1445
 
 
1446
    def test_find_ancestors_across_indexes(self):
 
1447
        key1 = ('key-1',)
 
1448
        key2 = ('key-2',)
 
1449
        key3 = ('key-3',)
 
1450
        key4 = ('key-4',)
 
1451
        index1 = self.make_index('12', ref_lists=1, nodes=[
 
1452
            (key1, 'value', ([],)),
 
1453
            (key2, 'value', ([key1],)),
 
1454
            ])
 
1455
        index2 = self.make_index('34', ref_lists=1, nodes=[
 
1456
            (key3, 'value', ([key2],)),
 
1457
            (key4, 'value', ([key3],)),
 
1458
            ])
 
1459
        c_index = CombinedGraphIndex([index1, index2])
 
1460
        parent_map, missing_keys = c_index.find_ancestry([key1], 0)
 
1461
        self.assertEqual({key1: ()}, parent_map)
 
1462
        self.assertEqual(set(), missing_keys)
 
1463
        # Now look for a key from index2 which requires us to find the key in
 
1464
        # the second index, and then continue searching for parents in the
 
1465
        # first index
 
1466
        parent_map, missing_keys = c_index.find_ancestry([key3], 0)
 
1467
        self.assertEqual({key1: (), key2: (key1,), key3: (key2,)}, parent_map)
 
1468
        self.assertEqual(set(), missing_keys)
 
1469
 
 
1470
    def test_find_ancestors_missing_keys(self):
 
1471
        key1 = ('key-1',)
 
1472
        key2 = ('key-2',)
 
1473
        key3 = ('key-3',)
 
1474
        key4 = ('key-4',)
 
1475
        index1 = self.make_index('12', ref_lists=1, nodes=[
 
1476
            (key1, 'value', ([],)),
 
1477
            (key2, 'value', ([key1],)),
 
1478
            ])
 
1479
        index2 = self.make_index('34', ref_lists=1, nodes=[
 
1480
            (key3, 'value', ([key2],)),
 
1481
            ])
 
1482
        c_index = CombinedGraphIndex([index1, index2])
 
1483
        # Searching for a key which is actually not present at all should
 
1484
        # eventually converge
 
1485
        parent_map, missing_keys = c_index.find_ancestry([key4], 0)
 
1486
        self.assertEqual({}, parent_map)
 
1487
        self.assertEqual(set([key4]), missing_keys)
 
1488
 
 
1489
    def test_find_ancestors_no_indexes(self):
 
1490
        c_index = CombinedGraphIndex([])
 
1491
        key1 = ('key-1',)
 
1492
        parent_map, missing_keys = c_index.find_ancestry([key1], 0)
 
1493
        self.assertEqual({}, parent_map)
 
1494
        self.assertEqual(set([key1]), missing_keys)
 
1495
 
 
1496
    def test_find_ancestors_ghost_parent(self):
 
1497
        key1 = ('key-1',)
 
1498
        key2 = ('key-2',)
 
1499
        key3 = ('key-3',)
 
1500
        key4 = ('key-4',)
 
1501
        index1 = self.make_index('12', ref_lists=1, nodes=[
 
1502
            (key1, 'value', ([],)),
 
1503
            (key2, 'value', ([key1],)),
 
1504
            ])
 
1505
        index2 = self.make_index('34', ref_lists=1, nodes=[
 
1506
            (key4, 'value', ([key2, key3],)),
 
1507
            ])
 
1508
        c_index = CombinedGraphIndex([index1, index2])
 
1509
        # Searching for a key which is actually not present at all should
 
1510
        # eventually converge
 
1511
        parent_map, missing_keys = c_index.find_ancestry([key4], 0)
 
1512
        self.assertEqual({key4: (key2, key3), key2: (key1,), key1: ()},
 
1513
                         parent_map)
 
1514
        self.assertEqual(set([key3]), missing_keys)
 
1515
 
 
1516
    def test__find_ancestors_empty_index(self):
 
1517
        index = self.make_index('test', ref_lists=1, key_elements=1, nodes=[])
 
1518
        parent_map = {}
 
1519
        missing_keys = set()
 
1520
        search_keys = index._find_ancestors([('one',), ('two',)], 0, parent_map,
 
1521
                                            missing_keys)
 
1522
        self.assertEqual(set(), search_keys)
 
1523
        self.assertEqual({}, parent_map)
 
1524
        self.assertEqual(set([('one',), ('two',)]), missing_keys)
 
1525
 
1274
1526
 
1275
1527
class TestInMemoryGraphIndex(TestCaseWithMemoryTransport):
1276
1528