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