/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
2592.1.4 by Robert Collins
Create a GraphIndexBuilder.
1
# Copyright (C) 2007 Canonical Ltd
2
#
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
17
"""Tests for indices."""
18
2592.1.5 by Robert Collins
Trivial index reading.
19
from bzrlib import errors
2592.1.38 by Robert Collins
Create an InMemoryGraphIndex for temporary indexing.
20
from bzrlib.index import *
2592.1.4 by Robert Collins
Create a GraphIndexBuilder.
21
from bzrlib.tests import TestCaseWithMemoryTransport
22
23
24
class TestGraphIndexBuilder(TestCaseWithMemoryTransport):
25
26
    def test_build_index_empty(self):
27
        builder = GraphIndexBuilder()
28
        stream = builder.finish()
29
        contents = stream.read()
2592.1.6 by Robert Collins
Record the number of node reference lists a particular index has.
30
        self.assertEqual("Bazaar Graph Index 1\nnode_ref_lists=0\n\n", contents)
31
32
    def test_build_index_one_reference_list_empty(self):
33
        builder = GraphIndexBuilder(reference_lists=1)
34
        stream = builder.finish()
35
        contents = stream.read()
36
        self.assertEqual("Bazaar Graph Index 1\nnode_ref_lists=1\n\n", contents)
2592.1.4 by Robert Collins
Create a GraphIndexBuilder.
37
2592.1.10 by Robert Collins
Make validate detect node reference parsing errors.
38
    def test_build_index_two_reference_list_empty(self):
39
        builder = GraphIndexBuilder(reference_lists=2)
40
        stream = builder.finish()
41
        contents = stream.read()
42
        self.assertEqual("Bazaar Graph Index 1\nnode_ref_lists=2\n\n", contents)
43
2592.1.12 by Robert Collins
Handle basic node adds.
44
    def test_build_index_one_node(self):
45
        builder = GraphIndexBuilder()
46
        builder.add_node('akey', (), 'data')
47
        stream = builder.finish()
48
        contents = stream.read()
49
        self.assertEqual("Bazaar Graph Index 1\nnode_ref_lists=0\n"
2592.1.43 by Robert Collins
Various index tweaks and test clarity from John's review.
50
            "akey\x00\x00\x00data\n\n", contents)
2592.1.12 by Robert Collins
Handle basic node adds.
51
2592.1.21 by Robert Collins
Empty values are ok.
52
    def test_add_node_empty_value(self):
53
        builder = GraphIndexBuilder()
54
        builder.add_node('akey', (), '')
55
        stream = builder.finish()
56
        contents = stream.read()
57
        self.assertEqual("Bazaar Graph Index 1\nnode_ref_lists=0\n"
2592.1.43 by Robert Collins
Various index tweaks and test clarity from John's review.
58
            "akey\x00\x00\x00\n\n", contents)
2592.1.21 by Robert Collins
Empty values are ok.
59
2592.1.40 by Robert Collins
Reverse index ordering - we do not have date prefixed revids.
60
    def test_build_index_two_nodes_sorted(self):
2592.1.17 by Robert Collins
Multi node sort order is defined.
61
        # the highest sorted node comes first.
62
        builder = GraphIndexBuilder()
63
        # use three to have a good chance of glitching dictionary hash
64
        # lookups etc. Insert in randomish order that is not correct
65
        # and not the reverse of the correct order.
2592.1.40 by Robert Collins
Reverse index ordering - we do not have date prefixed revids.
66
        builder.add_node('2002', (), 'data')
67
        builder.add_node('2000', (), 'data')
2592.1.17 by Robert Collins
Multi node sort order is defined.
68
        builder.add_node('2001', (), 'data')
69
        stream = builder.finish()
70
        contents = stream.read()
