~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_index.py

  • Committer: Alexander Belchenko
  • Date: 2007-09-22 17:29:16 UTC
  • mfrom: (2846 +trunk)
  • mto: This revision was merged to the branch mainline in revision 2864.
  • Revision ID: bialix@ukr.net-20070922172916-yzl05wpf8ye852gw
Bug #140419 fixed by Robert Collins

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
 
19
from bzrlib import errors
 
20
from bzrlib.index import *
 
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()
 
30
        self.assertEqual(
 
31
            "Bazaar Graph Index 1\nnode_ref_lists=0\nkey_elements=1\nlen=0\n\n",
 
32
            contents)
 
33
 
 
34
    def test_build_index_empty_two_element_keys(self):
 
35
        builder = GraphIndexBuilder(key_elements=2)
 
36
        stream = builder.finish()
 
37
        contents = stream.read()
 
38
        self.assertEqual(
 
39
            "Bazaar Graph Index 1\nnode_ref_lists=0\nkey_elements=2\nlen=0\n\n",
 
40
            contents)
 
41
 
 
42
    def test_build_index_one_reference_list_empty(self):
 
43
        builder = GraphIndexBuilder(reference_lists=1)
 
44
        stream = builder.finish()
 
45
        contents = stream.read()
 
46
        self.assertEqual(
 
47
            "Bazaar Graph Index 1\nnode_ref_lists=1\nkey_elements=1\nlen=0\n\n",
 
48
            contents)
 
49
 
 
50
    def test_build_index_two_reference_list_empty(self):
 
51
        builder = GraphIndexBuilder(reference_lists=2)
 
52
        stream = builder.finish()
 
53
        contents = stream.read()
 
54
        self.assertEqual(
 
55
            "Bazaar Graph Index 1\nnode_ref_lists=2\nkey_elements=1\nlen=0\n\n",
 
56
            contents)
 
57
 
 
58
    def test_build_index_one_node_no_refs(self):
 
59
        builder = GraphIndexBuilder()
 
60
        builder.add_node(('akey', ), 'data')
 
61
        stream = builder.finish()
 
62
        contents = stream.read()
 
63
        self.assertEqual(
 
64
            "Bazaar Graph Index 1\nnode_ref_lists=0\nkey_elements=1\nlen=1\n"
 
65
            "akey\x00\x00\x00data\n\n", contents)
 
66
 
 
67
    def test_build_index_one_node_no_refs_accepts_empty_reflist(self):
 
68
        builder = GraphIndexBuilder()
 
69
        builder.add_node(('akey', ), 'data', ())
 
70
        stream = builder.finish()
 
71
        contents = stream.read()
 
72
        self.assertEqual(
 
73
            "Bazaar Graph Index 1\nnode_ref_lists=0\nkey_elements=1\nlen=1\n"
 
74
            "akey\x00\x00\x00data\n\n", contents)
 
75
 
 
76
    def test_build_index_one_node_2_element_keys(self):
 
77
        # multipart keys are separated by \x00 - because they are fixed length,
 
78
        # not variable this does not cause any issues, and seems clearer to the
 
79
        # author.
 
80
        builder = GraphIndexBuilder(key_elements=2)
 
81
        builder.add_node(('akey', 'secondpart'), 'data')
 
82
        stream = builder.finish()
 
83
        contents = stream.read()
 
84
        self.assertEqual(
 
85
            "Bazaar Graph Index 1\nnode_ref_lists=0\nkey_elements=2\nlen=1\n"
 
86
            "akey\x00secondpart\x00\x00\x00data\n\n", contents)
 
87
 
 
88
    def test_add_node_empty_value(self):
 
89
        builder = GraphIndexBuilder()
 
90
        builder.add_node(('akey', ), '')
 
91
        stream = builder.finish()
 
92
        contents = stream.read()
 
93
        self.assertEqual(
 
94
            "Bazaar Graph Index 1\nnode_ref_lists=0\nkey_elements=1\nlen=1\n"
 
95
            "akey\x00\x00\x00\n\n", contents)
 
96
 
 
97
    def test_build_index_nodes_sorted(self):
 
98
        # the highest sorted node comes first.
 
99
        builder = GraphIndexBuilder()
 
100
        # use three to have a good chance of glitching dictionary hash
 
101
        # lookups etc. Insert in randomish order that is not correct
 
102
        # and not the reverse of the correct order.
 
103
        builder.add_node(('2002', ), 'data')
 
104
        builder.add_node(('2000', ), 'data')
 
105
        builder.add_node(('2001', ), 'data')
 
106
        stream = builder.finish()
 
107
        contents = stream.read()
 
108
        self.assertEqual(
 
109
            "Bazaar Graph Index 1\nnode_ref_lists=0\nkey_elements=1\nlen=3\n"
 
110
            "2000\x00\x00\x00data\n"
 
111
            "2001\x00\x00\x00data\n"
 
112
            "2002\x00\x00\x00data\n"
 
113
            "\n", contents)
 
114
 
 
115
    def test_build_index_2_element_key_nodes_sorted(self):
 
116
        # multiple element keys are sorted first-key, second-key.
 
117
        builder = GraphIndexBuilder(key_elements=2)
 
118
        # use three values of each key element, to have a good chance of
 
119
        # glitching dictionary hash lookups etc. Insert in randomish order that
 
120
        # is not correct and not the reverse of the correct order.
 
121
        builder.add_node(('2002', '2002'), 'data')
 
122
        builder.add_node(('2002', '2000'), 'data')
 
123
        builder.add_node(('2002', '2001'), 'data')
 
124
        builder.add_node(('2000', '2002'), 'data')
 
125
        builder.add_node(('2000', '2000'), 'data')
 
126
        builder.add_node(('2000', '2001'), 'data')
 
127
        builder.add_node(('2001', '2002'), 'data')
 
128
        builder.add_node(('2001', '2000'), 'data')
 
129
        builder.add_node(('2001', '2001'), 'data')
 
130
        stream = builder.finish()
 
131
        contents = stream.read()
 
