17
17
"""Tests for indices."""
24
from ..sixish import int2byte
30
class ErrorTests(tests.TestCase):
32
def test_bad_index_format_signature(self):
33
error = _mod_index.BadIndexFormatSignature("foo", "bar")
34
self.assertEqual("foo is not an index of type bar.",
37
def test_bad_index_data(self):
38
error = _mod_index.BadIndexData("foo")
39
self.assertEqual("Error in data for index foo.",
42
def test_bad_index_duplicate_key(self):
43
error = _mod_index.BadIndexDuplicateKey("foo", "bar")
44
self.assertEqual("The key 'foo' is already in index 'bar'.",
47
def test_bad_index_key(self):
48
error = _mod_index.BadIndexKey("foo")
49
self.assertEqual("The key 'foo' is not a valid key.",
52
def test_bad_index_options(self):
53
error = _mod_index.BadIndexOptions("foo")
54
self.assertEqual("Could not parse options for index foo.",
57
def test_bad_index_value(self):
58
error = _mod_index.BadIndexValue("foo")
59
self.assertEqual("The value 'foo' is not a valid value.",
63
class TestGraphIndexBuilder(tests.TestCaseWithMemoryTransport):
19
from bzrlib import errors
20
from bzrlib.index import *
21
from bzrlib.tests import TestCaseWithMemoryTransport
22
from bzrlib.transport import get_transport
25
class TestGraphIndexBuilder(TestCaseWithMemoryTransport):
65
27
def test_build_index_empty(self):
66
builder = _mod_index.GraphIndexBuilder()
28
builder = GraphIndexBuilder()
67
29
stream = builder.finish()
68
30
contents = stream.read()
70
b"Bazaar Graph Index 1\nnode_ref_lists=0\nkey_elements=1\nlen=0\n\n",
32
"Bazaar Graph Index 1\nnode_ref_lists=0\nkey_elements=1\nlen=0\n\n",
73
35
def test_build_index_empty_two_element_keys(self):
74
builder = _mod_index.GraphIndexBuilder(key_elements=2)
36
builder = GraphIndexBuilder(key_elements=2)
75
37
stream = builder.finish()
76
38
contents = stream.read()
78
b"Bazaar Graph Index 1\nnode_ref_lists=0\nkey_elements=2\nlen=0\n\n",
40
"Bazaar Graph Index 1\nnode_ref_lists=0\nkey_elements=2\nlen=0\n\n",
81
43
def test_build_index_one_reference_list_empty(self):
82
builder = _mod_index.GraphIndexBuilder(reference_lists=1)
44
builder = GraphIndexBuilder(reference_lists=1)
83
45
stream = builder.finish()
84
46
contents = stream.read()
86
b"Bazaar Graph Index 1\nnode_ref_lists=1\nkey_elements=1\nlen=0\n\n",
48
"Bazaar Graph Index 1\nnode_ref_lists=1\nkey_elements=1\nlen=0\n\n",
89
51
def test_build_index_two_reference_list_empty(self):
90
builder = _mod_index.GraphIndexBuilder(reference_lists=2)
52
builder = GraphIndexBuilder(reference_lists=2)
91
53
stream = builder.finish()
92
54
contents = stream.read()
94
b"Bazaar Graph Index 1\nnode_ref_lists=2\nkey_elements=1\nlen=0\n\n",
56
"Bazaar Graph Index 1\nnode_ref_lists=2\nkey_elements=1\nlen=0\n\n",
97
59
def test_build_index_one_node_no_refs(self):
98
builder = _mod_index.GraphIndexBuilder()
99
builder.add_node((b'akey', ), b'data')
60
builder = GraphIndexBuilder()
61
builder.add_node(('akey', ), 'data')
100
62
stream = builder.finish()
101
63
contents = stream.read()
103
b"Bazaar Graph Index 1\nnode_ref_lists=0\nkey_elements=1\nlen=1\n"
104
b"akey\x00\x00\x00data\n\n", contents)
65
"Bazaar Graph Index 1\nnode_ref_lists=0\nkey_elements=1\nlen=1\n"
66
"akey\x00\x00\x00data\n\n", contents)
106
68
def test_build_index_one_node_no_refs_accepts_empty_reflist(self):
107
builder = _mod_index.GraphIndexBuilder()
108
builder.add_node((b'akey', ), b'data', ())
69
builder = GraphIndexBuilder()
70
builder.add_node(('akey', ), 'data', ())
109
71
stream = builder.finish()
110
72
contents = stream.read()
112
b"Bazaar Graph Index 1\nnode_ref_lists=0\nkey_elements=1\nlen=1\n"
113
b"akey\x00\x00\x00data\n\n", contents)
74
"Bazaar Graph Index 1\nnode_ref_lists=0\nkey_elements=1\nlen=1\n"
75
"akey\x00\x00\x00data\n\n", contents)
115
77
def test_build_index_one_node_2_element_keys(self):
116
78
# multipart keys are separated by \x00 - because they are fixed length,
117
79
# not variable this does not cause any issues, and seems clearer to the
119
builder = _mod_index.GraphIndexBuilder(key_elements=2)
120
builder.add_node((b'akey', b'secondpart'), b'data')
81
builder = GraphIndexBuilder(key_elements=2)
82
builder.add_node(('akey', 'secondpart'), 'data')
121
83
stream = builder.finish()
122
84
contents = stream.read()
124
b"Bazaar Graph Index 1\nnode_ref_lists=0\nkey_elements=2\nlen=1\n"
125
b"akey\x00secondpart\x00\x00\x00data\n\n", contents)
86
"Bazaar Graph Index 1\nnode_ref_lists=0\nkey_elements=2\nlen=1\n"
87
"akey\x00secondpart\x00\x00\x00data\n\n", contents)
127
89
def test_add_node_empty_value(self):
128
builder = _mod_index.GraphIndexBuilder()
129
builder.add_node((b'akey', ), b'')
90
builder = GraphIndexBuilder()
91
builder.add_node(('akey', ), '')
130
92
stream = builder.finish()
131
93
contents = stream.read()
133
b"Bazaar Graph Index 1\nnode_ref_lists=0\nkey_elements=1\nlen=1\n"
134
b"akey\x00\x00\x00\n\n", contents)
95
"Bazaar Graph Index 1\nnode_ref_lists=0\nkey_elements=1\nlen=1\n"
96
"akey\x00\x00\x00\n\n", contents)
136
98
def test_build_index_nodes_sorted(self):
137
99
# the highest sorted node comes first.
138
builder = _mod_index.GraphIndexBuilder()
100
builder = GraphIndexBuilder()
139
101
# use three to have a good chance of glitching dictionary hash
140
102
# lookups etc. Insert in randomish order that is not correct
141
103
# and not the reverse of the correct order.
142
builder.add_node((b'2002', ), b'data')
143
builder.add_node((b'2000', ), b'data')
144
builder.add_node((b'2001', ), b'data')
104
builder.add_node(('2002', ), 'data')
105
builder.add_node(('2000', ), 'data')
106
builder.add_node(('2001', ), 'data')
145
107
stream = builder.finish()
146
108
contents = stream.read()
147
109
self.assertEqual(
148
b"Bazaar Graph Index 1\nnode_ref_lists=0\nkey_elements=1\nlen=3\n"
149
b"2000\x00\x00\x00data\n"
150
b"2001\x00\x00\x00data\n"
151
b"2002\x00\x00\x00data\n"
110
"Bazaar Graph Index 1\nnode_ref_lists=0\nkey_elements=1\nlen=3\n"
111
"2000\x00\x00\x00data\n"
112
"2001\x00\x00\x00data\n"
113
"2002\x00\x00\x00data\n"
154
116
def test_build_index_2_element_key_nodes_sorted(self):
155
117
# multiple element keys are sorted first-key, second-key.
156
builder = _mod_index.GraphIndexBuilder(key_elements=2)
118
builder = GraphIndexBuilder(key_elements=2)
157
119
# use three values of each key element, to have a good chance of
158
120
# glitching dictionary hash lookups etc. Insert in randomish order that
159
121
# is not correct and not the reverse of the correct order.
160
builder.add_node((b'2002', b'2002'), b'data')
161
builder.add_node((b'2002', b'2000'), b'data')
162
builder.add_node((b'2002', b'2001'), b'data')
163
builder.add_node((b'2000', b'2002'), b'data')
164
builder.add_node((b'2000', b'2000'), b'data')
165
builder.add_node((b'2000', b'2001'), b'data')
166
builder.add_node((b'2001', b'2002'), b'data')
167
builder.add_node((b'2001', b'2000'), b'data')
168
builder.add_node((b'2001', b'2001'), b'data')
122
builder.add_node(('2002', '2002'), 'data')
123
builder.add_node(('2002', '2000'), 'data')
124
builder.add_node(('2002', '2001'), 'data')
125
builder.add_node(('2000', '2002'), 'data')
126
builder.add_node(('2000', '2000'), 'data')
127
builder.add_node(('2000', '2001'), 'data')
128
builder.add_node(('2001', '2002'), 'data')
129
builder.add_node(('2001', '2000'), 'data')
130
builder.add_node(('2001', '2001'), 'data')
169
131
stream = builder.finish()
170
132
contents = stream.read()
171
133
self.assertEqual(
172
b"Bazaar Graph Index 1\nnode_ref_lists=0\nkey_elements=2\nlen=9\n"
173
b"2000\x002000\x00\x00\x00data\n"
174
b"2000\x002001\x00\x00\x00data\n"
175
b"2000\x002002\x00\x00\x00data\n"
176
b"2001\x002000\x00\x00\x00data\n"
177
b"2001\x002001\x00\x00\x00data\n"
178
b"2001\x002002\x00\x00\x00data\n"
179
b"2002\x002000\x00\x00\x00data\n"
180
b"2002\x002001\x00\x00\x00data\n"
181
b"2002\x002002\x00\x00\x00data\n"
134
"Bazaar Graph Index 1\nnode_ref_lists=0\nkey_elements=2\nlen=9\n"
135
"2000\x002000\x00\x00\x00data\n"
136
"2000\x002001\x00\x00\x00data\n"
137
"2000\x002002\x00\x00\x00data\n"
138
"2001\x002000\x00\x00\x00data\n"
139
"2001\x002001\x00\x00\x00data\n"
140
"2001\x002002\x00\x00\x00data\n"
141
"2002\x002000\x00\x00\x00data\n"
142
"2002\x002001\x00\x00\x00data\n"
143
"2002\x002002\x00\x00\x00data\n"
184
146
def test_build_index_reference_lists_are_included_one(self):
185
builder = _mod_index.GraphIndexBuilder(reference_lists=1)
186
builder.add_node((b'key', ), b'data', ([], ))
147
builder = GraphIndexBuilder(reference_lists=1)
148
builder.add_node(('key', ), 'data', ([], ))
187
149
stream = builder.finish()
188
150
contents = stream.read()
189
151
self.assertEqual(
190
b"Bazaar Graph Index 1\nnode_ref_lists=1\nkey_elements=1\nlen=1\n"
191
b"key\x00\x00\x00data\n"
152
"Bazaar Graph Index 1\nnode_ref_lists=1\nkey_elements=1\nlen=1\n"
153
"key\x00\x00\x00data\n"
194
156
def test_build_index_reference_lists_with_2_element_keys(self):
195
builder = _mod_index.GraphIndexBuilder(
196
reference_lists=1, key_elements=2)
197
builder.add_node((b'key', b'key2'), b'data', ([], ))
157
builder = GraphIndexBuilder(reference_lists=1, key_elements=2)
158
builder.add_node(('key', 'key2'), 'data', ([], ))
198
159
stream = builder.finish()
199
160
contents = stream.read()
200
161
self.assertEqual(
201
b"Bazaar Graph Index 1\nnode_ref_lists=1\nkey_elements=2\nlen=1\n"
202
b"key\x00key2\x00\x00\x00data\n"
162
"Bazaar Graph Index 1\nnode_ref_lists=1\nkey_elements=2\nlen=1\n"
163
"key\x00key2\x00\x00\x00data\n"
205
166
def test_build_index_reference_lists_are_included_two(self):
206
builder = _mod_index.GraphIndexBuilder(reference_lists=2)
207
builder.add_node((b'key', ), b'data', ([], []))
167
builder = GraphIndexBuilder(reference_lists=2)
168
builder.add_node(('key', ), 'data', ([], []))
208
169
stream = builder.finish()
209
170
contents = stream.read()
210
171
self.assertEqual(
211
b"Bazaar Graph Index 1\nnode_ref_lists=2\nkey_elements=1\nlen=1\n"
212
b"key\x00\x00\t\x00data\n"
172
"Bazaar Graph Index 1\nnode_ref_lists=2\nkey_elements=1\nlen=1\n"
173
"key\x00\x00\t\x00data\n"
215
176
def test_clear_cache(self):
216
builder = _mod_index.GraphIndexBuilder(reference_lists=2)
177
builder = GraphIndexBuilder(reference_lists=2)
217
178
# This is a no-op, but the api should exist
218
179
builder.clear_cache()
220
181
def test_node_references_are_byte_offsets(self):
221
builder = _mod_index.GraphIndexBuilder(reference_lists=1)
222
builder.add_node((b'reference', ), b'data', ([], ))
223
builder.add_node((b'key', ), b'data', ([(b'reference', )], ))
182
builder = GraphIndexBuilder(reference_lists=1)
183
builder.add_node(('reference', ), 'data', ([], ))
184
builder.add_node(('key', ), 'data', ([('reference', )], ))
224
185
stream = builder.finish()
225
186
contents = stream.read()
226
187
self.assertEqual(
227
b"Bazaar Graph Index 1\nnode_ref_lists=1\nkey_elements=1\nlen=2\n"
228
b"key\x00\x0072\x00data\n"
229
b"reference\x00\x00\x00data\n"
188
"Bazaar Graph Index 1\nnode_ref_lists=1\nkey_elements=1\nlen=2\n"
189
"key\x00\x0072\x00data\n"
190
"reference\x00\x00\x00data\n"
232
193
def test_node_references_are_cr_delimited(self):
233
builder = _mod_index.GraphIndexBuilder(reference_lists=1)
234
builder.add_node((b'reference', ), b'data', ([], ))
235
builder.add_node((b'reference2', ), b'data', ([], ))
236
builder.add_node((b'key', ), b'data',
237
([(b'reference', ), (b'reference2', )], ))
194
builder = GraphIndexBuilder(reference_lists=1)
195
builder.add_node(('reference', ), 'data', ([], ))
196
builder.add_node(('reference2', ), 'data', ([], ))
197
builder.add_node(('key', ), 'data', ([('reference', ), ('reference2', )], ))
238
198
stream = builder.finish()
239
199
contents = stream.read()
240
200
self.assertEqual(
241
b"Bazaar Graph Index 1\nnode_ref_lists=1\nkey_elements=1\nlen=3\n"
242
b"key\x00\x00077\r094\x00data\n"
243
b"reference\x00\x00\x00data\n"
244
b"reference2\x00\x00\x00data\n"
201
"Bazaar Graph Index 1\nnode_ref_lists=1\nkey_elements=1\nlen=3\n"
202
"key\x00\x00077\r094\x00data\n"
203
"reference\x00\x00\x00data\n"
204
"reference2\x00\x00\x00data\n"
247
207
def test_multiple_reference_lists_are_tab_delimited(self):
248
builder = _mod_index.GraphIndexBuilder(reference_lists=2)
249
builder.add_node((b'keference', ), b'data', ([], []))
250
builder.add_node((b'rey', ), b'data',
251
([(b'keference', )], [(b'keference', )]))
208
builder = GraphIndexBuilder(reference_lists=2)
209
builder.add_node(('keference', ), 'data', ([], []))
210
builder.add_node(('rey', ), 'data', ([('keference', )], [('keference', )]))
252
211
stream = builder.finish()
253
212
contents = stream.read()
254
213
self.assertEqual(
255
b"Bazaar Graph Index 1\nnode_ref_lists=2\nkey_elements=1\nlen=2\n"
256
b"keference\x00\x00\t\x00data\n"
257
b"rey\x00\x0059\t59\x00data\n"
214
"Bazaar Graph Index 1\nnode_ref_lists=2\nkey_elements=1\nlen=2\n"
215
"keference\x00\x00\t\x00data\n"
216
"rey\x00\x0059\t59\x00data\n"
260
219
def test_add_node_referencing_missing_key_makes_absent(self):
261
builder = _mod_index.GraphIndexBuilder(reference_lists=1)
262
builder.add_node((b'rey', ), b'data',
263
([(b'beference', ), (b'aeference2', )], ))
220
builder = GraphIndexBuilder(reference_lists=1)
221
builder.add_node(('rey', ), 'data', ([('beference', ), ('aeference2', )], ))
264
222
stream = builder.finish()
265
223
contents = stream.read()
266
224
self.assertEqual(
267
b"Bazaar Graph Index 1\nnode_ref_lists=1\nkey_elements=1\nlen=1\n"
268
b"aeference2\x00a\x00\x00\n"
269
b"beference\x00a\x00\x00\n"
270
b"rey\x00\x00074\r059\x00data\n"
225
"Bazaar Graph Index 1\nnode_ref_lists=1\nkey_elements=1\nlen=1\n"
226
"aeference2\x00a\x00\x00\n"
227
"beference\x00a\x00\x00\n"
228
"rey\x00\x00074\r059\x00data\n"
273
231
def test_node_references_three_digits(self):
274
232
# test the node digit expands as needed.
275
builder = _mod_index.GraphIndexBuilder(reference_lists=1)
276
references = [((b"%d" % val), ) for val in range(8, -1, -1)]
277
builder.add_node((b'2-key', ), b'', (references, ))
233
builder = GraphIndexBuilder(reference_lists=1)
234
references = [(str(val), ) for val in reversed(range(9))]
235
builder.add_node(('2-key', ), '', (references, ))
278
236
stream = builder.finish()
279
237
contents = stream.read()
280
238
self.assertEqualDiff(
281
b"Bazaar Graph Index 1\nnode_ref_lists=1\nkey_elements=1\nlen=1\n"
285
b"2-key\x00\x00151\r145\r139\r133\r127\r121\r071\r065\r059\x00\n"
239
"Bazaar Graph Index 1\nnode_ref_lists=1\nkey_elements=1\nlen=1\n"
243
"2-key\x00\x00151\r145\r139\r133\r127\r121\r071\r065\r059\x00\n"
294
252
def test_absent_has_no_reference_overhead(self):
295
253
# the offsets after an absent record should be correct when there are
296
254
# >1 reference lists.
297
builder = _mod_index.GraphIndexBuilder(reference_lists=2)
298
builder.add_node((b'parent', ), b'', ([(b'aail', ), (b'zther', )], []))
255
builder = GraphIndexBuilder(reference_lists=2)
256
builder.add_node(('parent', ), '', ([('aail', ), ('zther', )], []))
299
257
stream = builder.finish()
300
258
contents = stream.read()
301
259
self.assertEqual(
302
b"Bazaar Graph Index 1\nnode_ref_lists=2\nkey_elements=1\nlen=1\n"
303
b"aail\x00a\x00\x00\n"
304
b"parent\x00\x0059\r84\t\x00\n"
305
b"zther\x00a\x00\x00\n"
260
"Bazaar Graph Index 1\nnode_ref_lists=2\nkey_elements=1\nlen=1\n"
261
"aail\x00a\x00\x00\n"
262
"parent\x00\x0059\r84\t\x00\n"
263
"zther\x00a\x00\x00\n"
308
266
def test_add_node_bad_key(self):
309
builder = _mod_index.GraphIndexBuilder()
310
for bad_char in bytearray(b'\t\n\x0b\x0c\r\x00 '):
311
self.assertRaises(_mod_index.BadIndexKey, builder.add_node,
312
(b'a%skey' % int2byte(bad_char), ), b'data')
313
self.assertRaises(_mod_index.BadIndexKey, builder.add_node,
315
self.assertRaises(_mod_index.BadIndexKey, builder.add_node,
316
b'not-a-tuple', b'data')
267
builder = GraphIndexBuilder()
268
for bad_char in '\t\n\x0b\x0c\r\x00 ':
269
self.assertRaises(errors.BadIndexKey, builder.add_node,
270
('a%skey' % bad_char, ), 'data')
271
self.assertRaises(errors.BadIndexKey, builder.add_node,
273
self.assertRaises(errors.BadIndexKey, builder.add_node,
274
'not-a-tuple', 'data')
317
275
# not enough length
318
self.assertRaises(_mod_index.BadIndexKey, builder.add_node,
276
self.assertRaises(errors.BadIndexKey, builder.add_node,
321
self.assertRaises(_mod_index.BadIndexKey, builder.add_node,
322
(b'primary', b'secondary'), b'data')
279
self.assertRaises(errors.BadIndexKey, builder.add_node,
280
('primary', 'secondary'), 'data')
323
281
# secondary key elements get checked too:
324
builder = _mod_index.GraphIndexBuilder(key_elements=2)
325
for bad_char in bytearray(b'\t\n\x0b\x0c\r\x00 '):
326
self.assertRaises(_mod_index.BadIndexKey, builder.add_node,
327
(b'prefix', b'a%skey' % int2byte(bad_char)), b'data')
282
builder = GraphIndexBuilder(key_elements=2)
283
for bad_char in '\t\n\x0b\x0c\r\x00 ':
284
self.assertRaises(errors.BadIndexKey, builder.add_node,
285
('prefix', 'a%skey' % bad_char), 'data')
329
287
def test_add_node_bad_data(self):
330
builder = _mod_index.GraphIndexBuilder()
331
self.assertRaises(_mod_index.BadIndexValue, builder.add_node, (b'akey', ),
333
self.assertRaises(_mod_index.BadIndexValue, builder.add_node, (b'akey', ),
288
builder = GraphIndexBuilder()
289
self.assertRaises(errors.BadIndexValue, builder.add_node, ('akey', ),
291
self.assertRaises(errors.BadIndexValue, builder.add_node, ('akey', ),
336
294
def test_add_node_bad_mismatched_ref_lists_length(self):
337
builder = _mod_index.GraphIndexBuilder()
338
self.assertRaises(_mod_index.BadIndexValue, builder.add_node, (b'akey', ),
340
builder = _mod_index.GraphIndexBuilder(reference_lists=1)
341
self.assertRaises(_mod_index.BadIndexValue, builder.add_node, (b'akey', ),
343
self.assertRaises(_mod_index.BadIndexValue, builder.add_node, (b'akey', ),
345
self.assertRaises(_mod_index.BadIndexValue, builder.add_node, (b'akey', ),
346
b'data aa', ([], []))
347
builder = _mod_index.GraphIndexBuilder(reference_lists=2)
348
self.assertRaises(_mod_index.BadIndexValue, builder.add_node, (b'akey', ),
350
self.assertRaises(_mod_index.BadIndexValue, builder.add_node, (b'akey', ),
352
self.assertRaises(_mod_index.BadIndexValue, builder.add_node, (b'akey', ),
353
b'data aa', ([], [], []))
295
builder = GraphIndexBuilder()
296
self.assertRaises(errors.BadIndexValue, builder.add_node, ('akey', ),
298
builder = GraphIndexBuilder(reference_lists=1)
299
self.assertRaises(errors.BadIndexValue, builder.add_node, ('akey', ),
301
self.assertRaises(errors.BadIndexValue, builder.add_node, ('akey', ),
303
self.assertRaises(errors.BadIndexValue, builder.add_node, ('akey', ),
305
builder = GraphIndexBuilder(reference_lists=2)
306
self.assertRaises(errors.BadIndexValue, builder.add_node, ('akey', ),
308
self.assertRaises(errors.BadIndexValue, builder.add_node, ('akey', ),
310
self.assertRaises(errors.BadIndexValue, builder.add_node, ('akey', ),
311
'data aa', ([], [], []))
355
313
def test_add_node_bad_key_in_reference_lists(self):
356
314
# first list, first key - trivial
357
builder = _mod_index.GraphIndexBuilder(reference_lists=1)
358
self.assertRaises(_mod_index.BadIndexKey, builder.add_node, (b'akey', ),
359
b'data aa', ([(b'a key', )], ))
315
builder = GraphIndexBuilder(reference_lists=1)
316
self.assertRaises(errors.BadIndexKey, builder.add_node, ('akey', ),
317
'data aa', ([('a key', )], ))
360
318
# references keys must be tuples too
361
self.assertRaises(_mod_index.BadIndexKey, builder.add_node, (b'akey', ),
362
b'data aa', (['not-a-tuple'], ))
319
self.assertRaises(errors.BadIndexKey, builder.add_node, ('akey', ),
320
'data aa', (['not-a-tuple'], ))
363
321
# not enough length
364
self.assertRaises(_mod_index.BadIndexKey, builder.add_node, (b'akey', ),
365
b'data aa', ([()], ))
322
self.assertRaises(errors.BadIndexKey, builder.add_node, ('akey', ),
367
self.assertRaises(_mod_index.BadIndexKey, builder.add_node, (b'akey', ),
368
b'data aa', ([(b'primary', b'secondary')], ))
325
self.assertRaises(errors.BadIndexKey, builder.add_node, ('akey', ),
326
'data aa', ([('primary', 'secondary')], ))
369
327
# need to check more than the first key in the list
370
self.assertRaises(_mod_index.BadIndexKey, builder.add_node, (b'akey', ),
371
b'data aa', ([(b'agoodkey', ), (b'that is a bad key', )], ))
328
self.assertRaises(errors.BadIndexKey, builder.add_node, ('akey', ),
329
'data aa', ([('agoodkey', ), ('that is a bad key', )], ))
372
330
# and if there is more than one list it should be getting checked
374
builder = _mod_index.GraphIndexBuilder(reference_lists=2)
375
self.assertRaises(_mod_index.BadIndexKey, builder.add_node, (b'akey', ),
376
b'data aa', ([], ['a bad key']))
332
builder = GraphIndexBuilder(reference_lists=2)
333
self.assertRaises(errors.BadIndexKey, builder.add_node, ('akey', ),
334
'data aa', ([], ['a bad key']))
378
336
def test_add_duplicate_key(self):
379
builder = _mod_index.GraphIndexBuilder()
380
builder.add_node((b'key', ), b'data')
381
self.assertRaises(_mod_index.BadIndexDuplicateKey,
382
builder.add_node, (b'key', ), b'data')
337
builder = GraphIndexBuilder()
338
builder.add_node(('key', ), 'data')
339
self.assertRaises(errors.BadIndexDuplicateKey, builder.add_node, ('key', ),
384
342
def test_add_duplicate_key_2_elements(self):
385
builder = _mod_index.GraphIndexBuilder(key_elements=2)
386
builder.add_node((b'key', b'key'), b'data')
387
self.assertRaises(_mod_index.BadIndexDuplicateKey, builder.add_node,
388
(b'key', b'key'), b'data')
343
builder = GraphIndexBuilder(key_elements=2)
344
builder.add_node(('key', 'key'), 'data')
345
self.assertRaises(errors.BadIndexDuplicateKey, builder.add_node,
346
('key', 'key'), 'data')
390
348
def test_add_key_after_referencing_key(self):
391
builder = _mod_index.GraphIndexBuilder(reference_lists=1)
392
builder.add_node((b'key', ), b'data', ([(b'reference', )], ))
393
builder.add_node((b'reference', ), b'data', ([],))
349
builder = GraphIndexBuilder(reference_lists=1)
350
builder.add_node(('key', ), 'data', ([('reference', )], ))
351
builder.add_node(('reference', ), 'data', ([],))
395
353
def test_add_key_after_referencing_key_2_elements(self):
396
builder = _mod_index.GraphIndexBuilder(
397
reference_lists=1, key_elements=2)
398
builder.add_node((b'k', b'ey'), b'data',
399
([(b'reference', b'tokey')], ))
400
builder.add_node((b'reference', b'tokey'), b'data', ([],))
354
builder = GraphIndexBuilder(reference_lists=1, key_elements=2)
355
builder.add_node(('k', 'ey'), 'data', ([('reference', 'tokey')], ))
356
builder.add_node(('reference', 'tokey'), 'data', ([],))
402
358
def test_set_optimize(self):
403
builder = _mod_index.GraphIndexBuilder(
404
reference_lists=1, key_elements=2)
359
builder = GraphIndexBuilder(reference_lists=1, key_elements=2)
405
360
builder.set_optimize(for_size=True)
406
361
self.assertTrue(builder._optimize_for_size)
407
362
builder.set_optimize(for_size=False)
408
363
self.assertFalse(builder._optimize_for_size)
411
class TestGraphIndex(tests.TestCaseWithMemoryTransport):
366
class TestGraphIndex(TestCaseWithMemoryTransport):
413
368
def make_key(self, number):
414
return ((b'%d' % number) + b'X' * 100,)
369
return (str(number) + 'X'*100,)
416
371
def make_value(self, number):
417
return (b'%d' % number) + b'Y' * 100
372
return str(number) + 'Y'*100
419
374
def make_nodes(self, count=64):
420
375
# generate a big enough index that we only read some of it on a typical
421
376
# bisection lookup.
423
378
for counter in range(count):
425
(self.make_key(counter), self.make_value(counter), ()))
379
nodes.append((self.make_key(counter), self.make_value(counter), ()))
428
382
def make_index(self, ref_lists=0, key_elements=1, nodes=[]):
429
builder = _mod_index.GraphIndexBuilder(
430
ref_lists, key_elements=key_elements)
383
builder = GraphIndexBuilder(ref_lists, key_elements=key_elements)
431
384
for key, value, references in nodes:
432
385
builder.add_node(key, value, references)
433
386
stream = builder.finish()
434
trans = transport.get_transport_from_url('trace+' + self.get_url())
387
trans = get_transport('trace+' + self.get_url())
435
388
size = trans.put_file('index', stream)
436
return _mod_index.GraphIndex(trans, 'index', size)
389
return GraphIndex(trans, 'index', size)
438
391
def make_index_with_offset(self, ref_lists=0, key_elements=1, nodes=[],
440
builder = _mod_index.GraphIndexBuilder(
441
ref_lists, key_elements=key_elements)
393
builder = GraphIndexBuilder(ref_lists, key_elements=key_elements)
442
394
for key, value, references in nodes:
443
395
builder.add_node(key, value, references)
444
396
content = builder.finish().read()
445
397
size = len(content)
446
398
trans = self.get_transport()
447
trans.put_bytes('index', (b' ' * offset) + content)
448
return _mod_index.GraphIndex(trans, 'index', size, offset=offset)
399
trans.put_bytes('index', (' '*offset) + content)
400
return GraphIndex(trans, 'index', size, offset=offset)
450
402
def test_clear_cache(self):
451
403
index = self.make_index()
830
782
def test_iter_entries_references_resolved(self):
831
783
index = self.make_index(1, nodes=[
832
((b'name', ), b'data', ([(b'ref', ), (b'ref', )], )),
833
((b'ref', ), b'refdata', ([], ))])
834
self.assertEqual({(index, (b'name', ), b'data', (((b'ref',), (b'ref',)),)),
835
(index, (b'ref', ), b'refdata', ((), ))},
836
set(index.iter_entries([(b'name',), (b'ref',)])))
784
(('name', ), 'data', ([('ref', ), ('ref', )], )),
785
(('ref', ), 'refdata', ([], ))])
786
self.assertEqual(set([(index, ('name', ), 'data', ((('ref',),('ref',)),)),
787
(index, ('ref', ), 'refdata', ((), ))]),
788
set(index.iter_entries([('name',), ('ref',)])))
838
790
def test_iter_entries_references_2_refs_resolved(self):
839
791
index = self.make_index(2, nodes=[
840
((b'name', ), b'data', ([(b'ref', )], [(b'ref', )])),
841
((b'ref', ), b'refdata', ([], []))])
842
self.assertEqual({(index, (b'name', ), b'data', (((b'ref',),), ((b'ref',),))),
843
(index, (b'ref', ), b'refdata', ((), ()))},
844
set(index.iter_entries([(b'name',), (b'ref',)])))
792
(('name', ), 'data', ([('ref', )], [('ref', )])),
793
(('ref', ), 'refdata', ([], []))])
794
self.assertEqual(set([(index, ('name', ), 'data', ((('ref',),), (('ref',),))),
795
(index, ('ref', ), 'refdata', ((), ()))]),
796
set(index.iter_entries([('name',), ('ref',)])))
846
798
def test_iteration_absent_skipped(self):
847
799
index = self.make_index(1, nodes=[
848
((b'name', ), b'data', ([(b'ref', )], ))])
849
self.assertEqual({(index, (b'name', ), b'data', (((b'ref',),),))},
850
set(index.iter_all_entries()))
851
self.assertEqual({(index, (b'name', ), b'data', (((b'ref',),),))},
852
set(index.iter_entries([(b'name', )])))
853
self.assertEqual([], list(index.iter_entries([(b'ref', )])))
800
(('name', ), 'data', ([('ref', )], ))])
801
self.assertEqual(set([(index, ('name', ), 'data', ((('ref',),),))]),
802
set(index.iter_all_entries()))
803
self.assertEqual(set([(index, ('name', ), 'data', ((('ref',),),))]),
804
set(index.iter_entries([('name', )])))
805
self.assertEqual([], list(index.iter_entries([('ref', )])))
855
807
def test_iteration_absent_skipped_2_element_keys(self):
856
808
index = self.make_index(1, key_elements=2, nodes=[
857
((b'name', b'fin'), b'data', ([(b'ref', b'erence')], ))])
858
self.assertEqual([(index, (b'name', b'fin'), b'data', (((b'ref', b'erence'),),))],
859
list(index.iter_all_entries()))
860
self.assertEqual([(index, (b'name', b'fin'), b'data', (((b'ref', b'erence'),),))],
861
list(index.iter_entries([(b'name', b'fin')])))
862
self.assertEqual([], list(index.iter_entries([(b'ref', b'erence')])))
809
(('name', 'fin'), 'data', ([('ref', 'erence')], ))])
810
self.assertEqual(set([(index, ('name', 'fin'), 'data', ((('ref', 'erence'),),))]),
811
set(index.iter_all_entries()))
812
self.assertEqual(set([(index, ('name', 'fin'), 'data', ((('ref', 'erence'),),))]),
813
set(index.iter_entries([('name', 'fin')])))
814
self.assertEqual([], list(index.iter_entries([('ref', 'erence')])))
864
816
def test_iter_all_keys(self):
865
817
index = self.make_index(1, nodes=[
866
((b'name', ), b'data', ([(b'ref', )], )),
867
((b'ref', ), b'refdata', ([], ))])
868
self.assertEqual({(index, (b'name', ), b'data', (((b'ref',),),)),
869
(index, (b'ref', ), b'refdata', ((), ))},
870
set(index.iter_entries([(b'name', ), (b'ref', )])))
818
(('name', ), 'data', ([('ref', )], )),
819
(('ref', ), 'refdata', ([], ))])
820
self.assertEqual(set([(index, ('name', ), 'data', ((('ref',),),)),
821
(index, ('ref', ), 'refdata', ((), ))]),
822
set(index.iter_entries([('name', ), ('ref', )])))
872
824
def test_iter_nothing_empty(self):
873
825
index = self.make_index()
876
828
def test_iter_missing_entry_empty(self):
877
829
index = self.make_index()
878
self.assertEqual([], list(index.iter_entries([(b'a', )])))
830
self.assertEqual([], list(index.iter_entries([('a', )])))
880
832
def test_iter_missing_entry_empty_no_size(self):
881
idx = self.make_index()
882
idx = _mod_index.GraphIndex(idx._transport, 'index', None)
883
self.assertEqual([], list(idx.iter_entries([(b'a', )])))
833
index = self.make_index()
834
index = GraphIndex(index._transport, 'index', None)
835
self.assertEqual([], list(index.iter_entries([('a', )])))
885
837
def test_iter_key_prefix_1_element_key_None(self):
886
838
index = self.make_index()
887
self.assertRaises(_mod_index.BadIndexKey, list,
888
index.iter_entries_prefix([(None, )]))
839
self.assertRaises(errors.BadIndexKey, list,
840
index.iter_entries_prefix([(None, )]))
890
842
def test_iter_key_prefix_wrong_length(self):
891
843
index = self.make_index()
892
self.assertRaises(_mod_index.BadIndexKey, list,
893
index.iter_entries_prefix([(b'foo', None)]))
844
self.assertRaises(errors.BadIndexKey, list,
845
index.iter_entries_prefix([('foo', None)]))
894
846
index = self.make_index(key_elements=2)
895
self.assertRaises(_mod_index.BadIndexKey, list,
896
index.iter_entries_prefix([(b'foo', )]))
897
self.assertRaises(_mod_index.BadIndexKey, list,
898
index.iter_entries_prefix([(b'foo', None, None)]))
847
self.assertRaises(errors.BadIndexKey, list,
848
index.iter_entries_prefix([('foo', )]))
849
self.assertRaises(errors.BadIndexKey, list,
850
index.iter_entries_prefix([('foo', None, None)]))
900
852
def test_iter_key_prefix_1_key_element_no_refs(self):
901
index = self.make_index(nodes=[
902
((b'name', ), b'data', ()),
903
((b'ref', ), b'refdata', ())])
904
self.assertEqual({(index, (b'name', ), b'data'),
905
(index, (b'ref', ), b'refdata')},
906
set(index.iter_entries_prefix([(b'name', ), (b'ref', )])))
853
index = self.make_index( nodes=[
854
(('name', ), 'data', ()),
855
(('ref', ), 'refdata', ())])
856
self.assertEqual(set([(index, ('name', ), 'data'),
857
(index, ('ref', ), 'refdata')]),
858
set(index.iter_entries_prefix([('name', ), ('ref', )])))
908
860
def test_iter_key_prefix_1_key_element_refs(self):
909
861
index = self.make_index(1, nodes=[
910
((b'name', ), b'data', ([(b'ref', )], )),
911
((b'ref', ), b'refdata', ([], ))])
912
self.assertEqual({(index, (b'name', ), b'data', (((b'ref',),),)),
913
(index, (b'ref', ), b'refdata', ((), ))},
914
set(index.iter_entries_prefix([(b'name', ), (b'ref', )])))
862
(('name', ), 'data', ([('ref', )], )),
863
(('ref', ), 'refdata', ([], ))])
864
self.assertEqual(set([(index, ('name', ), 'data', ((('ref',),),)),
865
(index, ('ref', ), 'refdata', ((), ))]),
866
set(index.iter_entries_prefix([('name', ), ('ref', )])))
916
868
def test_iter_key_prefix_2_key_element_no_refs(self):
917
869
index = self.make_index(key_elements=2, nodes=[
918
((b'name', b'fin1'), b'data', ()),
919
((b'name', b'fin2'), b'beta', ()),
920
((b'ref', b'erence'), b'refdata', ())])
921
self.assertEqual({(index, (b'name', b'fin1'), b'data'),
922
(index, (b'ref', b'erence'), b'refdata')},
923
set(index.iter_entries_prefix([(b'name', b'fin1'), (b'ref', b'erence')])))
924
self.assertEqual({(index, (b'name', b'fin1'), b'data'),
925
(index, (b'name', b'fin2'), b'beta')},
926
set(index.iter_entries_prefix([(b'name', None)])))
870
(('name', 'fin1'), 'data', ()),
871
(('name', 'fin2'), 'beta', ()),
872
(('ref', 'erence'), 'refdata', ())])
873
self.assertEqual(set([(index, ('name', 'fin1'), 'data'),
874
(index, ('ref', 'erence'), 'refdata')]),
875
set(index.iter_entries_prefix([('name', 'fin1'), ('ref', 'erence')])))
876
self.assertEqual(set([(index, ('name', 'fin1'), 'data'),
877
(index, ('name', 'fin2'), 'beta')]),
878
set(index.iter_entries_prefix([('name', None)])))
928
880
def test_iter_key_prefix_2_key_element_refs(self):
929
881
index = self.make_index(1, key_elements=2, nodes=[
930
((b'name', b'fin1'), b'data', ([(b'ref', b'erence')], )),
931
((b'name', b'fin2'), b'beta', ([], )),
932
((b'ref', b'erence'), b'refdata', ([], ))])
933
self.assertEqual({(index, (b'name', b'fin1'), b'data', (((b'ref', b'erence'),),)),
934
(index, (b'ref', b'erence'), b'refdata', ((), ))},
935
set(index.iter_entries_prefix([(b'name', b'fin1'), (b'ref', b'erence')])))
936
self.assertEqual({(index, (b'name', b'fin1'), b'data', (((b'ref', b'erence'),),)),
937
(index, (b'name', b'fin2'), b'beta', ((), ))},
938
set(index.iter_entries_prefix([(b'name', None)])))
882
(('name', 'fin1'), 'data', ([('ref', 'erence')], )),
883
(('name', 'fin2'), 'beta', ([], )),
884
(('ref', 'erence'), 'refdata', ([], ))])
885
self.assertEqual(set([(index, ('name', 'fin1'), 'data', ((('ref', 'erence'),),)),
886
(index, ('ref', 'erence'), 'refdata', ((), ))]),
887
set(index.iter_entries_prefix([('name', 'fin1'), ('ref', 'erence')])))
888
self.assertEqual(set([(index, ('name', 'fin1'), 'data', ((('ref', 'erence'),),)),
889
(index, ('name', 'fin2'), 'beta', ((), ))]),
890
set(index.iter_entries_prefix([('name', None)])))
940
892
def test_key_count_empty(self):
941
893
index = self.make_index()
942
894
self.assertEqual(0, index.key_count())
944
896
def test_key_count_one(self):
945
index = self.make_index(nodes=[((b'name', ), b'', ())])
897
index = self.make_index(nodes=[(('name', ), '', ())])
946
898
self.assertEqual(1, index.key_count())
948
900
def test_key_count_two(self):
949
901
index = self.make_index(nodes=[
950
((b'name', ), b'', ()), ((b'foo', ), b'', ())])
902
(('name', ), '', ()), (('foo', ), '', ())])
951
903
self.assertEqual(2, index.key_count())
953
905
def test_read_and_parse_tracks_real_read_value(self):
1180
1128
log.append(self._index)
1181
1129
return self._index.clear_cache()
1183
idx = _mod_index.CombinedGraphIndex([])
1184
idx1 = self.make_index('name', 0, nodes=[((b'key', ), b'', ())])
1185
idx.insert_index(0, ClearCacheProxy(idx1))
1186
idx2 = self.make_index('name', 0, nodes=[((b'key', ), b'', ())])
1187
idx.insert_index(1, ClearCacheProxy(idx2))
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))
1188
1136
# CombinedGraphIndex should call 'clear_cache()' on all children
1190
self.assertEqual(sorted([idx1, idx2]), sorted(log))
1138
self.assertEqual(sorted([index1, index2]), sorted(log))
1192
1140
def test_iter_all_entries_empty(self):
1193
idx = _mod_index.CombinedGraphIndex([])
1194
self.assertEqual([], list(idx.iter_all_entries()))
1141
index = CombinedGraphIndex([])
1142
self.assertEqual([], list(index.iter_all_entries()))
1196
1144
def test_iter_all_entries_children_empty(self):
1197
idx1 = self.make_index('name')
1198
idx = _mod_index.CombinedGraphIndex([idx1])
1199
self.assertEqual([], list(idx.iter_all_entries()))
1145
index1 = self.make_index('name')
1146
index = CombinedGraphIndex([index1])
1147
self.assertEqual([], list(index.iter_all_entries()))
1201
1149
def test_iter_all_entries_simple(self):
1202
idx1 = self.make_index('name', nodes=[((b'name', ), b'data', ())])
1203
idx = _mod_index.CombinedGraphIndex([idx1])
1204
self.assertEqual([(idx1, (b'name', ), b'data')],
1205
list(idx.iter_all_entries()))
1150
index1 = self.make_index('name', nodes=[(('name', ), 'data', ())])
1151
index = CombinedGraphIndex([index1])
1152
self.assertEqual([(index1, ('name', ), 'data')],
1153
list(index.iter_all_entries()))
1207
1155
def test_iter_all_entries_two_indices(self):
1208
idx1 = self.make_index('name1', nodes=[((b'name', ), b'data', ())])
1209
idx2 = self.make_index('name2', nodes=[((b'2', ), b'', ())])
1210
idx = _mod_index.CombinedGraphIndex([idx1, idx2])
1211
self.assertEqual([(idx1, (b'name', ), b'data'),
1212
(idx2, (b'2', ), b'')],
1213
list(idx.iter_all_entries()))
1156
index1 = self.make_index('name1', nodes=[(('name', ), 'data', ())])
1157
index2 = self.make_index('name2', nodes=[(('2', ), '', ())])
1158
index = CombinedGraphIndex([index1, index2])
1159
self.assertEqual([(index1, ('name', ), 'data'),
1160
(index2, ('2', ), '')],
1161
list(index.iter_all_entries()))
1215
1163
def test_iter_entries_two_indices_dup_key(self):
1216
idx1 = self.make_index('name1', nodes=[((b'name', ), b'data', ())])
1217
idx2 = self.make_index('name2', nodes=[((b'name', ), b'data', ())])
1218
idx = _mod_index.CombinedGraphIndex([idx1, idx2])
1219
self.assertEqual([(idx1, (b'name', ), b'data')],
1220
list(idx.iter_entries([(b'name', )])))
1164
index1 = self.make_index('name1', nodes=[(('name', ), 'data', ())])
1165
index2 = self.make_index('name2', nodes=[(('name', ), 'data', ())])
1166
index = CombinedGraphIndex([index1, index2])
1167
self.assertEqual([(index1, ('name', ), 'data')],
1168
list(index.iter_entries([('name', )])))
1222
1170
def test_iter_all_entries_two_indices_dup_key(self):
1223
idx1 = self.make_index('name1', nodes=[((b'name', ), b'data', ())])
1224
idx2 = self.make_index('name2', nodes=[((b'name', ), b'data', ())])
1225
idx = _mod_index.CombinedGraphIndex([idx1, idx2])
1226
self.assertEqual([(idx1, (b'name', ), b'data')],
1227
list(idx.iter_all_entries()))
1171
index1 = self.make_index('name1', nodes=[(('name', ), 'data', ())])
1172
index2 = self.make_index('name2', nodes=[(('name', ), 'data', ())])
1173
index = CombinedGraphIndex([index1, index2])
1174
self.assertEqual([(index1, ('name', ), 'data')],
1175
list(index.iter_all_entries()))
1229
1177
def test_iter_key_prefix_2_key_element_refs(self):
1230
idx1 = self.make_index('1', 1, key_elements=2, nodes=[
1231
((b'name', b'fin1'), b'data', ([(b'ref', b'erence')], ))])
1232
idx2 = self.make_index('2', 1, key_elements=2, nodes=[
1233
((b'name', b'fin2'), b'beta', ([], )),
1234
((b'ref', b'erence'), b'refdata', ([], ))])
1235
idx = _mod_index.CombinedGraphIndex([idx1, idx2])
1236
self.assertEqual({(idx1, (b'name', b'fin1'), b'data',
1237
(((b'ref', b'erence'),),)),
1238
(idx2, (b'ref', b'erence'), b'refdata', ((), ))},
1239
set(idx.iter_entries_prefix([(b'name', b'fin1'),
1240
(b'ref', b'erence')])))
1241
self.assertEqual({(idx1, (b'name', b'fin1'), b'data',
1242
(((b'ref', b'erence'),),)),
1243
(idx2, (b'name', b'fin2'), b'beta', ((), ))},
1244
set(idx.iter_entries_prefix([(b'name', None)])))
1178
index1 = self.make_index('1', 1, key_elements=2, nodes=[
1179
(('name', 'fin1'), 'data', ([('ref', 'erence')], ))])
1180
index2 = self.make_index('2', 1, key_elements=2, nodes=[
1181
(('name', 'fin2'), 'beta', ([], )),
1182
(('ref', 'erence'), 'refdata', ([], ))])
1183
index = CombinedGraphIndex([index1, index2])
1184
self.assertEqual(set([(index1, ('name', 'fin1'), 'data', ((('ref', 'erence'),),)),
1185
(index2, ('ref', 'erence'), 'refdata', ((), ))]),
1186
set(index.iter_entries_prefix([('name', 'fin1'), ('ref', 'erence')])))
1187
self.assertEqual(set([(index1, ('name', 'fin1'), 'data', ((('ref', 'erence'),),)),
1188
(index2, ('name', 'fin2'), 'beta', ((), ))]),
1189
set(index.iter_entries_prefix([('name', None)])))
1246
1191
def test_iter_nothing_empty(self):
1247
idx = _mod_index.CombinedGraphIndex([])
1248
self.assertEqual([], list(idx.iter_entries([])))
1192
index = CombinedGraphIndex([])
1193
self.assertEqual([], list(index.iter_entries([])))
1250
1195
def test_iter_nothing_children_empty(self):
1251
idx1 = self.make_index('name')
1252
idx = _mod_index.CombinedGraphIndex([idx1])
1253
self.assertEqual([], list(idx.iter_entries([])))
1196
index1 = self.make_index('name')
1197
index = CombinedGraphIndex([index1])
1198
self.assertEqual([], list(index.iter_entries([])))
1255
1200
def test_iter_all_keys(self):
1256
idx1 = self.make_index('1', 1, nodes=[((b'name', ), b'data',
1258
idx2 = self.make_index(
1259
'2', 1, nodes=[((b'ref', ), b'refdata', ((), ))])
1260
idx = _mod_index.CombinedGraphIndex([idx1, idx2])
1261
self.assertEqual({(idx1, (b'name', ), b'data', (((b'ref', ), ), )),
1262
(idx2, (b'ref', ), b'refdata', ((), ))},
1263
set(idx.iter_entries([(b'name', ), (b'ref', )])))
1201
index1 = self.make_index('1', 1, nodes=[
1202
(('name', ), 'data', ([('ref', )], ))])
1203
index2 = self.make_index('2', 1, nodes=[
1204
(('ref', ), 'refdata', ((), ))])
1205
index = CombinedGraphIndex([index1, index2])
1206
self.assertEqual(set([(index1, ('name', ), 'data', ((('ref', ), ), )),
1207
(index2, ('ref', ), 'refdata', ((), ))]),
1208
set(index.iter_entries([('name', ), ('ref', )])))
1265
1210
def test_iter_all_keys_dup_entry(self):
1266
idx1 = self.make_index('1', 1, nodes=[((b'name', ), b'data',
1268
((b'ref', ), b'refdata', ([], ))])
1269
idx2 = self.make_index(
1270
'2', 1, nodes=[((b'ref', ), b'refdata', ([], ))])
1271
idx = _mod_index.CombinedGraphIndex([idx1, idx2])
1272
self.assertEqual({(idx1, (b'name', ), b'data', (((b'ref',),),)),
1273
(idx1, (b'ref', ), b'refdata', ((), ))},
1274
set(idx.iter_entries([(b'name', ), (b'ref', )])))
1211
index1 = self.make_index('1', 1, nodes=[
1212
(('name', ), 'data', ([('ref', )], )),
1213
(('ref', ), 'refdata', ([], ))])
1214
index2 = self.make_index('2', 1, nodes=[
1215
(('ref', ), 'refdata', ([], ))])
1216
index = CombinedGraphIndex([index1, index2])
1217
self.assertEqual(set([(index1, ('name', ), 'data', ((('ref',),),)),
1218
(index1, ('ref', ), 'refdata', ((), ))]),
1219
set(index.iter_entries([('name', ), ('ref', )])))
1276
1221
def test_iter_missing_entry_empty(self):
1277
idx = _mod_index.CombinedGraphIndex([])
1278
self.assertEqual([], list(idx.iter_entries([('a', )])))
1222
index = CombinedGraphIndex([])
1223
self.assertEqual([], list(index.iter_entries([('a', )])))
1280
1225
def test_iter_missing_entry_one_index(self):
1281
idx1 = self.make_index('1')
1282
idx = _mod_index.CombinedGraphIndex([idx1])
1283
self.assertEqual([], list(idx.iter_entries([(b'a', )])))
1226
index1 = self.make_index('1')
1227
index = CombinedGraphIndex([index1])
1228
self.assertEqual([], list(index.iter_entries([('a', )])))
1285
1230
def test_iter_missing_entry_two_index(self):
1286
idx1 = self.make_index('1')
1287
idx2 = self.make_index('2')
1288
idx = _mod_index.CombinedGraphIndex([idx1, idx2])
1289
self.assertEqual([], list(idx.iter_entries([('a', )])))
1231
index1 = self.make_index('1')
1232
index2 = self.make_index('2')
1233
index = CombinedGraphIndex([index1, index2])
1234
self.assertEqual([], list(index.iter_entries([('a', )])))
1291
1236
def test_iter_entry_present_one_index_only(self):
1292
idx1 = self.make_index('1', nodes=[((b'key', ), b'', ())])
1293
idx2 = self.make_index('2', nodes=[])
1294
idx = _mod_index.CombinedGraphIndex([idx1, idx2])
1295
self.assertEqual([(idx1, (b'key', ), b'')],
1296
list(idx.iter_entries([(b'key', )])))
1237
index1 = self.make_index('1', nodes=[(('key', ), '', ())])
1238
index2 = self.make_index('2', nodes=[])
1239
index = CombinedGraphIndex([index1, index2])
1240
self.assertEqual([(index1, ('key', ), '')],
1241
list(index.iter_entries([('key', )])))
1297
1242
# and in the other direction
1298
idx = _mod_index.CombinedGraphIndex([idx2, idx1])
1299
self.assertEqual([(idx1, (b'key', ), b'')],
1300
list(idx.iter_entries([(b'key', )])))
1243
index = CombinedGraphIndex([index2, index1])
1244
self.assertEqual([(index1, ('key', ), '')],
1245
list(index.iter_entries([('key', )])))
1302
1247
def test_key_count_empty(self):
1303
idx1 = self.make_index('1', nodes=[])
1304
idx2 = self.make_index('2', nodes=[])
1305
idx = _mod_index.CombinedGraphIndex([idx1, idx2])
1306
self.assertEqual(0, idx.key_count())
1248
index1 = self.make_index('1', nodes=[])
1249
index2 = self.make_index('2', nodes=[])
1250
index = CombinedGraphIndex([index1, index2])
1251
self.assertEqual(0, index.key_count())
1308
1253
def test_key_count_sums_index_keys(self):
1309
idx1 = self.make_index('1', nodes=[
1311
((b'2',), b'', ())])
1312
idx2 = self.make_index('2', nodes=[((b'1',), b'', ())])
1313
idx = _mod_index.CombinedGraphIndex([idx1, idx2])
1314
self.assertEqual(3, idx.key_count())
1254
index1 = self.make_index('1', nodes=[
1257
index2 = self.make_index('2', nodes=[(('1',), '', ())])
1258
index = CombinedGraphIndex([index1, index2])
1259
self.assertEqual(3, index.key_count())
1316
1261
def test_validate_bad_child_index_errors(self):
1317
1262
trans = self.get_transport()
1318
trans.put_bytes('name', b"not an index\n")
1319
idx1 = _mod_index.GraphIndex(trans, 'name', 13)
1320
idx = _mod_index.CombinedGraphIndex([idx1])
1321
self.assertRaises(_mod_index.BadIndexFormatSignature, idx.validate)
1263
trans.put_bytes('name', "not an index\n")
1264
index1 = GraphIndex(trans, 'name', 13)
1265
index = CombinedGraphIndex([index1])
1266
self.assertRaises(errors.BadIndexFormatSignature, index.validate)
1323
1268
def test_validate_empty(self):
1324
idx = _mod_index.CombinedGraphIndex([])
1269
index = CombinedGraphIndex([])
1327
1272
def test_key_count_reloads(self):
1328
idx, reload_counter = self.make_combined_index_with_missing()
1329
self.assertEqual(2, idx.key_count())
1273
index, reload_counter = self.make_combined_index_with_missing()
1274
self.assertEqual(2, index.key_count())
1330
1275
self.assertEqual([1, 1, 0], reload_counter)
1332
1277
def test_key_count_no_reload(self):
1333
idx, reload_counter = self.make_combined_index_with_missing()
1334
idx._reload_func = None
1278
index, reload_counter = self.make_combined_index_with_missing()
1279
index._reload_func = None
1335
1280
# Without a _reload_func we just raise the exception
1336
self.assertRaises(errors.NoSuchFile, idx.key_count)
1281
self.assertRaises(errors.NoSuchFile, index.key_count)
1338
1283
def test_key_count_reloads_and_fails(self):
1339
1284
# We have deleted all underlying indexes, so we will try to reload, but
1340
1285
# still fail. This is mostly to test we don't get stuck in an infinite
1341
1286
# loop trying to reload
1342
idx, reload_counter = self.make_combined_index_with_missing(
1344
self.assertRaises(errors.NoSuchFile, idx.key_count)
1287
index, reload_counter = self.make_combined_index_with_missing(
1289
self.assertRaises(errors.NoSuchFile, index.key_count)
1345
1290
self.assertEqual([2, 1, 1], reload_counter)
1347
1292
def test_iter_entries_reloads(self):
1348
1293
index, reload_counter = self.make_combined_index_with_missing()
1349
result = list(index.iter_entries([(b'1',), (b'2',), (b'3',)]))
1294
result = list(index.iter_entries([('1',), ('2',), ('3',)]))
1350
1295
index3 = index._indices[0]
1351
self.assertEqual({(index3, (b'1',), b''), (index3, (b'2',), b'')},
1296
self.assertEqual([(index3, ('1',), ''), (index3, ('2',), '')],
1353
1298
self.assertEqual([1, 1, 0], reload_counter)
1355
1300
def test_iter_entries_reloads_midway(self):
1404
1349
def test_iter_all_entries_reloads_and_fails(self):
1405
1350
index, reload_counter = self.make_combined_index_with_missing(
1407
1352
self.assertListRaises(errors.NoSuchFile, index.iter_all_entries)
1409
1354
def test_iter_entries_prefix_reloads(self):
1410
1355
index, reload_counter = self.make_combined_index_with_missing()
1411
result = list(index.iter_entries_prefix([(b'1',)]))
1356
result = list(index.iter_entries_prefix([('1',)]))
1412
1357
index3 = index._indices[0]
1413
self.assertEqual([(index3, (b'1',), b'')], result)
1358
self.assertEqual([(index3, ('1',), '')], result)
1414
1359
self.assertEqual([1, 1, 0], reload_counter)
1416
1361
def test_iter_entries_prefix_reloads_midway(self):
1417
1362
index, reload_counter = self.make_combined_index_with_missing(['2'])
1418
1363
index1, index2 = index._indices
1419
result = list(index.iter_entries_prefix([(b'1',)]))
1364
result = list(index.iter_entries_prefix([('1',)]))
1420
1365
index3 = index._indices[0]
1421
# We had already yielded b'1', so we just go on to the next, we should
1422
# not yield b'1' twice.
1423
self.assertEqual([(index1, (b'1',), b'')], result)
1366
# We had already yielded '1', so we just go on to the next, we should
1367
# not yield '1' twice.
1368
self.assertEqual([(index1, ('1',), '')], result)
1424
1369
self.assertEqual([1, 1, 0], reload_counter)
1426
1371
def test_iter_entries_prefix_no_reload(self):
1427
1372
index, reload_counter = self.make_combined_index_with_missing()
1428
1373
index._reload_func = None
1429
1374
self.assertListRaises(errors.NoSuchFile, index.iter_entries_prefix,
1432
1377
def test_iter_entries_prefix_reloads_and_fails(self):
1433
1378
index, reload_counter = self.make_combined_index_with_missing(
1435
1380
self.assertListRaises(errors.NoSuchFile, index.iter_entries_prefix,
1438
def make_index_with_simple_nodes(self, name, num_nodes=1):
1439
"""Make an index named after 'name', with keys named after 'name' too.
1441
Nodes will have a value of '' and no references.
1444
((('index-%s-key-%s' % (name, n)).encode('ascii'),), b'', ())
1445
for n in range(1, num_nodes + 1)]
1446
return self.make_index('index-%s' % name, 0, nodes=nodes)
1448
def test_reorder_after_iter_entries(self):
1449
# Four indices: [key1] in idx1, [key2,key3] in idx2, [] in idx3,
1451
idx = _mod_index.CombinedGraphIndex([])
1452
idx.insert_index(0, self.make_index_with_simple_nodes('1'), b'1')
1453
idx.insert_index(1, self.make_index_with_simple_nodes('2'), b'2')
1454
idx.insert_index(2, self.make_index_with_simple_nodes('3'), b'3')
1455
idx.insert_index(3, self.make_index_with_simple_nodes('4'), b'4')
1456
idx1, idx2, idx3, idx4 = idx._indices
1457
# Query a key from idx4 and idx2.
1458
self.assertLength(2, list(idx.iter_entries(
1459
[(b'index-4-key-1',), (b'index-2-key-1',)])))
1460
# Now idx2 and idx4 should be moved to the front (and idx1 should
1461
# still be before idx3).
1462
self.assertEqual([idx2, idx4, idx1, idx3], idx._indices)
1463
self.assertEqual([b'2', b'4', b'1', b'3'], idx._index_names)
1465
def test_reorder_propagates_to_siblings(self):
1466
# Two CombinedGraphIndex objects, with the same number of indicies with
1468
cgi1 = _mod_index.CombinedGraphIndex([])
1469
cgi2 = _mod_index.CombinedGraphIndex([])
1470
cgi1.insert_index(0, self.make_index_with_simple_nodes('1-1'), 'one')
1471
cgi1.insert_index(1, self.make_index_with_simple_nodes('1-2'), 'two')
1472
cgi2.insert_index(0, self.make_index_with_simple_nodes('2-1'), 'one')
1473
cgi2.insert_index(1, self.make_index_with_simple_nodes('2-2'), 'two')
1474
index2_1, index2_2 = cgi2._indices
1475
cgi1.set_sibling_indices([cgi2])
1476
# Trigger a reordering in cgi1. cgi2 will be reordered as well.
1477
list(cgi1.iter_entries([(b'index-1-2-key-1',)]))
1478
self.assertEqual([index2_2, index2_1], cgi2._indices)
1479
self.assertEqual(['two', 'one'], cgi2._index_names)
1481
1383
def test_validate_reloads(self):
1482
idx, reload_counter = self.make_combined_index_with_missing()
1384
index, reload_counter = self.make_combined_index_with_missing()
1484
1386
self.assertEqual([1, 1, 0], reload_counter)
1486
1388
def test_validate_reloads_midway(self):
1487
idx, reload_counter = self.make_combined_index_with_missing(['2'])
1389
index, reload_counter = self.make_combined_index_with_missing(['2'])
1490
1392
def test_validate_no_reload(self):
1491
idx, reload_counter = self.make_combined_index_with_missing()
1492
idx._reload_func = None
1493
self.assertRaises(errors.NoSuchFile, idx.validate)
1393
index, reload_counter = self.make_combined_index_with_missing()
1394
index._reload_func = None
1395
self.assertRaises(errors.NoSuchFile, index.validate)
1495
1397
def test_validate_reloads_and_fails(self):
1496
idx, reload_counter = self.make_combined_index_with_missing(
1498
self.assertRaises(errors.NoSuchFile, idx.validate)
1398
index, reload_counter = self.make_combined_index_with_missing(
1400
self.assertRaises(errors.NoSuchFile, index.validate)
1500
1402
def test_find_ancestors_across_indexes(self):
1505
1407
index1 = self.make_index('12', ref_lists=1, nodes=[
1506
(key1, b'value', ([],)),
1507
(key2, b'value', ([key1],)),
1408
(key1, 'value', ([],)),
1409
(key2, 'value', ([key1],)),
1509
1411
index2 = self.make_index('34', ref_lists=1, nodes=[
1510
(key3, b'value', ([key2],)),
1511
(key4, b'value', ([key3],)),
1412
(key3, 'value', ([key2],)),
1413
(key4, 'value', ([key3],)),
1513
c_index = _mod_index.CombinedGraphIndex([index1, index2])
1415
c_index = CombinedGraphIndex([index1, index2])
1514
1416
parent_map, missing_keys = c_index.find_ancestry([key1], 0)
1515
1417
self.assertEqual({key1: ()}, parent_map)
1516
1418
self.assertEqual(set(), missing_keys)
1522
1424
self.assertEqual(set(), missing_keys)
1524
1426
def test_find_ancestors_missing_keys(self):
1529
1431
index1 = self.make_index('12', ref_lists=1, nodes=[
1530
(key1, b'value', ([],)),
1531
(key2, b'value', ([key1],)),
1432
(key1, 'value', ([],)),
1433
(key2, 'value', ([key1],)),
1533
1435
index2 = self.make_index('34', ref_lists=1, nodes=[
1534
(key3, b'value', ([key2],)),
1436
(key3, 'value', ([key2],)),
1536
c_index = _mod_index.CombinedGraphIndex([index1, index2])
1438
c_index = CombinedGraphIndex([index1, index2])
1537
1439
# Searching for a key which is actually not present at all should
1538
1440
# eventually converge
1539
1441
parent_map, missing_keys = c_index.find_ancestry([key4], 0)
1540
1442
self.assertEqual({}, parent_map)
1541
self.assertEqual({key4}, missing_keys)
1443
self.assertEqual(set([key4]), missing_keys)
1543
1445
def test_find_ancestors_no_indexes(self):
1544
c_index = _mod_index.CombinedGraphIndex([])
1446
c_index = CombinedGraphIndex([])
1546
1448
parent_map, missing_keys = c_index.find_ancestry([key1], 0)
1547
1449
self.assertEqual({}, parent_map)
1548
self.assertEqual({key1}, missing_keys)
1450
self.assertEqual(set([key1]), missing_keys)
1550
1452
def test_find_ancestors_ghost_parent(self):
1555
1457
index1 = self.make_index('12', ref_lists=1, nodes=[
1556
(key1, b'value', ([],)),
1557
(key2, b'value', ([key1],)),
1458
(key1, 'value', ([],)),
1459
(key2, 'value', ([key1],)),
1559
1461
index2 = self.make_index('34', ref_lists=1, nodes=[
1560
(key4, b'value', ([key2, key3],)),
1462
(key4, 'value', ([key2, key3],)),
1562
c_index = _mod_index.CombinedGraphIndex([index1, index2])
1464
c_index = CombinedGraphIndex([index1, index2])
1563
1465
# Searching for a key which is actually not present at all should
1564
1466
# eventually converge
1565
1467
parent_map, missing_keys = c_index.find_ancestry([key4], 0)
1566
1468
self.assertEqual({key4: (key2, key3), key2: (key1,), key1: ()},
1568
self.assertEqual({key3}, missing_keys)
1470
self.assertEqual(set([key3]), missing_keys)
1570
1472
def test__find_ancestors_empty_index(self):
1571
idx = self.make_index('test', ref_lists=1, key_elements=1, nodes=[])
1473
index = self.make_index('test', ref_lists=1, key_elements=1, nodes=[])
1572
1474
parent_map = {}
1573
1475
missing_keys = set()
1574
search_keys = idx._find_ancestors([(b'one',), (b'two',)], 0, parent_map,
1476
search_keys = index._find_ancestors([('one',), ('two',)], 0, parent_map,
1576
1478
self.assertEqual(set(), search_keys)
1577
1479
self.assertEqual({}, parent_map)
1578
self.assertEqual({(b'one',), (b'two',)}, missing_keys)
1581
class TestInMemoryGraphIndex(tests.TestCaseWithMemoryTransport):
1480
self.assertEqual(set([('one',), ('two',)]), missing_keys)
1483
class TestInMemoryGraphIndex(TestCaseWithMemoryTransport):
1583
1485
def make_index(self, ref_lists=0, key_elements=1, nodes=[]):
1584
result = _mod_index.InMemoryGraphIndex(
1585
ref_lists, key_elements=key_elements)
1486
result = InMemoryGraphIndex(ref_lists, key_elements=key_elements)
1586
1487
result.add_nodes(nodes)
1589
1490
def test_add_nodes_no_refs(self):
1590
1491
index = self.make_index(0)
1591
index.add_nodes([((b'name', ), b'data')])
1592
index.add_nodes([((b'name2', ), b''), ((b'name3', ), b'')])
1594
(index, (b'name', ), b'data'),
1595
(index, (b'name2', ), b''),
1596
(index, (b'name3', ), b''),
1597
}, set(index.iter_all_entries()))
1492
index.add_nodes([(('name', ), 'data')])
1493
index.add_nodes([(('name2', ), ''), (('name3', ), '')])
1494
self.assertEqual(set([
1495
(index, ('name', ), 'data'),
1496
(index, ('name2', ), ''),
1497
(index, ('name3', ), ''),
1498
]), set(index.iter_all_entries()))
1599
1500
def test_add_nodes(self):
1600
1501
index = self.make_index(1)
1601
index.add_nodes([((b'name', ), b'data', ([],))])
1602
index.add_nodes([((b'name2', ), b'', ([],)),
1603
((b'name3', ), b'', ([(b'r', )],))])
1605
(index, (b'name', ), b'data', ((),)),
1606
(index, (b'name2', ), b'', ((),)),
1607
(index, (b'name3', ), b'', (((b'r', ), ), )),
1608
}, set(index.iter_all_entries()))
1502
index.add_nodes([(('name', ), 'data', ([],))])
1503
index.add_nodes([(('name2', ), '', ([],)), (('name3', ), '', ([('r', )],))])
1504
self.assertEqual(set([
1505
(index, ('name', ), 'data', ((),)),
1506
(index, ('name2', ), '', ((),)),
1507
(index, ('name3', ), '', ((('r', ), ), )),
1508
]), set(index.iter_all_entries()))
1610
1510
def test_iter_all_entries_empty(self):
1611
1511
index = self.make_index()
1612
1512
self.assertEqual([], list(index.iter_all_entries()))
1614
1514
def test_iter_all_entries_simple(self):
1615
index = self.make_index(nodes=[((b'name', ), b'data')])
1616
self.assertEqual([(index, (b'name', ), b'data')],
1617
list(index.iter_all_entries()))
1515
index = self.make_index(nodes=[(('name', ), 'data')])
1516
self.assertEqual([(index, ('name', ), 'data')],
1517
list(index.iter_all_entries()))
1619
1519
def test_iter_all_entries_references(self):
1620
1520
index = self.make_index(1, nodes=[
1621
((b'name', ), b'data', ([(b'ref', )], )),
1622
((b'ref', ), b'refdata', ([], ))])
1623
self.assertEqual({(index, (b'name', ), b'data', (((b'ref', ),),)),
1624
(index, (b'ref', ), b'refdata', ((), ))},
1625
set(index.iter_all_entries()))
1521
(('name', ), 'data', ([('ref', )], )),
1522
(('ref', ), 'refdata', ([], ))])
1523
self.assertEqual(set([(index, ('name', ), 'data', ((('ref', ),),)),
1524
(index, ('ref', ), 'refdata', ((), ))]),
1525
set(index.iter_all_entries()))
1627
1527
def test_iteration_absent_skipped(self):
1628
1528
index = self.make_index(1, nodes=[
1629
((b'name', ), b'data', ([(b'ref', )], ))])
1630
self.assertEqual({(index, (b'name', ), b'data', (((b'ref',),),))},
1631
set(index.iter_all_entries()))
1632
self.assertEqual({(index, (b'name', ), b'data', (((b'ref',),),))},
1633
set(index.iter_entries([(b'name', )])))
1634
self.assertEqual([], list(index.iter_entries([(b'ref', )])))
1529
(('name', ), 'data', ([('ref', )], ))])
1530
self.assertEqual(set([(index, ('name', ), 'data', ((('ref',),),))]),
1531
set(index.iter_all_entries()))
1532
self.assertEqual(set([(index, ('name', ), 'data', ((('ref',),),))]),
1533
set(index.iter_entries([('name', )])))
1534
self.assertEqual([], list(index.iter_entries([('ref', )])))
1636
1536
def test_iter_all_keys(self):
1637
1537
index = self.make_index(1, nodes=[
1638
((b'name', ), b'data', ([(b'ref', )], )),
1639
((b'ref', ), b'refdata', ([], ))])
1640
self.assertEqual({(index, (b'name', ), b'data', (((b'ref',),),)),
1641
(index, (b'ref', ), b'refdata', ((), ))},
1642
set(index.iter_entries([(b'name', ), (b'ref', )])))
1538
(('name', ), 'data', ([('ref', )], )),
1539
(('ref', ), 'refdata', ([], ))])
1540
self.assertEqual(set([(index, ('name', ), 'data', ((('ref',),),)),
1541
(index, ('ref', ), 'refdata', ((), ))]),
1542
set(index.iter_entries([('name', ), ('ref', )])))
1644
1544
def test_iter_key_prefix_1_key_element_no_refs(self):
1645
index = self.make_index(nodes=[
1646
((b'name', ), b'data'),
1647
((b'ref', ), b'refdata')])
1648
self.assertEqual({(index, (b'name', ), b'data'),
1649
(index, (b'ref', ), b'refdata')},
1650
set(index.iter_entries_prefix([(b'name', ), (b'ref', )])))
1545
index = self.make_index( nodes=[
1546
(('name', ), 'data'),
1547
(('ref', ), 'refdata')])
1548
self.assertEqual(set([(index, ('name', ), 'data'),
1549
(index, ('ref', ), 'refdata')]),
1550
set(index.iter_entries_prefix([('name', ), ('ref', )])))
1652
1552
def test_iter_key_prefix_1_key_element_refs(self):
1653
1553
index = self.make_index(1, nodes=[
1654
((b'name', ), b'data', ([(b'ref', )], )),
1655
((b'ref', ), b'refdata', ([], ))])
1656
self.assertEqual({(index, (b'name', ), b'data', (((b'ref',),),)),
1657
(index, (b'ref', ), b'refdata', ((), ))},
1658
set(index.iter_entries_prefix([(b'name', ), (b'ref', )])))
1554
(('name', ), 'data', ([('ref', )], )),
1555
(('ref', ), 'refdata', ([], ))])
1556
self.assertEqual(set([(index, ('name', ), 'data', ((('ref',),),)),
1557
(index, ('ref', ), 'refdata', ((), ))]),
1558
set(index.iter_entries_prefix([('name', ), ('ref', )])))
1660
1560
def test_iter_key_prefix_2_key_element_no_refs(self):
1661
1561
index = self.make_index(key_elements=2, nodes=[
1662
((b'name', b'fin1'), b'data'),
1663
((b'name', b'fin2'), b'beta'),
1664
((b'ref', b'erence'), b'refdata')])
1665
self.assertEqual({(index, (b'name', b'fin1'), b'data'),
1666
(index, (b'ref', b'erence'), b'refdata')},
1667
set(index.iter_entries_prefix([(b'name', b'fin1'), (b'ref', b'erence')])))
1668
self.assertEqual({(index, (b'name', b'fin1'), b'data'),
1669
(index, (b'name', b'fin2'), b'beta')},
1670
set(index.iter_entries_prefix([(b'name', None)])))
1562
(('name', 'fin1'), 'data'),
1563
(('name', 'fin2'), 'beta'),
1564
(('ref', 'erence'), 'refdata')])
1565
self.assertEqual(set([(index, ('name', 'fin1'), 'data'),
1566
(index, ('ref', 'erence'), 'refdata')]),
1567
set(index.iter_entries_prefix([('name', 'fin1'), ('ref', 'erence')])))
1568
self.assertEqual(set([(index, ('name', 'fin1'), 'data'),
1569
(index, ('name', 'fin2'), 'beta')]),
1570
set(index.iter_entries_prefix([('name', None)])))
1672
1572
def test_iter_key_prefix_2_key_element_refs(self):
1673
1573
index = self.make_index(1, key_elements=2, nodes=[
1674
((b'name', b'fin1'), b'data', ([(b'ref', b'erence')], )),
1675
((b'name', b'fin2'), b'beta', ([], )),
1676
((b'ref', b'erence'), b'refdata', ([], ))])
1677
self.assertEqual({(index, (b'name', b'fin1'), b'data', (((b'ref', b'erence'),),)),
1678
(index, (b'ref', b'erence'), b'refdata', ((), ))},
1679
set(index.iter_entries_prefix([(b'name', b'fin1'), (b'ref', b'erence')])))
1680
self.assertEqual({(index, (b'name', b'fin1'), b'data', (((b'ref', b'erence'),),)),
1681
(index, (b'name', b'fin2'), b'beta', ((), ))},
1682
set(index.iter_entries_prefix([(b'name', None)])))
1574
(('name', 'fin1'), 'data', ([('ref', 'erence')], )),
1575
(('name', 'fin2'), 'beta', ([], )),
1576
(('ref', 'erence'), 'refdata', ([], ))])
1577
self.assertEqual(set([(index, ('name', 'fin1'), 'data', ((('ref', 'erence'),),)),
1578
(index, ('ref', 'erence'), 'refdata', ((), ))]),
1579
set(index.iter_entries_prefix([('name', 'fin1'), ('ref', 'erence')])))
1580
self.assertEqual(set([(index, ('name', 'fin1'), 'data', ((('ref', 'erence'),),)),
1581
(index, ('name', 'fin2'), 'beta', ((), ))]),
1582
set(index.iter_entries_prefix([('name', None)])))
1684
1584
def test_iter_nothing_empty(self):
1685
1585
index = self.make_index()
1706
1606
index.validate()
1708
1608
def test_validate_no_refs_content(self):
1709
index = self.make_index(nodes=[((b'key', ), b'value')])
1609
index = self.make_index(nodes=[(('key', ), 'value')])
1710
1610
index.validate()
1713
class TestGraphIndexPrefixAdapter(tests.TestCaseWithMemoryTransport):
1613
class TestGraphIndexPrefixAdapter(TestCaseWithMemoryTransport):
1715
def make_index(self, ref_lists=1, key_elements=2, nodes=[],
1716
add_callback=False):
1717
result = _mod_index.InMemoryGraphIndex(
1718
ref_lists, key_elements=key_elements)
1615
def make_index(self, ref_lists=1, key_elements=2, nodes=[], add_callback=False):
1616
result = InMemoryGraphIndex(ref_lists, key_elements=key_elements)
1719
1617
result.add_nodes(nodes)
1720
1618
if add_callback:
1721
1619
add_nodes_callback = result.add_nodes
1723
1621
add_nodes_callback = None
1724
adapter = _mod_index.GraphIndexPrefixAdapter(
1725
result, (b'prefix', ), key_elements - 1,
1622
adapter = GraphIndexPrefixAdapter(result, ('prefix', ), key_elements - 1,
1726
1623
add_nodes_callback=add_nodes_callback)
1727
1624
return result, adapter
1729
1626
def test_add_node(self):
1730
1627
index, adapter = self.make_index(add_callback=True)
1731
adapter.add_node((b'key',), b'value', (((b'ref',),),))
1732
self.assertEqual({(index, (b'prefix', b'key'), b'value',
1733
(((b'prefix', b'ref'),),))},
1734
set(index.iter_all_entries()))
1628
adapter.add_node(('key',), 'value', ((('ref',),),))
1629
self.assertEqual(set([(index, ('prefix', 'key'), 'value', ((('prefix', 'ref'),),))]),
1630
set(index.iter_all_entries()))
1736
1632
def test_add_nodes(self):
1737
1633
index, adapter = self.make_index(add_callback=True)
1738
1634
adapter.add_nodes((
1739
((b'key',), b'value', (((b'ref',),),)),
1740
((b'key2',), b'value2', ((),)),
1635
(('key',), 'value', ((('ref',),),)),
1636
(('key2',), 'value2', ((),)),
1743
(index, (b'prefix', b'key2'), b'value2', ((),)),
1744
(index, (b'prefix', b'key'), b'value', (((b'prefix', b'ref'),),))
1638
self.assertEqual(set([
1639
(index, ('prefix', 'key2'), 'value2', ((),)),
1640
(index, ('prefix', 'key'), 'value', ((('prefix', 'ref'),),))
1746
1642
set(index.iter_all_entries()))
1748
1644
def test_construct(self):
1749
idx = _mod_index.InMemoryGraphIndex()
1750
adapter = _mod_index.GraphIndexPrefixAdapter(idx, (b'prefix', ), 1)
1645
index = InMemoryGraphIndex()
1646
adapter = GraphIndexPrefixAdapter(index, ('prefix', ), 1)
1752
1648
def test_construct_with_callback(self):
1753
idx = _mod_index.InMemoryGraphIndex()
1754
adapter = _mod_index.GraphIndexPrefixAdapter(idx, (b'prefix', ), 1,
1649
index = InMemoryGraphIndex()
1650
adapter = GraphIndexPrefixAdapter(index, ('prefix', ), 1, index.add_nodes)
1757
1652
def test_iter_all_entries_cross_prefix_map_errors(self):
1758
1653
index, adapter = self.make_index(nodes=[
1759
((b'prefix', b'key1'), b'data1', (((b'prefixaltered', b'key2'),),))])
1760
self.assertRaises(_mod_index.BadIndexData, list,
1761
adapter.iter_all_entries())
1654
(('prefix', 'key1'), 'data1', ((('prefixaltered', 'key2'),),))])
1655
self.assertRaises(errors.BadIndexData, list, adapter.iter_all_entries())
1763
1657
def test_iter_all_entries(self):
1764
1658
index, adapter = self.make_index(nodes=[
1765
((b'notprefix', b'key1'), b'data', ((), )),
1766
((b'prefix', b'key1'), b'data1', ((), )),
1767
((b'prefix', b'key2'), b'data2', (((b'prefix', b'key1'),),))])
1768
self.assertEqual({(index, (b'key1', ), b'data1', ((),)),
1769
(index, (b'key2', ), b'data2', (((b'key1',),),))},
1770
set(adapter.iter_all_entries()))
1659
(('notprefix', 'key1'), 'data', ((), )),
1660
(('prefix', 'key1'), 'data1', ((), )),
1661
(('prefix', 'key2'), 'data2', ((('prefix', 'key1'),),))])
1662
self.assertEqual(set([(index, ('key1', ), 'data1', ((),)),
1663
(index, ('key2', ), 'data2', ((('key1',),),))]),
1664
set(adapter.iter_all_entries()))
1772
1666
def test_iter_entries(self):
1773
1667
index, adapter = self.make_index(nodes=[
1774
((b'notprefix', b'key1'), b'data', ((), )),
1775
((b'prefix', b'key1'), b'data1', ((), )),
1776
((b'prefix', b'key2'), b'data2', (((b'prefix', b'key1'),),))])
1668
(('notprefix', 'key1'), 'data', ((), )),
1669
(('prefix', 'key1'), 'data1', ((), )),
1670
(('prefix', 'key2'), 'data2', ((('prefix', 'key1'),),))])
1777
1671
# ask for many - get all
1778
self.assertEqual({(index, (b'key1', ), b'data1', ((),)),
1779
(index, (b'key2', ), b'data2', (((b'key1', ),),))},
1780
set(adapter.iter_entries([(b'key1', ), (b'key2', )])))
1672
self.assertEqual(set([(index, ('key1', ), 'data1', ((),)),
1673
(index, ('key2', ), 'data2', ((('key1', ),),))]),
1674
set(adapter.iter_entries([('key1', ), ('key2', )])))
1781
1675
# ask for one, get one
1782
self.assertEqual({(index, (b'key1', ), b'data1', ((),))},
1783
set(adapter.iter_entries([(b'key1', )])))
1676
self.assertEqual(set([(index, ('key1', ), 'data1', ((),))]),
1677
set(adapter.iter_entries([('key1', )])))
1784
1678
# ask for missing, get none
1785
1679
self.assertEqual(set(),
1786
set(adapter.iter_entries([(b'key3', )])))
1680
set(adapter.iter_entries([('key3', )])))
1788
1682
def test_iter_entries_prefix(self):
1789
1683
index, adapter = self.make_index(key_elements=3, nodes=[
1790
((b'notprefix', b'foo', b'key1'), b'data', ((), )),
1791
((b'prefix', b'prefix2', b'key1'), b'data1', ((), )),
1792
((b'prefix', b'prefix2', b'key2'), b'data2', (((b'prefix', b'prefix2', b'key1'),),))])
1684
(('notprefix', 'foo', 'key1'), 'data', ((), )),
1685
(('prefix', 'prefix2', 'key1'), 'data1', ((), )),
1686
(('prefix', 'prefix2', 'key2'), 'data2', ((('prefix', 'prefix2', 'key1'),),))])
1793
1687
# ask for a prefix, get the results for just that prefix, adjusted.
1794
self.assertEqual({(index, (b'prefix2', b'key1', ), b'data1', ((),)),
1795
(index, (b'prefix2', b'key2', ), b'data2', (((b'prefix2', b'key1', ),),))},
1796
set(adapter.iter_entries_prefix([(b'prefix2', None)])))
1688
self.assertEqual(set([(index, ('prefix2', 'key1', ), 'data1', ((),)),
1689
(index, ('prefix2', 'key2', ), 'data2', ((('prefix2', 'key1', ),),))]),
1690
set(adapter.iter_entries_prefix([('prefix2', None)])))
1798
1692
def test_key_count_no_matching_keys(self):
1799
1693
index, adapter = self.make_index(nodes=[
1800
((b'notprefix', b'key1'), b'data', ((), ))])
1694
(('notprefix', 'key1'), 'data', ((), ))])
1801
1695
self.assertEqual(0, adapter.key_count())
1803
1697
def test_key_count_some_keys(self):
1804
1698
index, adapter = self.make_index(nodes=[
1805
((b'notprefix', b'key1'), b'data', ((), )),
1806
((b'prefix', b'key1'), b'data1', ((), )),
1807
((b'prefix', b'key2'), b'data2', (((b'prefix', b'key1'),),))])
1699
(('notprefix', 'key1'), 'data', ((), )),
1700
(('prefix', 'key1'), 'data1', ((), )),
1701
(('prefix', 'key2'), 'data2', ((('prefix', 'key1'),),))])
1808
1702
self.assertEqual(2, adapter.key_count())
1810
1704
def test_validate(self):
1811
1705
index, adapter = self.make_index()
1814
1707
def validate():
1815
1708
calls.append('called')
1816
1709
index.validate = validate