71
        self.assertEqual("Bazaar Graph Index 1\nnode_ref_lists=0\n"
2592.1.43 by Robert Collins
Various index tweaks and test clarity from John's review.
72
            "2000\x00\x00\x00data\n"
73
            "2001\x00\x00\x00data\n"
74
            "2002\x00\x00\x00data\n"
2592.1.17 by Robert Collins
Multi node sort order is defined.
75
            "\n", contents)
76
2592.1.19 by Robert Collins
Node references are tab separated.
77
    def test_build_index_reference_lists_are_included_one(self):
78
        builder = GraphIndexBuilder(reference_lists=1)
79
        builder.add_node('key', ([], ), 'data')
80
        stream = builder.finish()
81
        contents = stream.read()
82
        self.assertEqual("Bazaar Graph Index 1\nnode_ref_lists=1\n"
2592.1.43 by Robert Collins
Various index tweaks and test clarity from John's review.
83
            "key\x00\x00\x00data\n"
2592.1.19 by Robert Collins
Node references are tab separated.
84
            "\n", contents)
85
86
    def test_build_index_reference_lists_are_included_two(self):
87
        builder = GraphIndexBuilder(reference_lists=2)
88
        builder.add_node('key', ([], []), 'data')
89
        stream = builder.finish()
90
        contents = stream.read()
91
        self.assertEqual("Bazaar Graph Index 1\nnode_ref_lists=2\n"
2592.1.43 by Robert Collins
Various index tweaks and test clarity from John's review.
92
            "key\x00\x00\t\x00data\n"
2592.1.19 by Robert Collins
Node references are tab separated.
93
            "\n", contents)
94
2592.1.22 by Robert Collins
Node references are byte offsets.
95
    def test_node_references_are_byte_offsets(self):
96
        builder = GraphIndexBuilder(reference_lists=1)
97
        builder.add_node('reference', ([], ), 'data')
98
        builder.add_node('key', (['reference'], ), 'data')
99
        stream = builder.finish()
100
        contents = stream.read()
101
        self.assertEqual("Bazaar Graph Index 1\nnode_ref_lists=1\n"
2592.1.40 by Robert Collins
Reverse index ordering - we do not have date prefixed revids.
102
            "key\x00\x0051\x00data\n"
103
            "reference\x00\x00\x00data\n"
2592.1.22 by Robert Collins
Node references are byte offsets.
104
            "\n", contents)
105
2592.1.23 by Robert Collins
node reference delimiting tested.
106
    def test_node_references_are_cr_delimited(self):
107
        builder = GraphIndexBuilder(reference_lists=1)
108
        builder.add_node('reference', ([], ), 'data')
109
        builder.add_node('reference2', ([], ), 'data')
110
        builder.add_node('key', (['reference', 'reference2'], ), 'data')
111
        stream = builder.finish()
112
        contents = stream.read()
113
        self.assertEqual("Bazaar Graph Index 1\nnode_ref_lists=1\n"
2592.1.43 by Robert Collins
Various index tweaks and test clarity from John's review.
114
            "key\x00\x0054\r71\x00data\n"
115
            "reference\x00\x00\x00data\n"
116
            "reference2\x00\x00\x00data\n"
2592.1.23 by Robert Collins
node reference delimiting tested.
117
            "\n", contents)
118
2592.1.24 by Robert Collins
Delimiting of multiple reference lists is by \t
119
    def test_multiple_reference_lists_are_tab_delimited(self):
120
        builder = GraphIndexBuilder(reference_lists=2)
2592.1.40 by Robert Collins
Reverse index ordering - we do not have date prefixed revids.
121
        builder.add_node('keference', ([], []), 'data')
122
        builder.add_node('rey', (['keference'], ['keference']), 'data')
2592.1.24 by Robert Collins
Delimiting of multiple reference lists is by \t
123
        stream = builder.finish()
124
        contents = stream.read()
125
        self.assertEqual("Bazaar Graph Index 1\nnode_ref_lists=2\n"
2592.1.43 by Robert Collins
Various index tweaks and test clarity from John's review.
126
            "keference\x00\x00\t\x00data\n"
127
            "rey\x00\x0038\t38\x00data\n"
2592.1.24 by Robert Collins
Delimiting of multiple reference lists is by \t
128
            "\n", contents)