132
        self.assertEqual(
 
133
            "Bazaar Graph Index 1\nnode_ref_lists=0\nkey_elements=2\nlen=9\n"
 
134
            "2000\x002000\x00\x00\x00data\n"
 
135
            "2000\x002001\x00\x00\x00data\n"
 
136
            "2000\x002002\x00\x00\x00data\n"
 
137
            "2001\x002000\x00\x00\x00data\n"
 
138
            "2001\x002001\x00\x00\x00data\n"
 
139
            "2001\x002002\x00\x00\x00data\n"
 
140
            "2002\x002000\x00\x00\x00data\n"
 
141
            "2002\x002001\x00\x00\x00data\n"
 
142
            "2002\x002002\x00\x00\x00data\n"
 
143
            "\n", contents)
 
144
 
 
145
    def test_build_index_reference_lists_are_included_one(self):
 
146
        builder = GraphIndexBuilder(reference_lists=1)
 
147
        builder.add_node(('key', ), 'data', ([], ))
 
148
        stream = builder.finish()
 
149
        contents = stream.read()
 
150
        self.assertEqual(
 
151
            "Bazaar Graph Index 1\nnode_ref_lists=1\nkey_elements=1\nlen=1\n"
 
152
            "key\x00\x00\x00data\n"
 
153
            "\n", contents)
 
154
 
 
155
    def test_build_index_reference_lists_with_2_element_keys(self):
 
156
        builder = GraphIndexBuilder(reference_lists=1, key_elements=2)
 
157
        builder.add_node(('key', 'key2'), 'data', ([], ))
 
158
        stream = builder.finish()
 
159
        contents = stream.read()
 
160
        self.assertEqual(
 
161
            "Bazaar Graph Index 1\nnode_ref_lists=1\nkey_elements=2\nlen=1\n"
 
162
            "key\x00key2\x00\x00\x00data\n"
 
163
            "\n", contents)
 
164
 
 
165
    def test_build_index_reference_lists_are_included_two(self):
 
166
        builder = GraphIndexBuilder(reference_lists=2)
 
167
        builder.add_node(('key', ), 'data', ([], []))
 
168
        stream = builder.finish()
 
169
        contents = stream.read()
 
170
        self.assertEqual(
 
171
            "Bazaar Graph Index 1\nnode_ref_lists=2\nkey_elements=1\nlen=1\n"
 
172
            "key\x00\x00\t\x00data\n"
 
173
            "\n", contents)
 
174
 
 
175
    def test_node_references_are_byte_offsets(self):
 
176
        builder = GraphIndexBuilder(reference_lists=1)
 
177
        builder.add_node(('reference', ), 'data', ([], ))
 
178
        builder.add_node(('key', ), 'data', ([('reference', )], ))
 
179
        stream = builder.finish()
 
180
        contents = stream.read()
 
181
        self.assertEqual(
 
182
            "Bazaar Graph Index 1\nnode_ref_lists=1\nkey_elements=1\nlen=2\n"
 
183
            "key\x00\x0072\x00data\n"
 
184
            "reference\x00\x00\x00data\n"
 
185
            "\n", contents)
 
186
 
 
187
    def test_node_references_are_cr_delimited(self):
 
188
        builder = GraphIndexBuilder(reference_lists=1)
 
189
        builder.add_node(('reference', ), 'data', ([], ))
 
190
        builder.add_node(('reference2', ), 'data', ([], ))
 
191
        builder.add_node(('key', ), 'data', ([('reference', ), ('reference2', )], ))
 
192
        stream = builder.finish()
 
193
        contents = stream.read()
 
194
        self.assertEqual(
 
195
            "Bazaar Graph Index 1\nnode_ref_lists=1\nkey_elements=1\nlen=3\n"
 
196
            "key\x00\x00077\r094\x00data\n"
 
197
            "reference\x00\x00\x00data\n"
 
198
            "reference2\x00\x00\x00data\n"
 
199
            "\n", contents)
 
200
 
 
201
    def test_multiple_reference_lists_are_tab_delimited(self):
 
202
        builder = GraphIndexBuilder(reference_lists=2)
 
203
        builder.add_node(('keference', ), 'data', ([], []))
 
204
        builder.add_node(('rey', ), 'data', ([('keference', )], [('keference', )]))
 
205
        stream = builder.finish()
 
206
        contents = stream.read()
 
207
        self.assertEqual(
 
208
            "Bazaar Graph Index 1\nnode_ref_lists=2\nkey_elements=1\nlen=2\n"
 
209
            "keference\x00\x00\t\x00data\n"
 
210
            "rey\x00\x0059\t59\x00data\n"
 
211
            "\n", contents)
 
212
 
 
213
    def test_add_node_referencing_missing_key_makes_absent(self):
 
214
        builder = GraphIndexBuilder(reference_lists=1)
 
215
        builder.add_node(('rey', ), 'data', ([('beference', ), ('aeference2', )], ))
 
216
        stream = builder.finish()
 
217
        contents = stream.read()
 
218
        self.assertEqual(
 
219
            "Bazaar Graph Index 1\nnode_ref_lists=1\nkey_elements=1\nlen=1\n"
 
220
            "aeference2\x00a\x00\x00\n"
 
221
            "beference\x00a\x00\x00\n"
 
222
            "rey\x00\x00074\r059\x00data\n"
 
223
            "\n", contents)
 
224
 
 
225
    def test_node_references_three_digits(self):
 
226
        # test the node digit expands as needed.
 
227
        builder = GraphIndexBuilder(reference_lists=1)
 
228
        references = [(str(val), ) for val in reversed(range(9))]
 
229
        builder.add_node(('2-key', ), '', (references, ))
 
230
        stream = builder.finish()
 
231
        contents = stream.read()
 
232
        self.assertEqual(
 
233
            "Bazaar Graph Index 1\nnode_ref_lists=1\nkey_elements=1\nlen=1\n"
 
234
            "0\x00a\x00\x00\n"
 
235
            "1\x00a\x00\x00\n"
 
236
            "2\x00a\x00\x00\n"
 
237
            "2-key\x00\x00151\r145\r139\r133\r127\r121\r071\r065\r059\x00\n"
 
238
            "3\x00a\x00\x00\n"
 
239
            "4\x00a\x00\x00\n"
 
240
            "5\x00a\x00\x00\n"
 
241
            "6\x00a\x00\x00\n"
 
242
            "7\x00a\x00\x00\n"
 
243
            "8\x00a\x00\x00\n"
 
244
            "\n", contents)
 
245
 
 
246
    def test_absent_has_no_reference_overhead(self):
 
247
        # the offsets after an absent record should be correct when there are
 
248
        # >1 reference lists.
 
