/brz/remove-bazaar

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