129
2592.1.25 by Robert Collins
Fix and tune node offset calculation.
130
    def test_add_node_referencing_missing_key_makes_absent(self):
131
        builder = GraphIndexBuilder(reference_lists=1)
2592.1.40 by Robert Collins
Reverse index ordering - we do not have date prefixed revids.
132
        builder.add_node('rey', (['beference', 'aeference2'], ), 'data')
2592.1.25 by Robert Collins
Fix and tune node offset calculation.
133
        stream = builder.finish()
134
        contents = stream.read()
135
        self.assertEqual("Bazaar Graph Index 1\nnode_ref_lists=1\n"
2592.1.43 by Robert Collins
Various index tweaks and test clarity from John's review.
136
            "aeference2\x00a\x00\x00\n"
137
            "beference\x00a\x00\x00\n"
138
            "rey\x00\x0053\r38\x00data\n"
2592.1.25 by Robert Collins
Fix and tune node offset calculation.
139
            "\n", contents)
140
2592.1.26 by Robert Collins
Test digit buffering is accurate.
141
    def test_node_references_three_digits(self):
142
        # test the node digit expands as needed.
143
        builder = GraphIndexBuilder(reference_lists=1)
2592.1.40 by Robert Collins
Reverse index ordering - we do not have date prefixed revids.
144
        references = map(str, reversed(range(9)))
145
        builder.add_node('2-key', (references, ), '')
2592.1.26 by Robert Collins
Test digit buffering is accurate.
146
        stream = builder.finish()
147
        contents = stream.read()
148
        self.assertEqual("Bazaar Graph Index 1\nnode_ref_lists=1\n"
2592.1.40 by Robert Collins
Reverse index ordering - we do not have date prefixed revids.
149
            "0\x00a\x00\x00\n"
150
            "1\x00a\x00\x00\n"
151
            "2\x00a\x00\x00\n"
152
            "2-key\x00\x00130\r124\r118\r112\r106\r100\r050\r044\r038\x00\n"
153
            "3\x00a\x00\x00\n"
154
            "4\x00a\x00\x00\n"
155
            "5\x00a\x00\x00\n"
156
            "6\x00a\x00\x00\n"
157
            "7\x00a\x00\x00\n"
2592.1.26 by Robert Collins
Test digit buffering is accurate.
158
            "8\x00a\x00\x00\n"
2592.1.40 by Robert Collins
Reverse index ordering - we do not have date prefixed revids.
159
            "\n", contents)
160
161
    def test_absent_has_no_reference_overhead(self):
162
        # the offsets after an absent record should be correct when there are
163
        # >1 reference lists.
164
        builder = GraphIndexBuilder(reference_lists=2)
165
        builder.add_node('parent', (['aail', 'zther'], []), '')
166
        stream = builder.finish()
167
        contents = stream.read()
168
        self.assertEqual("Bazaar Graph Index 1\nnode_ref_lists=2\n"
169
            "aail\x00a\x00\x00\n"
170
            "parent\x00\x0038\r63\t\x00\n"
171
            "zther\x00a\x00\x00\n"
2592.1.26 by Robert Collins
Test digit buffering is accurate.
172
            "\n", contents)
173
2592.1.13 by Robert Collins
Handle mismatched numbers of reference lists.
174
    def test_add_node_bad_key(self):
2592.1.12 by Robert Collins
Handle basic node adds.
175
        builder = GraphIndexBuilder()
2592.1.14 by Robert Collins
Detect bad reference key values.
176
        for bad_char in '\t\n\x0b\x0c\r\x00 ':
177
            self.assertRaises(errors.BadIndexKey, builder.add_node,
178
                'a%skey' % bad_char, (), 'data')