249
        builder = GraphIndexBuilder(reference_lists=2)
 
250
        builder.add_node(('parent', ), '', ([('aail', ), ('zther', )], []))
 
251
        stream = builder.finish()
 
252
        contents = stream.read()
 
253
        self.assertEqual(
 
254
            "Bazaar Graph Index 1\nnode_ref_lists=2\nkey_elements=1\nlen=1\n"
 
255
            "aail\x00a\x00\x00\n"
 
256
            "parent\x00\x0059\r84\t\x00\n"
 
257
            "zther\x00a\x00\x00\n"
 
258
            "\n", contents)
 
259
 
 
260
    def test_add_node_bad_key(self):
 
261
        builder = GraphIndexBuilder()
 
262
        for bad_char in '\t\n\x0b\x0c\r\x00 ':
 
263
            self.assertRaises(errors.BadIndexKey, builder.add_node,
 
264
                ('a%skey' % bad_char, ), 'data')
 
265
        self.assertRaises(errors.BadIndexKey, builder.add_node,
 
266
                ('', ), 'data')
 
267
        self.assertRaises(errors.BadIndexKey, builder.add_node,
 
268
                'not-a-tuple', 'data')
 
269
        # not enough length
 
270
        self.assertRaises(errors.BadIndexKey, builder.add_node,
 
271
                (), 'data')
 
272
        # too long
 
273
        self.assertRaises(errors.BadIndexKey, builder.add_node,
 
274
                ('primary', 'secondary'), 'data')
 
275
        # secondary key elements get checked too:
 
276
        builder = GraphIndexBuilder(key_elements=2)
 
277
        for bad_char in '\t\n\x0b\x0c\r\x00 ':
 
278
            self.assertRaises(errors.BadIndexKey, builder.add_node,
 
279
                ('prefix', 'a%skey' % bad_char), 'data')
 
280
 
 
281
    def test_add_node_bad_data(self):
 
282
        builder = GraphIndexBuilder()
 
283
        self.assertRaises(errors.BadIndexValue, builder.add_node, ('akey', ),
 
284
            'data\naa')
 
285
        self.assertRaises(errors.BadIndexValue, builder.add_node, ('akey', ),
 
286
            'data\x00aa')
 
287
 
 
288
    def test_add_node_bad_mismatched_ref_lists_length(self):
 
289
        builder = GraphIndexBuilder()
 
290
        self.assertRaises(errors.BadIndexValue, builder.add_node, ('akey', ),
 
291
            'data aa', ([], ))
 
292
        builder = GraphIndexBuilder(reference_lists=1)
 
293
        self.assertRaises(errors.BadIndexValue, builder.add_node, ('akey', ),
 
294
            'data aa')
 
295
        self.assertRaises(errors.BadIndexValue, builder.add_node, ('akey', ),
 
296
            'data aa', (), )
 
297
        self.assertRaises(errors.BadIndexValue, builder.add_node, ('akey', ),
 
298
            'data aa', ([], []))
 
299
        builder = GraphIndexBuilder(reference_lists=2)
 
300
        self.assertRaises(errors.BadIndexValue, builder.add_node, ('akey', ),
 
301
            'data aa')
 
302
        self.assertRaises(errors.BadIndexValue, builder.add_node, ('akey', ),
 
303
            'data aa', ([], ))
 
304
        self.assertRaises(errors.BadIndexValue, builder.add_node, ('akey', ),
 
305
            'data aa', ([], [], []))
 
306
 
 
307
    def test_add_node_bad_key_in_reference_lists(self):
 
308
        # first list, first key - trivial
 
309
        builder = GraphIndexBuilder(reference_lists=1)
 
310
        self.assertRaises(errors.BadIndexKey, builder.add_node, ('akey', ),
 
311
            'data aa', ([('a key', )], ))
 
312
        # references keys must be tuples too
 
313
        self.assertRaises(errors.BadIndexKey, builder.add_node, ('akey', ),
 
314
            'data aa', (['not-a-tuple'], ))
 
315
        # not enough length
 
316
        self.assertRaises(errors.BadIndexKey, builder.add_node, ('akey', ),
 
317
            'data aa', ([()], ))
 
318
        # too long
 
319
        self.assertRaises(errors.BadIndexKey, builder.add_node, ('akey', ),
 
320
            'data aa', ([('primary', 'secondary')], ))
 
321
        # need to check more than the first key in the list
 
322
        self.assertRaises(errors.BadIndexKey, builder.add_node, ('akey', ),
 
323
            'data aa', ([('agoodkey', ), ('that is a bad key', )], ))
 
324
        # and if there is more than one list it should be getting checked
 
325
        # too
 
326
        builder = GraphIndexBuilder(reference_lists=2)
 
327
        self.assertRaises(errors.BadIndexKey, builder.add_node, ('akey', ),
 
328
            'data aa', ([], ['a bad key']))
 
329
 
 
330
    def test_add_duplicate_key(self):
 
331
        builder = GraphIndexBuilder()
 
332
        builder.add_node(('key', ), 'data')
 
333
        self.assertRaises(errors.BadIndexDuplicateKey, builder.add_node, ('key', ),
 
334
            'data')
 
335
 
 
336
    def test_add_duplicate_key_2_elements(self):
 
337
        builder = GraphIndexBuilder(key_elements=2)
 
338
        builder.add_node(('key', 'key'), 'data')
 
339
        self.assertRaises(errors.BadIndexDuplicateKey, builder.add_node,
 
340
            ('key', 'key'), 'data')
 
341
 
 
342
    def test_add_key_after_referencing_key(self):
 
343
        builder = GraphIndexBuilder(reference_lists=1)
 
344
        builder.add_node(('key', ), 'data', ([('reference', )], ))
 
345
        builder.add_node(('reference', ), 'data', ([],))
 
346
 
 
347
    def test_add_key_after_referencing_key_2_elements(self):
 
348
        builder = GraphIndexBuilder(reference_lists=1, key_elements=2)
 
349
        builder.add_node(('k', 'ey'), 'data', ([('reference', 'tokey')], ))
 
350
        builder.add_node(('reference', 'tokey'), 'data', ([],))
 
351
 
 
352
 
 
353
class TestGraphIndex(TestCaseWithMemoryTransport):
 
354
 
 
355
    def make_index(self, ref_lists=0, key_elements=1, nodes=[]):
 
