/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_index.py

  • Committer: John Arbash Meinel
  • Date: 2009-06-12 18:05:15 UTC
  • mto: (4371.4.5 vila-better-heads)
  • mto: This revision was merged to the branch mainline in revision 4449.
  • Revision ID: john@arbash-meinel.com-20090612180515-t0cwbjsnve094oik
Add a failing test for handling nodes that are in the same linear chain.

It fails because the ancestry skipping causes us to miss the fact that the two nodes
are actually directly related. We could check at the beginning, as the 
code used to do, but I think that will be incomplete for the more-than-two
heads cases.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2007-2010 Canonical Ltd
 
1
# Copyright (C) 2007 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
 
 
181
176
    def test_node_references_are_byte_offsets(self):
182
177
        builder = GraphIndexBuilder(reference_lists=1)
183
178
        builder.add_node(('reference', ), 'data', ([], ))
235
230
        builder.add_node(('2-key', ), '', (references, ))
236
231
        stream = builder.finish()
237
232
        contents = stream.read()
238
 
        self.assertEqualDiff(
 
233
        self.assertEqual(
239
234
            "Bazaar Graph Index 1\nnode_ref_lists=1\nkey_elements=1\nlen=1\n"
240
235
            "0\x00a\x00\x00\n"
241
236
            "1\x00a\x00\x00\n"
388
383
        size = trans.put_file('index', stream)
389
384
        return GraphIndex(trans, 'index', size)
390
385
 
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
 
 
408
386
    def test_open_bad_index_no_error(self):
409
387
        trans = self.get_transport()
410
388
        trans.put_bytes('name', "not an index\n")
411
389
        index = GraphIndex(trans, 'name', 13)
412
390
 
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
 
 
433
391
    def test_open_sets_parsed_map_empty(self):
434
392
        index = self.make_index()
435
393
        self.assertEqual([], index._parsed_byte_map)
995
953
            ])
996
954
        self.assertEqual(set([]), index.external_references(0))
997
955
 
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
 
 
1060
956
 
1061
957
class TestCombinedGraphIndex(TestCaseWithMemoryTransport):
1062
958
 
1113
1009
        index.insert_index(0, index1)
1114
1010
        self.assertEqual([(index1, ('key', ), '')], list(index.iter_all_entries()))
1115
1011
 
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
 
 
1140
1012
    def test_iter_all_entries_empty(self):
1141
1013
        index = CombinedGraphIndex([])
1142
1014
        self.assertEqual([], list(index.iter_all_entries()))
1380
1252
        self.assertListRaises(errors.NoSuchFile, index.iter_entries_prefix,
1381
1253
                                                 [('1',)])
1382
1254
 
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
 
 
1427
1255
    def test_validate_reloads(self):
1428
1256
        index, reload_counter = self.make_combined_index_with_missing()
1429
1257
        index.validate()
1443
1271
                                    ['1', '2', '3'])
1444
1272
        self.assertRaises(errors.NoSuchFile, index.validate)
1445
1273
 
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
 
 
1526
1274
 
1527
1275
class TestInMemoryGraphIndex(TestCaseWithMemoryTransport):
1528
1276