2592.1.20 by Robert Collins
Empty keys are invalid.
179
        self.assertRaises(errors.BadIndexKey, builder.add_node,
180
                '', (), 'data')
2592.1.12 by Robert Collins
Handle basic node adds.
181
2592.1.13 by Robert Collins
Handle mismatched numbers of reference lists.
182
    def test_add_node_bad_data(self):
2592.1.12 by Robert Collins
Handle basic node adds.
183
        builder = GraphIndexBuilder()
184
        self.assertRaises(errors.BadIndexValue, builder.add_node, 'akey',
185
            (), 'data\naa')
186
        self.assertRaises(errors.BadIndexValue, builder.add_node, 'akey',
2592.1.43 by Robert Collins
Various index tweaks and test clarity from John's review.
187
            (), 'data\x00aa')
2592.1.12 by Robert Collins
Handle basic node adds.
188
2592.1.13 by Robert Collins
Handle mismatched numbers of reference lists.
189
    def test_add_node_bad_mismatched_ref_lists_length(self):
190
        builder = GraphIndexBuilder()
191
        self.assertRaises(errors.BadIndexValue, builder.add_node, 'akey',
192
            ([], ), 'data aa')
193
        builder = GraphIndexBuilder(reference_lists=1)
194
        self.assertRaises(errors.BadIndexValue, builder.add_node, 'akey',
195
            (), 'data aa')
196
        self.assertRaises(errors.BadIndexValue, builder.add_node, 'akey',
197
            ([], []), 'data aa')
198
        builder = GraphIndexBuilder(reference_lists=2)
199
        self.assertRaises(errors.BadIndexValue, builder.add_node, 'akey',
200
            (), 'data aa')
201
        self.assertRaises(errors.BadIndexValue, builder.add_node, 'akey',
202
            ([], ), 'data aa')
203
        self.assertRaises(errors.BadIndexValue, builder.add_node, 'akey',
204
            ([], [], []), 'data aa')
205
2592.1.14 by Robert Collins
Detect bad reference key values.
206
    def test_add_node_bad_key_in_reference_lists(self):
207
        # first list, first key - trivial
208
        builder = GraphIndexBuilder(reference_lists=1)
209
        self.assertRaises(errors.BadIndexKey, builder.add_node, 'akey',
210
            (['a key'], ), 'data aa')
211
        # need to check more than the first key in the list
212
        self.assertRaises(errors.BadIndexKey, builder.add_node, 'akey',
213
            (['agoodkey', 'this is a bad key'], ), 'data aa')
214
        # and if there is more than one list it should be getting checked
215
        # too
216
        builder = GraphIndexBuilder(reference_lists=2)
217
        self.assertRaises(errors.BadIndexKey, builder.add_node, 'akey',
218
            ([], ['a bad key']), 'data aa')
219
2592.1.15 by Robert Collins
Detect duplicate key insertion.
220
    def test_add_duplicate_key(self):
221
        builder = GraphIndexBuilder()
222
        builder.add_node('key', (), 'data')
223
        self.assertRaises(errors.BadIndexDuplicateKey, builder.add_node, 'key',
224
            (), 'data')
225
2592.1.16 by Robert Collins
Can add keys after referencing them.
226
    def test_add_key_after_referencing_key(self):
227
        builder = GraphIndexBuilder(reference_lists=1)
2592.1.25 by Robert Collins
Fix and tune node offset calculation.
228
        builder.add_node('key', (['reference'], ), 'data')
2592.1.16 by Robert Collins
Can add keys after referencing them.
229
        builder.add_node('reference', ([],), 'data')
230
2592.1.5 by Robert Collins
Trivial index reading.
231
232
class TestGraphIndex(TestCaseWithMemoryTransport):
233
2592.1.12 by Robert Collins
Handle basic node adds.
234
    def make_index(self, ref_lists=0, nodes=[]):
2592.1.27 by Robert Collins
Test missing end lines with non-empty indices.
235
        builder = GraphIndexBuilder(ref_lists)