356
        builder = GraphIndexBuilder(ref_lists, key_elements=key_elements)
 
357
        for key, value, references in nodes:
 
358
            builder.add_node(key, value, references)
 
359
        stream = builder.finish()
 
360
        trans = self.get_transport()
 
361
        trans.put_file('index', stream)
 
362
        return GraphIndex(trans, 'index')
 
363
 
 
364
    def test_open_bad_index_no_error(self):
 
365
        trans = self.get_transport()
 
366
        trans.put_bytes('name', "not an index\n")
 
367
        index = GraphIndex(trans, 'name')
 
368
 
 
369
    def test_iter_all_entries_empty(self):
 
370
        index = self.make_index()
 
371
        self.assertEqual([], list(index.iter_all_entries()))
 
372
 
 
373
    def test_iter_all_entries_simple(self):
 
374
        index = self.make_index(nodes=[(('name', ), 'data', ())])
 
375
        self.assertEqual([(index, ('name', ), 'data')],
 
376
            list(index.iter_all_entries()))
 
377
 
 
378
    def test_iter_all_entries_simple_2_elements(self):
 
379
        index = self.make_index(key_elements=2,
 
380
            nodes=[(('name', 'surname'), 'data', ())])
 
381
        self.assertEqual([(index, ('name', 'surname'), 'data')],
 
382
            list(index.iter_all_entries()))
 
383
 
 
384
    def test_iter_all_entries_references_resolved(self):
 
385
        index = self.make_index(1, nodes=[
 
386
            (('name', ), 'data', ([('ref', )], )),
 
387
            (('ref', ), 'refdata', ([], ))])
 
388
        self.assertEqual(set([(index, ('name', ), 'data', ((('ref',),),)),
 
389
            (index, ('ref', ), 'refdata', ((), ))]),
 
390
            set(index.iter_all_entries()))
 
391
 
 
392
    def test_iteration_absent_skipped(self):
 
393
        index = self.make_index(1, nodes=[
 
394
            (('name', ), 'data', ([('ref', )], ))])
 
395
        self.assertEqual(set([(index, ('name', ), 'data', ((('ref',),),))]),
 
396
            set(index.iter_all_entries()))
 
397
        self.assertEqual(set([(index, ('name', ), 'data', ((('ref',),),))]),
 
398
            set(index.iter_entries([('name', )])))
 
399
        self.assertEqual([], list(index.iter_entries([('ref', )])))
 
400
 
 
401
    def test_iteration_absent_skipped_2_element_keys(self):
 
402
        index = self.make_index(1, key_elements=2, nodes=[
 
403
            (('name', 'fin'), 'data', ([('ref', 'erence')], ))])
 
404
        self.assertEqual(set([(index, ('name', 'fin'), 'data', ((('ref', 'erence'),),))]),
 
405
            set(index.iter_all_entries()))
 
406
        self.assertEqual(set([(index, ('name', 'fin'), 'data', ((('ref', 'erence'),),))]),
 
407
            set(index.iter_entries([('name', 'fin')])))
 
408
        self.assertEqual([], list(index.iter_entries([('ref', 'erence')])))
 
409
 
 
410
    def test_iter_all_keys(self):
 
411
        index = self.make_index(1, nodes=[
 
412
            (('name', ), 'data', ([('ref', )], )),
 
413
            (('ref', ), 'refdata', ([], ))])
 
414
        self.assertEqual(set([(index, ('name', ), 'data', ((('ref',),),)),
 
415
            (index, ('ref', ), 'refdata', ((), ))]),
 
416
            set(index.iter_entries([('name', ), ('ref', )])))
 
417
 
 
418
    def test_iter_nothing_empty(self):
 
419
        index = self.make_index()
 
420
        self.assertEqual([], list(index.iter_entries([])))
 
421
 
 
422
    def test_iter_missing_entry_empty(self):
 
423
        index = self.make_index()
 
424
        self.assertEqual([], list(index.iter_entries([('a', )])))
 
425
 
 
426
    def test_iter_key_prefix_1_element_key_None(self):
 
427
        index = self.make_index()
 
428
        self.assertRaises(errors.BadIndexKey, list,
 
429
            index.iter_entries_prefix([(None, )]))
 
430
 
 
431
    def test_iter_key_prefix_wrong_length(self):
 
432
        index = self.make_index()
 
433
        self.assertRaises(errors.BadIndexKey, list,
 
434
            index.iter_entries_prefix([('foo', None)]))
 
435
        index = self.make_index(key_elements=2)
 
436
        self.assertRaises(errors.BadIndexKey, list,
 
437
            index.iter_entries_prefix([('foo', )]))
 
438
        self.assertRaises(errors.BadIndexKey, list,
 
439
            index.iter_entries_prefix([('foo', None, None)]))
 
440
 
 
441
    def test_iter_key_prefix_1_key_element_no_refs(self):
 
442
        index = self.make_index( nodes=[
 
443
            (('name', ), 'data', ()),
 
444
            (('ref', ), 'refdata', ())])
 
445
        self.assertEqual(set([(index, ('name', ), 'data'),
 
446
            (index, ('ref', ), 'refdata')]),
 
447
            set(index.iter_entries_prefix([('name', ), ('ref', )])))
 
448
 
 
449
    def test_iter_key_prefix_1_key_element_refs(self):
 
450
        index = self.make_index(1, nodes=[
 
451
            (('name', ), 'data', ([('ref', )], )),
 
452
            (('ref', ), 'refdata', ([], ))])
 
453
        self.assertEqual(set([(index, ('name', ), 'data', ((('ref',),),)),
 
454
            (index, ('ref', ), 'refdata', ((), ))]),
 
455
            set(index.iter_entries_prefix([('name', ), ('ref', )])))
 
456
 
 
457
    def test_iter_key_prefix_2_key_element_no_refs(self):
 
458
        index = self.make_index(key_elements=2, nodes=[
 
459
            (('name', 'fin1'), 'data', ()),
 
460
            (('name', 'fin2'), 'beta', ()),
 
461
            (('ref', 'erence'), 'refdata', ())])
 
462
        self.assertEqual(set([(index, ('name', 'fin1'), 'data'),
 
463
            (index, ('ref', 'erence'), 'refdata')]),
 
464
            set(index.iter_entries_prefix([('name', 'fin1'), ('ref', 'erence')])))
 