2592.1.12 by Robert Collins
Handle basic node adds.
236
        for node, references, value in nodes:
237
            builder.add_node(node, references, value)
2592.1.5 by Robert Collins
Trivial index reading.
238
        stream = builder.finish()
239
        trans = self.get_transport()
2592.1.6 by Robert Collins
Record the number of node reference lists a particular index has.
240
        trans.put_file('index', stream)
2592.1.5 by Robert Collins
Trivial index reading.
241
        return GraphIndex(trans, 'index')
242
2592.1.7 by Robert Collins
A validate that goes boom.
243
    def test_open_bad_index_no_error(self):
244
        trans = self.get_transport()
245
        trans.put_bytes('name', "not an index\n")
246
        index = GraphIndex(trans, 'name')
247
2592.1.5 by Robert Collins
Trivial index reading.
248
    def test_iter_all_entries_empty(self):
249
        index = self.make_index()
250
        self.assertEqual([], list(index.iter_all_entries()))
251
2592.1.27 by Robert Collins
Test missing end lines with non-empty indices.
252
    def test_iter_all_entries_simple(self):
253
        index = self.make_index(nodes=[('name', (), 'data')])
254
        self.assertEqual([('name', (), 'data')],
255
            list(index.iter_all_entries()))
256
2592.1.28 by Robert Collins
Basic two pass iter_all_entries.
257
    def test_iter_all_entries_references_resolved(self):
258
        index = self.make_index(1, nodes=[
259
            ('name', (['ref'], ), 'data'),
260
            ('ref', ([], ), 'refdata')])
261
        self.assertEqual(set([('name', (('ref',),), 'data'),
262
            ('ref', ((), ), 'refdata')]),
263
            set(index.iter_all_entries()))
264
2592.1.30 by Robert Collins
Absent entries are not yeilded.
265
    def test_iteration_absent_skipped(self):
266
        index = self.make_index(1, nodes=[
267
            ('name', (['ref'], ), 'data')])
268
        self.assertEqual(set([('name', (('ref',),), 'data')]),
269
            set(index.iter_all_entries()))
270
        self.assertEqual(set([('name', (('ref',),), 'data')]),
271
            set(index.iter_entries(['name'])))
2592.1.35 by Robert Collins
Change the missing key interface in index operations to not raise, allowing callers to set policy.
272
        self.assertEqual([], list(index.iter_entries(['ref'])))
2592.1.30 by Robert Collins
Absent entries are not yeilded.
273
2592.1.31 by Robert Collins
Build a combined graph index to use multiple indices at once.
274
    def test_iter_all_keys(self):
2592.1.29 by Robert Collins
Basic iter_entries working.
275
        index = self.make_index(1, nodes=[
276
            ('name', (['ref'], ), 'data'),
277
            ('ref', ([], ), 'refdata')])
278
        self.assertEqual(set([('name', (('ref',),), 'data'),
279
            ('ref', ((), ), 'refdata')]),
280
            set(index.iter_entries(['name', 'ref'])))
281
2592.1.31 by Robert Collins
Build a combined graph index to use multiple indices at once.
282
    def test_iter_nothing_empty(self):
2592.1.9 by Robert Collins
Iterating no keys should work too.
283
        index = self.make_index()
284
        self.assertEqual([], list(index.iter_entries([])))
285
2592.1.5 by Robert Collins
Trivial index reading.
286
    def test_iter_missing_entry_empty(self):
287
        index = self.make_index()
2592.1.35 by Robert Collins
Change the missing key interface in index operations to not raise, allowing callers to set policy.
288
        self.assertEqual([], list(index.iter_entries(['a'])))
2592.1.7 by Robert Collins
A validate that goes boom.
289
290
    def test_validate_bad_index_errors(self):
291
        trans = self.get_transport()
292
        trans.put_bytes('name', "not an index\n")
293
        index = GraphIndex(trans, 'name')
294
        self.assertRaises(errors.BadIndexFormatSignature, index.validate)
2592.1.8 by Robert Collins
Empty files should validate ok.
295
2592.1.10 by Robert Collins
Make validate detect node reference parsing errors.
296
    def test_validate_bad_node_refs(self):
297
        index = self.make_index(2)
298
        trans = self.get_transport()
299
        content = trans.get_bytes('index')
300
        # change the options line to end with a rather than a parseable number
301
        new_content = content[:-2] + 'a\n\n'
302
        trans.put_bytes('index', new_content)
303
        self.assertRaises(errors.BadIndexOptions, index.validate)
304
2592.1.27 by Robert Collins
Test missing end lines with non-empty indices.
305
    def test_validate_missing_end_line_empty(self):
2592.1.11 by Robert Collins
Detect truncated indices.
306
        index = self.make_index(2)
307
        trans = self.get_transport()
308
        content = trans.get_bytes('index')
309
        # truncate the last byte
310
        trans.put_bytes('index', content[:-1])
311
        self.assertRaises(errors.BadIndexData, index.validate)
312
2592.1.27 by Robert Collins
Test missing end lines with non-empty indices.
313
    def test_validate_missing_end_line_nonempty(self):
314
        index = self.make_index(2, [('key', ([], []), '')])
315
        trans = self.get_transport()
316
        content = trans.get_bytes('index')
317
        # truncate the last byte
318
        trans.put_bytes('index', content[:-1])
319
        self.assertRaises(errors.BadIndexData, index.validate)
320
2592.1.8 by Robert Collins
Empty files should validate ok.
321
    def test_validate_empty(self):
322
        index = self.make_index()
323
        index.validate()
2592.1.12 by Robert Collins
Handle basic node adds.
324
325
    def test_validate_no_refs_content(self):
326
        index = self.make_index(nodes=[('key', (), 'value')])
327
        index.validate()
2592.1.31 by Robert Collins
Build a combined graph index to use multiple indices at once.
328
329
330
class TestCombinedGraphIndex(TestCaseWithMemoryTransport):
331
332
    def make_index(self, name, ref_lists=0, nodes=[]):
333
        builder = GraphIndexBuilder(ref_lists)
334
        for node, references, value in nodes:
335
            builder.add_node(node, references, value)
336
        stream = builder.finish()
337
        trans = self.get_transport()
338
        trans.put_file(name, stream)
339
        return GraphIndex(trans, name)
340
341
    def test_open_missing_index_no_error(self):
342
        trans = self.get_transport()
343
        index1 = GraphIndex(trans, 'missing')
344
        index = CombinedGraphIndex([index1])
345
2592.1.37 by Robert Collins
Add CombinedGraphIndex.insert_index.
346
    def test_add_index(self):
347
        index = CombinedGraphIndex([])
348
        index1 = self.make_index('name', nodes=[('key', (), '')])
349
        index.insert_index(0, index1)
350
        self.assertEqual([('key', (), '')], list(index.iter_all_entries()))
351
2592.1.31 by Robert Collins
Build a combined graph index to use multiple indices at once.
352
    def test_iter_all_entries_empty(self):
353
        index = CombinedGraphIndex([])
354
        self.assertEqual([], list(index.iter_all_entries()))
355
356
    def test_iter_all_entries_children_empty(self):
357
        index1 = self.make_index('name')
358
        index = CombinedGraphIndex([index1])
359
        self.assertEqual([], list(index.iter_all_entries()))
360
361
    def test_iter_all_entries_simple(self):
362
        index1 = self.make_index('name', nodes=[('name', (), 'data')])
363
        index = CombinedGraphIndex([index1])
364
        self.assertEqual([('name', (), 'data')],
365
            list(index.iter_all_entries()))
366
367
    def test_iter_all_entries_two_indices(self):
368
        index1 = self.make_index('name1', nodes=[('name', (), 'data')])
369
        index2 = self.make_index('name2', nodes=[('2', (), '')])