465
        self.assertEqual(set([(index, ('name', 'fin1'), 'data'),
 
466
            (index, ('name', 'fin2'), 'beta')]),
 
467
            set(index.iter_entries_prefix([('name', None)])))
 
468
 
 
469
    def test_iter_key_prefix_2_key_element_refs(self):
 
470
        index = self.make_index(1, key_elements=2, nodes=[
 
471
            (('name', 'fin1'), 'data', ([('ref', 'erence')], )),
 
472
            (('name', 'fin2'), 'beta', ([], )),
 
473
            (('ref', 'erence'), 'refdata', ([], ))])
 
474
        self.assertEqual(set([(index, ('name', 'fin1'), 'data', ((('ref', 'erence'),),)),
 
475
            (index, ('ref', 'erence'), 'refdata', ((), ))]),
 
476
            set(index.iter_entries_prefix([('name', 'fin1'), ('ref', 'erence')])))
 
477
        self.assertEqual(set([(index, ('name', 'fin1'), 'data', ((('ref', 'erence'),),)),
 
478
            (index, ('name', 'fin2'), 'beta', ((), ))]),
 
479
            set(index.iter_entries_prefix([('name', None)])))
 
480
 
 
481
    def test_key_count_empty(self):
 
482
        index = self.make_index()
 
483
        self.assertEqual(0, index.key_count())
 
484
 
 
485
    def test_key_count_one(self):
 
486
        index = self.make_index(nodes=[(('name', ), '', ())])
 
487
        self.assertEqual(1, index.key_count())
 
488
 
 
489
    def test_key_count_two(self):
 
490
        index = self.make_index(nodes=[
 
491
            (('name', ), '', ()), (('foo', ), '', ())])
 
492
        self.assertEqual(2, index.key_count())
 
493
 
 
494
    def test_validate_bad_index_errors(self):
 
495
        trans = self.get_transport()
 
496
        trans.put_bytes('name', "not an index\n")
 
497
        index = GraphIndex(trans, 'name')
 
498
        self.assertRaises(errors.BadIndexFormatSignature, index.validate)
 
499
 
 
500
    def test_validate_bad_node_refs(self):
 
501
        index = self.make_index(2)
 
502
        trans = self.get_transport()
 
503
        content = trans.get_bytes('index')
 
504
        # change the options line to end with a rather than a parseable number
 
505
        new_content = content[:-2] + 'a\n\n'
 
506
        trans.put_bytes('index', new_content)
 
507
        self.assertRaises(errors.BadIndexOptions, index.validate)
 
508
 
 
509
    def test_validate_missing_end_line_empty(self):
 
510
        index = self.make_index(2)
 
511
        trans = self.get_transport()
 
512
        content = trans.get_bytes('index')
 
513
        # truncate the last byte
 
514
        trans.put_bytes('index', content[:-1])
 
515
        self.assertRaises(errors.BadIndexData, index.validate)
 
516
 
 
517
    def test_validate_missing_end_line_nonempty(self):
 
518
        index = self.make_index(2, nodes=[(('key', ), '', ([], []))])
 
519
        trans = self.get_transport()
 
520
        content = trans.get_bytes('index')
 
521
        # truncate the last byte
 
522
        trans.put_bytes('index', content[:-1])
 
523
        self.assertRaises(errors.BadIndexData, index.validate)
 
524
 
 
525
    def test_validate_empty(self):
 
526
        index = self.make_index()
 
527
        index.validate()
 
528
 
 
529
    def test_validate_no_refs_content(self):
 
530
        index = self.make_index(nodes=[(('key', ), 'value', ())])
 
531
        index.validate()
 
532
 
 
533
 
 
534
class TestCombinedGraphIndex(TestCaseWithMemoryTransport):
 
535
 
 
536
    def make_index(self, name, ref_lists=0, key_elements=1, nodes=[]):
 
537
        builder = GraphIndexBuilder(ref_lists, key_elements=key_elements)
 
538
        for key, value, references in nodes:
 
539
            builder.add_node(key, value, references)
 
540
        stream = builder.finish()
 
541
        trans = self.get_transport()
 
542
        trans.put_file(name, stream)
 
543
        return GraphIndex(trans, name)
 
544
 
 
545
    def test_open_missing_index_no_error(self):
 
546
        trans = self.get_transport()
 
547
        index1 = GraphIndex(trans, 'missing')
 
548
        index = CombinedGraphIndex([index1])
 
549
 
 
550
    def test_add_index(self):
 
551
        index = CombinedGraphIndex([])
 
552
        index1 = self.make_index('name', 0, nodes=[(('key', ), '', ())])
 
553
        index.insert_index(0, index1)
 
554
        self.assertEqual([(index1, ('key', ), '')], list(index.iter_all_entries()))
 
555
 
 
556
    def test_iter_all_entries_empty(self):
 
557
        index = CombinedGraphIndex([])
 
558
        self.assertEqual([], list(index.iter_all_entries()))
 
559
 
 
560
    def test_iter_all_entries_children_empty(self):
 
561
        index1 = self.make_index('name')
 
562
        index = CombinedGraphIndex([index1])
 
563
        self.assertEqual([], list(index.iter_all_entries()))
 
564
 
 
565
    def test_iter_all_entries_simple(self):
 
566
        index1 = self.make_index('name', nodes=[(('name', ), 'data', ())])
 
567
        index = CombinedGraphIndex([index1])
 
568
        self.assertEqual([(index1, ('name', ), 'data')],
 
569
            list(index.iter_all_entries()))
 
570
 
 
571
    def test_iter_all_entries_two_indices(self):
 
572
        index1 = self.make_index('name1', nodes=[(('name', ), 'data', ())])
 
573
        index2 = self.make_index('name2', nodes=[(('2', ), '', ())])
 
574
        index = CombinedGraphIndex([index1, index2])
 
575
        self.assertEqual([(index1, ('name', ), 'data'),
 
576
            (index2, ('2', ), '')],
 
577
            list(index.iter_all_entries()))
 
578
 
 
579
    def test_iter_entries_two_indices_dup_key(self):
 
580
        index1 = self.make_index('name1', nodes=[(('name', ), 'data', ())])
 
581
        index2 = self.make_index('name2', nodes=[(('name', ), 'data', ())])
 
582
        index = CombinedGraphIndex([index1, index2])
 
583
        self.assertEqual([(index1, ('name', ), 'data')],
 
584
            list(index.iter_entries([('name', )])))
 