370
        index = CombinedGraphIndex([index1, index2])
371
        self.assertEqual([('name', (), 'data'),
372
            ('2', (), '')],
373
            list(index.iter_all_entries()))
374
2592.1.39 by Robert Collins
CombinedGraphIndex.iter_entries does not need to see all entries.
375
    def test_iter_entries_two_indices_dup_key(self):
376
        index1 = self.make_index('name1', nodes=[('name', (), 'data')])
377
        index2 = self.make_index('name2', nodes=[('name', (), 'data')])
378
        index = CombinedGraphIndex([index1, index2])
379
        self.assertEqual([('name', (), 'data')],
380
            list(index.iter_entries(['name'])))
381
2592.1.31 by Robert Collins
Build a combined graph index to use multiple indices at once.
382
    def test_iter_all_entries_two_indices_dup_key(self):
383
        index1 = self.make_index('name1', nodes=[('name', (), 'data')])
384
        index2 = self.make_index('name2', nodes=[('name', (), 'data')])
385
        index = CombinedGraphIndex([index1, index2])
386
        self.assertEqual([('name', (), 'data')],
387
            list(index.iter_all_entries()))
388
389
    def test_iter_nothing_empty(self):
390
        index = CombinedGraphIndex([])
391
        self.assertEqual([], list(index.iter_entries([])))
392
393
    def test_iter_nothing_children_empty(self):
394
        index1 = self.make_index('name')
395
        index = CombinedGraphIndex([index1])
396
        self.assertEqual([], list(index.iter_entries([])))
397
398
    def test_iter_all_keys(self):
399
        index1 = self.make_index('1', 1, nodes=[
400
            ('name', (['ref'], ), 'data')])
401
        index2 = self.make_index('2', 1, nodes=[
402
            ('ref', ([], ), 'refdata')])
403
        index = CombinedGraphIndex([index1, index2])
404
        self.assertEqual(set([('name', (('ref',),), 'data'),
405
            ('ref', ((), ), 'refdata')]),
406
            set(index.iter_entries(['name', 'ref'])))
407
 
408
    def test_iter_all_keys_dup_entry(self):
409
        index1 = self.make_index('1', 1, nodes=[
410
            ('name', (['ref'], ), 'data'),
411
            ('ref', ([], ), 'refdata')])
412
        index2 = self.make_index('2', 1, nodes=[
413
            ('ref', ([], ), 'refdata')])
414
        index = CombinedGraphIndex([index1, index2])
415
        self.assertEqual(set([('name', (('ref',),), 'data'),
416
            ('ref', ((), ), 'refdata')]),
417
            set(index.iter_entries(['name', 'ref'])))
418
 
419
    def test_iter_missing_entry_empty(self):
420
        index = CombinedGraphIndex([])
2592.1.35 by Robert Collins
Change the missing key interface in index operations to not raise, allowing callers to set policy.
421
        self.assertEqual([], list(index.iter_entries(['a'])))
2592.1.31 by Robert Collins
Build a combined graph index to use multiple indices at once.
422
423
    def test_iter_missing_entry_one_index(self):
424
        index1 = self.make_index('1')
425
        index = CombinedGraphIndex([index1])
2592.1.35 by Robert Collins
Change the missing key interface in index operations to not raise, allowing callers to set policy.
426
        self.assertEqual([], list(index.iter_entries(['a'])))
2592.1.31 by Robert Collins
Build a combined graph index to use multiple indices at once.
427
428
    def test_iter_missing_entry_two_index(self):
429
        index1 = self.make_index('1')
430
        index2 = self.make_index('2')
431
        index = CombinedGraphIndex([index1, index2])
2592.1.35 by Robert Collins
Change the missing key interface in index operations to not raise, allowing callers to set policy.
432
        self.assertEqual([], list(index.iter_entries(['a'])))
2592.1.31 by Robert Collins
Build a combined graph index to use multiple indices at once.
433
 
434
    def test_iter_entry_present_one_index_only(self):
435
        index1 = self.make_index('1', nodes=[('key', (), '')])
436
        index2 = self.make_index('2', nodes=[])
437
        index = CombinedGraphIndex([index1, index2])
438
        self.assertEqual([('key', (), '')],
439
            list(index.iter_entries(['key'])))
440
        # and in the other direction
441
        index = CombinedGraphIndex([index2, index1])
442
        self.assertEqual([('key', (), '')],
443
            list(index.iter_entries(['key'])))
444
445
    def test_validate_bad_child_index_errors(self):
446
        trans = self.get_transport()
447
        trans.put_bytes('name', "not an index\n")
448
        index1 = GraphIndex(trans, 'name')
449
        index = CombinedGraphIndex([index1])
450
        self.assertRaises(errors.BadIndexFormatSignature, index.validate)
451
452
    def test_validate_empty(self):
453
        index = CombinedGraphIndex([])
454
        index.validate()
2592.1.38 by Robert Collins
Create an InMemoryGraphIndex for temporary indexing.
455
456
457
class TestInMemoryGraphIndex(TestCaseWithMemoryTransport):
458
459
    def make_index(self, ref_lists=0, nodes=[]):
460
        result = InMemoryGraphIndex(ref_lists)
461
        result.add_nodes(nodes)
462
        return result
463
464
    def test_add_nodes(self):
465
        index = self.make_index(1)
466
        index.add_nodes([('name', ([],), 'data')])
467
        index.add_nodes([('name2', ([],), ''), ('name3', (['r'],), '')])
468
        self.assertEqual(set([
469
            ('name', ((),), 'data'),
470
            ('name2', ((),), ''),
471
            ('name3', (('r',),), ''),
472
            ]), set(index.iter_all_entries()))
473
474
    def test_iter_all_entries_empty(self):
475
        index = self.make_index()
476
        self.assertEqual([], list(index.iter_all_entries()))
477
478
    def test_iter_all_entries_simple(self):
479
        index = self.make_index(nodes=[('name', (), 'data')])
480
        self.assertEqual([('name', (), 'data')],
481
            list(index.iter_all_entries()))
482
483
    def test_iter_all_entries_references(self):
484
        index = self.make_index(1, nodes=[
485
            ('name', (['ref'], ), 'data'),
486
            ('ref', ([], ), 'refdata')])
487
        self.assertEqual(set([('name', (('ref',),), 'data'),
488
            ('ref', ((), ), 'refdata')]),
489
            set(index.iter_all_entries()))
490
491
    def test_iteration_absent_skipped(self):
492
        index = self.make_index(1, nodes=[
493
            ('name', (['ref'], ), 'data')])
494
        self.assertEqual(set([('name', (('ref',),), 'data')]),
495
            set(index.iter_all_entries()))
496
        self.assertEqual(set([('name', (('ref',),), 'data')]),
497
            set(index.iter_entries(['name'])))
498
        self.assertEqual([], list(index.iter_entries(['ref'])))
499
500
    def test_iter_all_keys(self):
501
        index = self.make_index(1, nodes=[
502
            ('name', (['ref'], ), 'data'),
503
            ('ref', ([], ), 'refdata')])
504
        self.assertEqual(set([('name', (('ref',),), 'data'),
505
            ('ref', ((), ), 'refdata')]),
506
            set(index.iter_entries(['name', 'ref'])))
507
508
    def test_iter_nothing_empty(self):
509
        index = self.make_index()
510
        self.assertEqual([], list(index.iter_entries([])))
511
512
    def test_iter_missing_entry_empty(self):
513
        index = self.make_index()
514
        self.assertEqual([], list(index.iter_entries(['a'])))
515
516
    def test_validate_empty(self):
517
        index = self.make_index()
518
        index.validate()
519
520
    def test_validate_no_refs_content(self):
521
        index = self.make_index(nodes=[('key', (), 'value')])
522
        index.validate()
523
524