585
 
 
586
    def test_iter_all_entries_two_indices_dup_key(self):
 
587
        index1 = self.make_index('name1', nodes=[(('name', ), 'data', ())])
 
588
        index2 = self.make_index('name2', nodes=[(('name', ), 'data', ())])
 
589
        index = CombinedGraphIndex([index1, index2])
 
590
        self.assertEqual([(index1, ('name', ), 'data')],
 
591
            list(index.iter_all_entries()))
 
592
 
 
593
    def test_iter_key_prefix_2_key_element_refs(self):
 
594
        index1 = self.make_index('1', 1, key_elements=2, nodes=[
 
595
            (('name', 'fin1'), 'data', ([('ref', 'erence')], ))])
 
596
        index2 = self.make_index('2', 1, key_elements=2, nodes=[
 
597
            (('name', 'fin2'), 'beta', ([], )),
 
598
            (('ref', 'erence'), 'refdata', ([], ))])
 
599
        index = CombinedGraphIndex([index1, index2])
 
600
        self.assertEqual(set([(index1, ('name', 'fin1'), 'data', ((('ref', 'erence'),),)),
 
601
            (index2, ('ref', 'erence'), 'refdata', ((), ))]),
 
602
            set(index.iter_entries_prefix([('name', 'fin1'), ('ref', 'erence')])))
 
603
        self.assertEqual(set([(index1, ('name', 'fin1'), 'data', ((('ref', 'erence'),),)),
 
604
            (index2, ('name', 'fin2'), 'beta', ((), ))]),
 
605
            set(index.iter_entries_prefix([('name', None)])))
 
606
 
 
607
    def test_iter_nothing_empty(self):
 
608
        index = CombinedGraphIndex([])
 
609
        self.assertEqual([], list(index.iter_entries([])))
 
610
 
 
611
    def test_iter_nothing_children_empty(self):
 
612
        index1 = self.make_index('name')
 
613
        index = CombinedGraphIndex([index1])
 
614
        self.assertEqual([], list(index.iter_entries([])))
 
615
 
 
616
    def test_iter_all_keys(self):
 
617
        index1 = self.make_index('1', 1, nodes=[
 
618
            (('name', ), 'data', ([('ref', )], ))])
 
619
        index2 = self.make_index('2', 1, nodes=[
 
620
            (('ref', ), 'refdata', ((), ))])
 
621
        index = CombinedGraphIndex([index1, index2])
 
622
        self.assertEqual(set([(index1, ('name', ), 'data', ((('ref', ), ), )),
 
623
            (index2, ('ref', ), 'refdata', ((), ))]),
 
624
            set(index.iter_entries([('name', ), ('ref', )])))
 
625
 
 
626
    def test_iter_all_keys_dup_entry(self):
 
627
        index1 = self.make_index('1', 1, nodes=[
 
628
            (('name', ), 'data', ([('ref', )], )),
 
629
            (('ref', ), 'refdata', ([], ))])
 
630
        index2 = self.make_index('2', 1, nodes=[
 
631
            (('ref', ), 'refdata', ([], ))])
 
632
        index = CombinedGraphIndex([index1, index2])
 
633
        self.assertEqual(set([(index1, ('name', ), 'data', ((('ref',),),)),
 
634
            (index1, ('ref', ), 'refdata', ((), ))]),
 
635
            set(index.iter_entries([('name', ), ('ref', )])))
 
636
 
 
637
    def test_iter_missing_entry_empty(self):
 
638
        index = CombinedGraphIndex([])
 
639
        self.assertEqual([], list(index.iter_entries([('a', )])))
 
640
 
 
641
    def test_iter_missing_entry_one_index(self):
 
642
        index1 = self.make_index('1')
 
643
        index = CombinedGraphIndex([index1])
 
644
        self.assertEqual([], list(index.iter_entries([('a', )])))
 
645
 
 
646
    def test_iter_missing_entry_two_index(self):
 
647
        index1 = self.make_index('1')
 
648
        index2 = self.make_index('2')
 
649
        index = CombinedGraphIndex([index1, index2])
 
650
        self.assertEqual([], list(index.iter_entries([('a', )])))
 
651
 
 
652
    def test_iter_entry_present_one_index_only(self):
 
653
        index1 = self.make_index('1', nodes=[(('key', ), '', ())])
 
654
        index2 = self.make_index('2', nodes=[])
 
655
        index = CombinedGraphIndex([index1, index2])
 
656
        self.assertEqual([(index1, ('key', ), '')],
 
657
            list(index.iter_entries([('key', )])))
 
658
        # and in the other direction
 
659
        index = CombinedGraphIndex([index2, index1])
 
660
        self.assertEqual([(index1, ('key', ), '')],
 
661
            list(index.iter_entries([('key', )])))
 
662
 
 
663
    def test_key_count_empty(self):
 
664
        index1 = self.make_index('1', nodes=[])
 
665
        index2 = self.make_index('2', nodes=[])
 
666
        index = CombinedGraphIndex([index1, index2])
 
667
        self.assertEqual(0, index.key_count())
 
668
 
 
669
    def test_key_count_sums_index_keys(self):
 
670
        index1 = self.make_index('1', nodes=[
 
671
            (('1',), '', ()),
 
672
            (('2',), '', ())])
 
673
        index2 = self.make_index('2', nodes=[(('1',), '', ())])
 
674
        index = CombinedGraphIndex([index1, index2])
 
675
        self.assertEqual(3, index.key_count())
 
676
 
 
677
    def test_validate_bad_child_index_errors(self):
 
678
        trans = self.get_transport()
 
679
        trans.put_bytes('name', "not an index\n")
 
680
        index1 = GraphIndex(trans, 'name')
 
681
        index = CombinedGraphIndex([index1])
 
682
        self.assertRaises(errors.BadIndexFormatSignature, index.validate)
 
683
 
 
684
    def test_validate_empty(self):
 
685
        index = CombinedGraphIndex([])
 
686
        index.validate()
 
687
 
 
688
 
 
689
class TestInMemoryGraphIndex(TestCaseWithMemoryTransport):
 
690
 
 
691
    def make_index(self, ref_lists=0, key_elements=1, nodes=[]):
 
692
        result = InMemoryGraphIndex(ref_lists, key_elements=key_elements)
 
693
        result.add_nodes(nodes)
 
694
        return result
 
695
 
 
696
    def test_add_nodes_no_refs(self):
 
697
        index = self.make_index(0)
 
698
        index.add_nodes([(('name', ), 'data')])
 
699
        index.add_nodes([(('name2', ), ''), (('name3', ), '')])
 
700
        self.assertEqual(set([
 
701
            (index, ('name', ), 'data'),
 
702
            (index, ('name2', ), ''),
 
703
            (index, ('name3', ), ''),
 
704
            ]), set(index.iter_all_entries()))
 
705
 
 
706
    def test_add_nodes(self):
 
707
        index = self.make_index(1)
 
708
        index.add_nodes([(('name', ), 'data', ([],))])
 
709
        index.add_nodes([(('name2', ), '', ([],)), (('name3', ), '', ([('r', )],))])
 
710
        self.assertEqual(set([
 
711
            (index, ('name', ), 'data', ((),)),
 
712
            (index, ('name2', ), '', ((),)),
 
713
            (index, ('name3', ), '', ((('r', ), ), )),
 
714
            ]), set(index.iter_all_entries()))
 
715
 
 
716
    def test_iter_all_entries_empty(self):
 
717
        index = self.make_index()
 
718
        self.assertEqual([], list(index.iter_all_entries()))
 
719
 
 
720
    def test_iter_all_entries_simple(self):
 
721
        index = self.make_index(nodes=[(('name', ), 'data')])
 
722
        self.assertEqual([(index, ('name', ), 'data')],
 
723
            list(index.iter_all_entries()))
 
724
 
 
725
    def test_iter_all_entries_references(self):
 
726
        index = self.make_index(1, nodes=[
 
727
            (('name', ), 'data', ([('ref', )], )),
 
728
            (('ref', ), 'refdata', ([], ))])
 
729
        self.assertEqual(set([(index, ('name', ), 'data', ((('ref', ),),)),
 
730
            (index, ('ref', ), 'refdata', ((), ))]),
 
731
            set(index.iter_all_entries()))
 
732
 
 
733
    def test_iteration_absent_skipped(self):
 
734
        index = self.make_index(1, nodes=[
 
735
            (('name', ), 'data', ([('ref', )], ))])
 
736
        self.assertEqual(set([(index, ('name', ), 'data', ((('ref',),),))]),
 
737
            set(index.iter_all_entries()))
 
738
        self.assertEqual(set([(index, ('name', ), 'data', ((('ref',),),))]),
 
739
            set(index.iter_entries([('name', )])))
 
740
        self.assertEqual([], list(index.iter_entries([('ref', )])))
 
741
 
 
742
    def test_iter_all_keys(self):
 
743
        index = self.make_index(1, nodes=[
 
744
            (('name', ), 'data', ([('ref', )], )),
 
745
            (('ref', ), 'refdata', ([], ))])
 
746
        self.assertEqual(set([(index, ('name', ), 'data', ((('ref',),),)),
 
747
            (index, ('ref', ), 'refdata', ((), ))]),
 
748
            set(index.iter_entries([('name', ), ('ref', )])))
 
749
 
 
750
    def test_iter_key_prefix_1_key_element_no_refs(self):
 
751
        index = self.make_index( nodes=[
 
752
            (('name', ), 'data'),
 
753
            (('ref', ), 'refdata')])
 
754
        self.assertEqual(set([(index, ('name', ), 'data'),
 
755
            (index, ('ref', ), 'refdata')]),
 
756
            set(index.iter_entries_prefix([('name', ), ('ref', )])))
 
757
 
 
758
    def test_iter_key_prefix_1_key_element_refs(self):
 
759
        index = self.make_index(1, nodes=[
 
760
            (('name', ), 'data', ([('ref', )], )),
 
761
            (('ref', ), 'refdata', ([], ))])
 
762
        self.assertEqual(set([(index, ('name', ), 'data', ((('ref',),),)),
 
763
            (index, ('ref', ), 'refdata', ((), ))]),
 
764
            set(index.iter_entries_prefix([('name', ), ('ref', )])))
 
765
 
 
766
    def test_iter_key_prefix_2_key_element_no_refs(self):
 
767
        index = self.make_index(key_elements=2, nodes=[
 
768
            (('name', 'fin1'), 'data'),
 
769
            (('name', 'fin2'), 'beta'),
 
770
            (('ref', 'erence'), 'refdata')])
 
771
        self.assertEqual(set([(index, ('name', 'fin1'), 'data'),
 
772
            (index, ('ref', 'erence'), 'refdata')]),
 
773
            set(index.iter_entries_prefix([('name', 'fin1'), ('ref', 'erence')])))
 
774
        self.assertEqual(set([(index, ('name', 'fin1'), 'data'),
 
775
            (index, ('name', 'fin2'), 'beta')]),
 
776
            set(index.iter_entries_prefix([('name', None)])))
 
777
 
 
778
    def test_iter_key_prefix_2_key_element_refs(self):
 
779
        index = self.make_index(1, key_elements=2, nodes=[
 
780
            (('name', 'fin1'), 'data', ([('ref', 'erence')], )),
 
781
            (('name', 'fin2'), 'beta', ([], )),
 
782
            (('ref', 'erence'), 'refdata', ([], ))])
 
783
        self.assertEqual(set([(index, ('name', 'fin1'), 'data', ((('ref', 'erence'),),)),
 
784
            (index, ('ref', 'erence'), 'refdata', ((), ))]),
 
785
            set(index.iter_entries_prefix([('name', 'fin1'), ('ref', 'erence')])))
 
786
        self.assertEqual(set([(index, ('name', 'fin1'), 'data', ((('ref', 'erence'),),)),
 
787
            (index, ('name', 'fin2'), 'beta', ((), ))]),
 
788
            set(index.iter_entries_prefix([('name', None)])))
 
789
 
 
790
    def test_iter_nothing_empty(self):
 
791
        index = self.make_index()
 
792
        self.assertEqual([], list(index.iter_entries([])))
 
793
 
 
794
    def test_iter_missing_entry_empty(self):
 
795
        index = self.make_index()
 
796
        self.assertEqual([], list(index.iter_entries(['a'])))
 
797
 
 
798
    def test_key_count_empty(self):
 
799
        index = self.make_index()
 
800
        self.assertEqual(0, index.key_count())
 
801
 
 
802
    def test_key_count_one(self):
 
803
        index = self.make_index(nodes=[(('name', ), '')])
 
804
        self.assertEqual(1, index.key_count())
 
805
 
 
806
    def test_key_count_two(self):
 
807
        index = self.make_index(nodes=[(('name', ), ''), (('foo', ), '')])
 
808
        self.assertEqual(2, index.key_count())
 
809
 
 
810
    def test_validate_empty(self):
 
811
        index = self.make_index()
 
812
        index.validate()
 
813
 
 
814
    def test_validate_no_refs_content(self):
 
815
        index = self.make_index(nodes=[(('key', ), 'value')])
 
816
        index.validate()
 
817
 
 
818
 
 
819
class TestGraphIndexPrefixAdapter(TestCaseWithMemoryTransport):
 
820
 
 
821
    def make_index(self, ref_lists=1, key_elements=2, nodes=[], add_callback=False):
 
822
        result = InMemoryGraphIndex(ref_lists, key_elements=key_elements)
 
823
        result.add_nodes(nodes)
 
824
        if add_callback:
 
825
            add_nodes_callback = result.add_nodes
 
826
        else:
 
827
            add_nodes_callback = None
 
828
        adapter = GraphIndexPrefixAdapter(result, ('prefix', ), key_elements - 1,
 
829
            add_nodes_callback=add_nodes_callback)
 
830
        return result, adapter
 
831
 
 
832
    def test_add_node(self):
 
833
        index, adapter = self.make_index(add_callback=True)
 
834
        adapter.add_node(('key',), 'value', ((('ref',),),))
 
835
        self.assertEqual(set([(index, ('prefix', 'key'), 'value', ((('prefix', 'ref'),),))]),
 
836
            set(index.iter_all_entries()))
 
837
 
 
838
    def test_add_nodes(self):
 
839
        index, adapter = self.make_index(add_callback=True)
 
840
        adapter.add_nodes((
 
841
            (('key',), 'value', ((('ref',),),)),
 
842
            (('key2',), 'value2', ((),)),
 
843
            ))
 
844
        self.assertEqual(set([
 
845
            (index, ('prefix', 'key2'), 'value2', ((),)),
 
846
            (index, ('prefix', 'key'), 'value', ((('prefix', 'ref'),),))
 
847
            ]),
 
848
            set(index.iter_all_entries()))
 
849
 
 
850
    def test_construct(self):
 
851
        index = InMemoryGraphIndex()
 
852
        adapter = GraphIndexPrefixAdapter(index, ('prefix', ), 1)
 
853
 
 
854
    def test_construct_with_callback(self):
 
855
        index = InMemoryGraphIndex()
 
856
        adapter = GraphIndexPrefixAdapter(index, ('prefix', ), 1, index.add_nodes)
 
857
 
 
858
    def test_iter_all_entries_cross_prefix_map_errors(self):
 
859
        index, adapter = self.make_index(nodes=[
 
860
            (('prefix', 'key1'), 'data1', ((('prefixaltered', 'key2'),),))])
 
861
        self.assertRaises(errors.BadIndexData, list, adapter.iter_all_entries())
 
862
 
 
863
    def test_iter_all_entries(self):
 
864
        index, adapter = self.make_index(nodes=[
 
865
            (('notprefix', 'key1'), 'data', ((), )),
 
866
            (('prefix', 'key1'), 'data1', ((), )),
 
867
            (('prefix', 'key2'), 'data2', ((('prefix', 'key1'),),))])
 
868
        self.assertEqual(set([(index, ('key1', ), 'data1', ((),)),
 
869
            (index, ('key2', ), 'data2', ((('key1',),),))]),
 
870
            set(adapter.iter_all_entries()))
 
871
 
 
872
    def test_iter_entries(self):
 
873
        index, adapter = self.make_index(nodes=[
 
874
            (('notprefix', 'key1'), 'data', ((), )),
 
875
            (('prefix', 'key1'), 'data1', ((), )),
 
876
            (('prefix', 'key2'), 'data2', ((('prefix', 'key1'),),))])
 
877
        # ask for many - get all
 
878
        self.assertEqual(set([(index, ('key1', ), 'data1', ((),)),
 
879
            (index, ('key2', ), 'data2', ((('key1', ),),))]),
 
880
            set(adapter.iter_entries([('key1', ), ('key2', )])))
 
881
        # ask for one, get one
 
882
        self.assertEqual(set([(index, ('key1', ), 'data1', ((),))]),
 
883
            set(adapter.iter_entries([('key1', )])))
 
884
        # ask for missing, get none
 
885
        self.assertEqual(set(),
 
886
            set(adapter.iter_entries([('key3', )])))
 
887
 
 
888
    def test_iter_entries_prefix(self):
 
889
        index, adapter = self.make_index(key_elements=3, nodes=[
 
890
            (('notprefix', 'foo', 'key1'), 'data', ((), )),
 
891
            (('prefix', 'prefix2', 'key1'), 'data1', ((), )),
 
892
            (('prefix', 'prefix2', 'key2'), 'data2', ((('prefix', 'prefix2', 'key1'),),))])
 
893
        # ask for a prefix, get the results for just that prefix, adjusted.
 
894
        self.assertEqual(set([(index, ('prefix2', 'key1', ), 'data1', ((),)),
 
895
            (index, ('prefix2', 'key2', ), 'data2', ((('prefix2', 'key1', ),),))]),
 
896
            set(adapter.iter_entries_prefix([('prefix2', None)])))
 
897
 
 
898
    def test_key_count_no_matching_keys(self):
 
899
        index, adapter = self.make_index(nodes=[
 
900
            (('notprefix', 'key1'), 'data', ((), ))])
 
901
        self.assertEqual(0, adapter.key_count())
 
902
 
 
903
    def test_key_count_some_keys(self):
 
904
        index, adapter = self.make_index(nodes=[
 
905
            (('notprefix', 'key1'), 'data', ((), )),
 
906
            (('prefix', 'key1'), 'data1', ((), )),
 
907
            (('prefix', 'key2'), 'data2', ((('prefix', 'key1'),),))])
 
908
        self.assertEqual(2, adapter.key_count())
 
909
 
 
910
    def test_validate(self):
 
911
        index, adapter = self.make_index()
 
912
        calls = []
 
913
        def validate():
 
914
            calls.append('called')
 
915
        index.validate = validate
 
916
        adapter.validate()
 
917
        self.assertEqual(['called'], calls)