/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to breezy/tests/test_index.py

  • Committer: Jelmer Vernooij
  • Date: 2020-03-22 01:35:14 UTC
  • mfrom: (7490.7.6 work)
  • mto: This revision was merged to the branch mainline in revision 7499.
  • Revision ID: jelmer@jelmer.uk-20200322013514-7vw1ntwho04rcuj3
merge lp:brz/3.1.

Show diffs side-by-side

added added

removed removed

Lines of Context:
31
31
    def test_bad_index_format_signature(self):
32
32
        error = _mod_index.BadIndexFormatSignature("foo", "bar")
33
33
        self.assertEqual("foo is not an index of type bar.",
34
 
            str(error))
 
34
                         str(error))
35
35
 
36
36
    def test_bad_index_data(self):
37
37
        error = _mod_index.BadIndexData("foo")
38
38
        self.assertEqual("Error in data for index foo.",
39
 
            str(error))
 
39
                         str(error))
40
40
 
41
41
    def test_bad_index_duplicate_key(self):
42
42
        error = _mod_index.BadIndexDuplicateKey("foo", "bar")
43
43
        self.assertEqual("The key 'foo' is already in index 'bar'.",
44
 
            str(error))
 
44
                         str(error))
45
45
 
46
46
    def test_bad_index_key(self):
47
47
        error = _mod_index.BadIndexKey("foo")
48
48
        self.assertEqual("The key 'foo' is not a valid key.",
49
 
            str(error))
 
49
                         str(error))
50
50
 
51
51
    def test_bad_index_options(self):
52
52
        error = _mod_index.BadIndexOptions("foo")
53
53
        self.assertEqual("Could not parse options for index foo.",
54
 
            str(error))
 
54
                         str(error))
55
55
 
56
56
    def test_bad_index_value(self):
57
57
        error = _mod_index.BadIndexValue("foo")
58
58
        self.assertEqual("The value 'foo' is not a valid value.",
59
 
            str(error))
 
59
                         str(error))
60
60
 
61
61
 
62
62
class TestGraphIndexBuilder(tests.TestCaseWithMemoryTransport):
66
66
        stream = builder.finish()
67
67
        contents = stream.read()
68
68
        self.assertEqual(
69
 
            "Bazaar Graph Index 1\nnode_ref_lists=0\nkey_elements=1\nlen=0\n\n",
 
69
            b"Bazaar Graph Index 1\nnode_ref_lists=0\nkey_elements=1\nlen=0\n\n",
70
70
            contents)
71
71
 
72
72
    def test_build_index_empty_two_element_keys(self):
74
74
        stream = builder.finish()
75
75
        contents = stream.read()
76
76
        self.assertEqual(
77
 
            "Bazaar Graph Index 1\nnode_ref_lists=0\nkey_elements=2\nlen=0\n\n",
 
77
            b"Bazaar Graph Index 1\nnode_ref_lists=0\nkey_elements=2\nlen=0\n\n",
78
78
            contents)
79
79
 
80
80
    def test_build_index_one_reference_list_empty(self):
82
82
        stream = builder.finish()
83
83
        contents = stream.read()
84
84
        self.assertEqual(
85
 
            "Bazaar Graph Index 1\nnode_ref_lists=1\nkey_elements=1\nlen=0\n\n",
 
85
            b"Bazaar Graph Index 1\nnode_ref_lists=1\nkey_elements=1\nlen=0\n\n",
86
86
            contents)
87
87
 
88
88
    def test_build_index_two_reference_list_empty(self):
90
90
        stream = builder.finish()
91
91
        contents = stream.read()
92
92
        self.assertEqual(
93
 
            "Bazaar Graph Index 1\nnode_ref_lists=2\nkey_elements=1\nlen=0\n\n",
 
93
            b"Bazaar Graph Index 1\nnode_ref_lists=2\nkey_elements=1\nlen=0\n\n",
94
94
            contents)
95
95
 
96
96
    def test_build_index_one_node_no_refs(self):
97
97
        builder = _mod_index.GraphIndexBuilder()
98
 
        builder.add_node(('akey', ), 'data')
 
98
        builder.add_node((b'akey', ), b'data')
99
99
        stream = builder.finish()
100
100
        contents = stream.read()
101
101
        self.assertEqual(
102
 
            "Bazaar Graph Index 1\nnode_ref_lists=0\nkey_elements=1\nlen=1\n"
103
 
            "akey\x00\x00\x00data\n\n", contents)
 
102
            b"Bazaar Graph Index 1\nnode_ref_lists=0\nkey_elements=1\nlen=1\n"
 
103
            b"akey\x00\x00\x00data\n\n", contents)
104
104
 
105
105
    def test_build_index_one_node_no_refs_accepts_empty_reflist(self):
106
106
        builder = _mod_index.GraphIndexBuilder()
107
 
        builder.add_node(('akey', ), 'data', ())
 
107
        builder.add_node((b'akey', ), b'data', ())
108
108
        stream = builder.finish()
109
109
        contents = stream.read()
110
110
        self.assertEqual(
111
 
            "Bazaar Graph Index 1\nnode_ref_lists=0\nkey_elements=1\nlen=1\n"
112
 
            "akey\x00\x00\x00data\n\n", contents)
 
111
            b"Bazaar Graph Index 1\nnode_ref_lists=0\nkey_elements=1\nlen=1\n"
 
112
            b"akey\x00\x00\x00data\n\n", contents)
113
113
 
114
114
    def test_build_index_one_node_2_element_keys(self):
115
115
        # multipart keys are separated by \x00 - because they are fixed length,
116
116
        # not variable this does not cause any issues, and seems clearer to the
117
117
        # author.
118
118
        builder = _mod_index.GraphIndexBuilder(key_elements=2)
119
 
        builder.add_node(('akey', 'secondpart'), 'data')
 
119
        builder.add_node((b'akey', b'secondpart'), b'data')
120
120
        stream = builder.finish()
121
121
        contents = stream.read()
122
122
        self.assertEqual(
123
 
            "Bazaar Graph Index 1\nnode_ref_lists=0\nkey_elements=2\nlen=1\n"
124
 
            "akey\x00secondpart\x00\x00\x00data\n\n", contents)
 
123
            b"Bazaar Graph Index 1\nnode_ref_lists=0\nkey_elements=2\nlen=1\n"
 
124
            b"akey\x00secondpart\x00\x00\x00data\n\n", contents)
125
125
 
126
126
    def test_add_node_empty_value(self):
127
127
        builder = _mod_index.GraphIndexBuilder()
128
 
        builder.add_node(('akey', ), '')
 
128
        builder.add_node((b'akey', ), b'')
129
129
        stream = builder.finish()
130
130
        contents = stream.read()
131
131
        self.assertEqual(
132
 
            "Bazaar Graph Index 1\nnode_ref_lists=0\nkey_elements=1\nlen=1\n"
133
 
            "akey\x00\x00\x00\n\n", contents)
 
132
            b"Bazaar Graph Index 1\nnode_ref_lists=0\nkey_elements=1\nlen=1\n"
 
133
            b"akey\x00\x00\x00\n\n", contents)
134
134
 
135
135
    def test_build_index_nodes_sorted(self):
136
136
        # the highest sorted node comes first.
138
138
        # use three to have a good chance of glitching dictionary hash
139
139
        # lookups etc. Insert in randomish order that is not correct
140
140
        # and not the reverse of the correct order.
141
 
        builder.add_node(('2002', ), 'data')
142
 
        builder.add_node(('2000', ), 'data')
143
 
        builder.add_node(('2001', ), 'data')
 
141
        builder.add_node((b'2002', ), b'data')
 
142
        builder.add_node((b'2000', ), b'data')
 
143
        builder.add_node((b'2001', ), b'data')
144
144
        stream = builder.finish()
145
145
        contents = stream.read()
146
146
        self.assertEqual(
147
 
            "Bazaar Graph Index 1\nnode_ref_lists=0\nkey_elements=1\nlen=3\n"
148
 
            "2000\x00\x00\x00data\n"
149
 
            "2001\x00\x00\x00data\n"
150
 
            "2002\x00\x00\x00data\n"
151
 
            "\n", contents)
 
147
            b"Bazaar Graph Index 1\nnode_ref_lists=0\nkey_elements=1\nlen=3\n"
 
148
            b"2000\x00\x00\x00data\n"
 
149
            b"2001\x00\x00\x00data\n"
 
150
            b"2002\x00\x00\x00data\n"
 
151
            b"\n", contents)
152
152
 
153
153
    def test_build_index_2_element_key_nodes_sorted(self):
154
154
        # multiple element keys are sorted first-key, second-key.
156
156
        # use three values of each key element, to have a good chance of
157
157
        # glitching dictionary hash lookups etc. Insert in randomish order that
158
158
        # is not correct and not the reverse of the correct order.
159
 
        builder.add_node(('2002', '2002'), 'data')
160
 
        builder.add_node(('2002', '2000'), 'data')
161
 
        builder.add_node(('2002', '2001'), 'data')
162
 
        builder.add_node(('2000', '2002'), 'data')
163
 
        builder.add_node(('2000', '2000'), 'data')
164
 
        builder.add_node(('2000', '2001'), 'data')
165
 
        builder.add_node(('2001', '2002'), 'data')
166
 
        builder.add_node(('2001', '2000'), 'data')
167
 
        builder.add_node(('2001', '2001'), 'data')
 
159
        builder.add_node((b'2002', b'2002'), b'data')
 
160
        builder.add_node((b'2002', b'2000'), b'data')
 
161
        builder.add_node((b'2002', b'2001'), b'data')
 
162
        builder.add_node((b'2000', b'2002'), b'data')
 
163
        builder.add_node((b'2000', b'2000'), b'data')
 
164
        builder.add_node((b'2000', b'2001'), b'data')
 
165
        builder.add_node((b'2001', b'2002'), b'data')
 
166
        builder.add_node((b'2001', b'2000'), b'data')
 
167
        builder.add_node((b'2001', b'2001'), b'data')
168
168
        stream = builder.finish()
169
169
        contents = stream.read()
170
170
        self.assertEqual(
171
 
            "Bazaar Graph Index 1\nnode_ref_lists=0\nkey_elements=2\nlen=9\n"
172
 
            "2000\x002000\x00\x00\x00data\n"
173
 
            "2000\x002001\x00\x00\x00data\n"
174
 
            "2000\x002002\x00\x00\x00data\n"
175
 
            "2001\x002000\x00\x00\x00data\n"
176
 
            "2001\x002001\x00\x00\x00data\n"
177
 
            "2001\x002002\x00\x00\x00data\n"
178
 
            "2002\x002000\x00\x00\x00data\n"
179
 
            "2002\x002001\x00\x00\x00data\n"
180
 
            "2002\x002002\x00\x00\x00data\n"
181
 
            "\n", contents)
 
171
            b"Bazaar Graph Index 1\nnode_ref_lists=0\nkey_elements=2\nlen=9\n"
 
172
            b"2000\x002000\x00\x00\x00data\n"
 
173
            b"2000\x002001\x00\x00\x00data\n"
 
174
            b"2000\x002002\x00\x00\x00data\n"
 
175
            b"2001\x002000\x00\x00\x00data\n"
 
176
            b"2001\x002001\x00\x00\x00data\n"
 
177
            b"2001\x002002\x00\x00\x00data\n"
 
178
            b"2002\x002000\x00\x00\x00data\n"
 
179
            b"2002\x002001\x00\x00\x00data\n"
 
180
            b"2002\x002002\x00\x00\x00data\n"
 
181
            b"\n", contents)
182
182
 
183
183
    def test_build_index_reference_lists_are_included_one(self):
184
184
        builder = _mod_index.GraphIndexBuilder(reference_lists=1)
185
 
        builder.add_node(('key', ), 'data', ([], ))
 
185
        builder.add_node((b'key', ), b'data', ([], ))
186
186
        stream = builder.finish()
187
187
        contents = stream.read()
188
188
        self.assertEqual(
189
 
            "Bazaar Graph Index 1\nnode_ref_lists=1\nkey_elements=1\nlen=1\n"
190
 
            "key\x00\x00\x00data\n"
191
 
            "\n", contents)
 
189
            b"Bazaar Graph Index 1\nnode_ref_lists=1\nkey_elements=1\nlen=1\n"
 
190
            b"key\x00\x00\x00data\n"
 
191
            b"\n", contents)
192
192
 
193
193
    def test_build_index_reference_lists_with_2_element_keys(self):
194
 
        builder = _mod_index.GraphIndexBuilder(reference_lists=1, key_elements=2)
195
 
        builder.add_node(('key', 'key2'), 'data', ([], ))
 
194
        builder = _mod_index.GraphIndexBuilder(
 
195
            reference_lists=1, key_elements=2)
 
196
        builder.add_node((b'key', b'key2'), b'data', ([], ))
196
197
        stream = builder.finish()
197
198
        contents = stream.read()
198
199
        self.assertEqual(
199
 
            "Bazaar Graph Index 1\nnode_ref_lists=1\nkey_elements=2\nlen=1\n"
200
 
            "key\x00key2\x00\x00\x00data\n"
201
 
            "\n", contents)
 
200
            b"Bazaar Graph Index 1\nnode_ref_lists=1\nkey_elements=2\nlen=1\n"
 
201
            b"key\x00key2\x00\x00\x00data\n"
 
202
            b"\n", contents)
202
203
 
203
204
    def test_build_index_reference_lists_are_included_two(self):
204
205
        builder = _mod_index.GraphIndexBuilder(reference_lists=2)
205
 
        builder.add_node(('key', ), 'data', ([], []))
 
206
        builder.add_node((b'key', ), b'data', ([], []))
206
207
        stream = builder.finish()
207
208
        contents = stream.read()
208
209
        self.assertEqual(
209
 
            "Bazaar Graph Index 1\nnode_ref_lists=2\nkey_elements=1\nlen=1\n"
210
 
            "key\x00\x00\t\x00data\n"
211
 
            "\n", contents)
 
210
            b"Bazaar Graph Index 1\nnode_ref_lists=2\nkey_elements=1\nlen=1\n"
 
211
            b"key\x00\x00\t\x00data\n"
 
212
            b"\n", contents)
212
213
 
213
214
    def test_clear_cache(self):
214
215
        builder = _mod_index.GraphIndexBuilder(reference_lists=2)
217
218
 
218
219
    def test_node_references_are_byte_offsets(self):
219
220
        builder = _mod_index.GraphIndexBuilder(reference_lists=1)
220
 
        builder.add_node(('reference', ), 'data', ([], ))
221
 
        builder.add_node(('key', ), 'data', ([('reference', )], ))
 
221
        builder.add_node((b'reference', ), b'data', ([], ))
 
222
        builder.add_node((b'key', ), b'data', ([(b'reference', )], ))
222
223
        stream = builder.finish()
223
224
        contents = stream.read()
224
225
        self.assertEqual(
225
 
            "Bazaar Graph Index 1\nnode_ref_lists=1\nkey_elements=1\nlen=2\n"
226
 
            "key\x00\x0072\x00data\n"
227
 
            "reference\x00\x00\x00data\n"
228
 
            "\n", contents)
 
226
            b"Bazaar Graph Index 1\nnode_ref_lists=1\nkey_elements=1\nlen=2\n"
 
227
            b"key\x00\x0072\x00data\n"
 
228
            b"reference\x00\x00\x00data\n"
 
229
            b"\n", contents)
229
230
 
230
231
    def test_node_references_are_cr_delimited(self):
231
232
        builder = _mod_index.GraphIndexBuilder(reference_lists=1)
232
 
        builder.add_node(('reference', ), 'data', ([], ))
233
 
        builder.add_node(('reference2', ), 'data', ([], ))
234
 
        builder.add_node(('key', ), 'data',
235
 
                         ([('reference', ), ('reference2', )], ))
 
233
        builder.add_node((b'reference', ), b'data', ([], ))
 
234
        builder.add_node((b'reference2', ), b'data', ([], ))
 
235
        builder.add_node((b'key', ), b'data',
 
236
                         ([(b'reference', ), (b'reference2', )], ))
236
237
        stream = builder.finish()
237
238
        contents = stream.read()
238
239
        self.assertEqual(
239
 
            "Bazaar Graph Index 1\nnode_ref_lists=1\nkey_elements=1\nlen=3\n"
240
 
            "key\x00\x00077\r094\x00data\n"
241
 
            "reference\x00\x00\x00data\n"
242
 
            "reference2\x00\x00\x00data\n"
243
 
            "\n", contents)
 
240
            b"Bazaar Graph Index 1\nnode_ref_lists=1\nkey_elements=1\nlen=3\n"
 
241
            b"key\x00\x00077\r094\x00data\n"
 
242
            b"reference\x00\x00\x00data\n"
 
243
            b"reference2\x00\x00\x00data\n"
 
244
            b"\n", contents)
244
245
 
245
246
    def test_multiple_reference_lists_are_tab_delimited(self):
246
247
        builder = _mod_index.GraphIndexBuilder(reference_lists=2)
247
 
        builder.add_node(('keference', ), 'data', ([], []))
248
 
        builder.add_node(('rey', ), 'data',
249
 
                         ([('keference', )], [('keference', )]))
 
248
        builder.add_node((b'keference', ), b'data', ([], []))
 
249
        builder.add_node((b'rey', ), b'data',
 
250
                         ([(b'keference', )], [(b'keference', )]))
250
251
        stream = builder.finish()
251
252
        contents = stream.read()
252
253
        self.assertEqual(
253
 
            "Bazaar Graph Index 1\nnode_ref_lists=2\nkey_elements=1\nlen=2\n"
254
 
            "keference\x00\x00\t\x00data\n"
255
 
            "rey\x00\x0059\t59\x00data\n"
256
 
            "\n", contents)
 
254
            b"Bazaar Graph Index 1\nnode_ref_lists=2\nkey_elements=1\nlen=2\n"
 
255
            b"keference\x00\x00\t\x00data\n"
 
256
            b"rey\x00\x0059\t59\x00data\n"
 
257
            b"\n", contents)
257
258
 
258
259
    def test_add_node_referencing_missing_key_makes_absent(self):
259
260
        builder = _mod_index.GraphIndexBuilder(reference_lists=1)
260
 
        builder.add_node(('rey', ), 'data',
261
 
                         ([('beference', ), ('aeference2', )], ))
 
261
        builder.add_node((b'rey', ), b'data',
 
262
                         ([(b'beference', ), (b'aeference2', )], ))
262
263
        stream = builder.finish()
263
264
        contents = stream.read()
264
265
        self.assertEqual(
265
 
            "Bazaar Graph Index 1\nnode_ref_lists=1\nkey_elements=1\nlen=1\n"
266
 
            "aeference2\x00a\x00\x00\n"
267
 
            "beference\x00a\x00\x00\n"
268
 
            "rey\x00\x00074\r059\x00data\n"
269
 
            "\n", contents)
 
266
            b"Bazaar Graph Index 1\nnode_ref_lists=1\nkey_elements=1\nlen=1\n"
 
267
            b"aeference2\x00a\x00\x00\n"
 
268
            b"beference\x00a\x00\x00\n"
 
269
            b"rey\x00\x00074\r059\x00data\n"
 
270
            b"\n", contents)
270
271
 
271
272
    def test_node_references_three_digits(self):
272
273
        # test the node digit expands as needed.
273
274
        builder = _mod_index.GraphIndexBuilder(reference_lists=1)
274
 
        references = [(str(val), ) for val in range(8, -1, -1)]
275
 
        builder.add_node(('2-key', ), '', (references, ))
 
275
        references = [((b"%d" % val), ) for val in range(8, -1, -1)]
 
276
        builder.add_node((b'2-key', ), b'', (references, ))
276
277
        stream = builder.finish()
277
278
        contents = stream.read()
278
279
        self.assertEqualDiff(
279
 
            "Bazaar Graph Index 1\nnode_ref_lists=1\nkey_elements=1\nlen=1\n"
280
 
            "0\x00a\x00\x00\n"
281
 
            "1\x00a\x00\x00\n"
282
 
            "2\x00a\x00\x00\n"
283
 
            "2-key\x00\x00151\r145\r139\r133\r127\r121\r071\r065\r059\x00\n"
284
 
            "3\x00a\x00\x00\n"
285
 
            "4\x00a\x00\x00\n"
286
 
            "5\x00a\x00\x00\n"
287
 
            "6\x00a\x00\x00\n"
288
 
            "7\x00a\x00\x00\n"
289
 
            "8\x00a\x00\x00\n"
290
 
            "\n", contents)
 
280
            b"Bazaar Graph Index 1\nnode_ref_lists=1\nkey_elements=1\nlen=1\n"
 
281
            b"0\x00a\x00\x00\n"
 
282
            b"1\x00a\x00\x00\n"
 
283
            b"2\x00a\x00\x00\n"
 
284
            b"2-key\x00\x00151\r145\r139\r133\r127\r121\r071\r065\r059\x00\n"
 
285
            b"3\x00a\x00\x00\n"
 
286
            b"4\x00a\x00\x00\n"
 
287
            b"5\x00a\x00\x00\n"
 
288
            b"6\x00a\x00\x00\n"
 
289
            b"7\x00a\x00\x00\n"
 
290
            b"8\x00a\x00\x00\n"
 
291
            b"\n", contents)
291
292
 
292
293
    def test_absent_has_no_reference_overhead(self):
293
294
        # the offsets after an absent record should be correct when there are
294
295
        # >1 reference lists.
295
296
        builder = _mod_index.GraphIndexBuilder(reference_lists=2)
296
 
        builder.add_node(('parent', ), '', ([('aail', ), ('zther', )], []))
 
297
        builder.add_node((b'parent', ), b'', ([(b'aail', ), (b'zther', )], []))
297
298
        stream = builder.finish()
298
299
        contents = stream.read()
299
300
        self.assertEqual(
300
 
            "Bazaar Graph Index 1\nnode_ref_lists=2\nkey_elements=1\nlen=1\n"
301
 
            "aail\x00a\x00\x00\n"
302
 
            "parent\x00\x0059\r84\t\x00\n"
303
 
            "zther\x00a\x00\x00\n"
304
 
            "\n", contents)
 
301
            b"Bazaar Graph Index 1\nnode_ref_lists=2\nkey_elements=1\nlen=1\n"
 
302
            b"aail\x00a\x00\x00\n"
 
303
            b"parent\x00\x0059\r84\t\x00\n"
 
304
            b"zther\x00a\x00\x00\n"
 
305
            b"\n", contents)
305
306
 
306
307
    def test_add_node_bad_key(self):
307
308
        builder = _mod_index.GraphIndexBuilder()
308
 
        for bad_char in '\t\n\x0b\x0c\r\x00 ':
 
309
        for bad_char in bytearray(b'\t\n\x0b\x0c\r\x00 '):
309
310
            self.assertRaises(_mod_index.BadIndexKey, builder.add_node,
310
 
                ('a%skey' % bad_char, ), 'data')
311
 
        self.assertRaises(_mod_index.BadIndexKey, builder.add_node,
312
 
                ('', ), 'data')
313
 
        self.assertRaises(_mod_index.BadIndexKey, builder.add_node,
314
 
                'not-a-tuple', 'data')
 
311
                              (b'a%skey' % bytes([bad_char]), ), b'data')
 
312
        self.assertRaises(_mod_index.BadIndexKey, builder.add_node,
 
313
                          (), b'data')
 
314
        self.assertRaises(_mod_index.BadIndexKey, builder.add_node,
 
315
                          b'not-a-tuple', b'data')
315
316
        # not enough length
316
317
        self.assertRaises(_mod_index.BadIndexKey, builder.add_node,
317
 
                (), 'data')
 
318
                          (), b'data')
318
319
        # too long
319
320
        self.assertRaises(_mod_index.BadIndexKey, builder.add_node,
320
 
                ('primary', 'secondary'), 'data')
 
321
                          (b'primary', b'secondary'), b'data')
321
322
        # secondary key elements get checked too:
322
323
        builder = _mod_index.GraphIndexBuilder(key_elements=2)
323
 
        for bad_char in '\t\n\x0b\x0c\r\x00 ':
 
324
        for bad_char in bytearray(b'\t\n\x0b\x0c\r\x00 '):
324
325
            self.assertRaises(_mod_index.BadIndexKey, builder.add_node,
325
 
                ('prefix', 'a%skey' % bad_char), 'data')
 
326
                              (b'prefix', b'a%skey' % bytes([bad_char])), b'data')
326
327
 
327
328
    def test_add_node_bad_data(self):
328
329
        builder = _mod_index.GraphIndexBuilder()
329
 
        self.assertRaises(_mod_index.BadIndexValue, builder.add_node, ('akey', ),
330
 
            'data\naa')
331
 
        self.assertRaises(_mod_index.BadIndexValue, builder.add_node, ('akey', ),
332
 
            'data\x00aa')
 
330
        self.assertRaises(_mod_index.BadIndexValue, builder.add_node, (b'akey', ),
 
331
                          b'data\naa')
 
332
        self.assertRaises(_mod_index.BadIndexValue, builder.add_node, (b'akey', ),
 
333
                          b'data\x00aa')
333
334
 
334
335
    def test_add_node_bad_mismatched_ref_lists_length(self):
335
336
        builder = _mod_index.GraphIndexBuilder()
336
 
        self.assertRaises(_mod_index.BadIndexValue, builder.add_node, ('akey', ),
337
 
            'data aa', ([], ))
 
337
        self.assertRaises(_mod_index.BadIndexValue, builder.add_node, (b'akey', ),
 
338
                          b'data aa', ([], ))
338
339
        builder = _mod_index.GraphIndexBuilder(reference_lists=1)
339
 
        self.assertRaises(_mod_index.BadIndexValue, builder.add_node, ('akey', ),
340
 
            'data aa')
341
 
        self.assertRaises(_mod_index.BadIndexValue, builder.add_node, ('akey', ),
342
 
            'data aa', (), )
343
 
        self.assertRaises(_mod_index.BadIndexValue, builder.add_node, ('akey', ),
344
 
            'data aa', ([], []))
 
340
        self.assertRaises(_mod_index.BadIndexValue, builder.add_node, (b'akey', ),
 
341
                          b'data aa')
 
342
        self.assertRaises(_mod_index.BadIndexValue, builder.add_node, (b'akey', ),
 
343
                          b'data aa', (), )
 
344
        self.assertRaises(_mod_index.BadIndexValue, builder.add_node, (b'akey', ),
 
345
                          b'data aa', ([], []))
345
346
        builder = _mod_index.GraphIndexBuilder(reference_lists=2)
346
 
        self.assertRaises(_mod_index.BadIndexValue, builder.add_node, ('akey', ),
347
 
            'data aa')
348
 
        self.assertRaises(_mod_index.BadIndexValue, builder.add_node, ('akey', ),
349
 
            'data aa', ([], ))
350
 
        self.assertRaises(_mod_index.BadIndexValue, builder.add_node, ('akey', ),
351
 
            'data aa', ([], [], []))
 
347
        self.assertRaises(_mod_index.BadIndexValue, builder.add_node, (b'akey', ),
 
348
                          b'data aa')
 
349
        self.assertRaises(_mod_index.BadIndexValue, builder.add_node, (b'akey', ),
 
350
                          b'data aa', ([], ))
 
351
        self.assertRaises(_mod_index.BadIndexValue, builder.add_node, (b'akey', ),
 
352
                          b'data aa', ([], [], []))
352
353
 
353
354
    def test_add_node_bad_key_in_reference_lists(self):
354
355
        # first list, first key - trivial
355
356
        builder = _mod_index.GraphIndexBuilder(reference_lists=1)
356
 
        self.assertRaises(_mod_index.BadIndexKey, builder.add_node, ('akey', ),
357
 
            'data aa', ([('a key', )], ))
 
357
        self.assertRaises(_mod_index.BadIndexKey, builder.add_node, (b'akey', ),
 
358
                          b'data aa', ([(b'a key', )], ))
358
359
        # references keys must be tuples too
359
 
        self.assertRaises(_mod_index.BadIndexKey, builder.add_node, ('akey', ),
360
 
            'data aa', (['not-a-tuple'], ))
 
360
        self.assertRaises(_mod_index.BadIndexKey, builder.add_node, (b'akey', ),
 
361
                          b'data aa', (['not-a-tuple'], ))
361
362
        # not enough length
362
 
        self.assertRaises(_mod_index.BadIndexKey, builder.add_node, ('akey', ),
363
 
            'data aa', ([()], ))
 
363
        self.assertRaises(_mod_index.BadIndexKey, builder.add_node, (b'akey', ),
 
364
                          b'data aa', ([()], ))
364
365
        # too long
365
 
        self.assertRaises(_mod_index.BadIndexKey, builder.add_node, ('akey', ),
366
 
            'data aa', ([('primary', 'secondary')], ))
 
366
        self.assertRaises(_mod_index.BadIndexKey, builder.add_node, (b'akey', ),
 
367
                          b'data aa', ([(b'primary', b'secondary')], ))
367
368
        # need to check more than the first key in the list
368
 
        self.assertRaises(_mod_index.BadIndexKey, builder.add_node, ('akey', ),
369
 
            'data aa', ([('agoodkey', ), ('that is a bad key', )], ))
 
369
        self.assertRaises(_mod_index.BadIndexKey, builder.add_node, (b'akey', ),
 
370
                          b'data aa', ([(b'agoodkey', ), (b'that is a bad key', )], ))
370
371
        # and if there is more than one list it should be getting checked
371
372
        # too
372
373
        builder = _mod_index.GraphIndexBuilder(reference_lists=2)
373
 
        self.assertRaises(_mod_index.BadIndexKey, builder.add_node, ('akey', ),
374
 
            'data aa', ([], ['a bad key']))
 
374
        self.assertRaises(_mod_index.BadIndexKey, builder.add_node, (b'akey', ),
 
375
                          b'data aa', ([], ['a bad key']))
375
376
 
376
377
    def test_add_duplicate_key(self):
377
378
        builder = _mod_index.GraphIndexBuilder()
378
 
        builder.add_node(('key', ), 'data')
 
379
        builder.add_node((b'key', ), b'data')
379
380
        self.assertRaises(_mod_index.BadIndexDuplicateKey,
380
 
                          builder.add_node, ('key', ), 'data')
 
381
                          builder.add_node, (b'key', ), b'data')
381
382
 
382
383
    def test_add_duplicate_key_2_elements(self):
383
384
        builder = _mod_index.GraphIndexBuilder(key_elements=2)
384
 
        builder.add_node(('key', 'key'), 'data')
 
385
        builder.add_node((b'key', b'key'), b'data')
385
386
        self.assertRaises(_mod_index.BadIndexDuplicateKey, builder.add_node,
386
 
            ('key', 'key'), 'data')
 
387
                          (b'key', b'key'), b'data')
387
388
 
388
389
    def test_add_key_after_referencing_key(self):
389
390
        builder = _mod_index.GraphIndexBuilder(reference_lists=1)
390
 
        builder.add_node(('key', ), 'data', ([('reference', )], ))
391
 
        builder.add_node(('reference', ), 'data', ([],))
 
391
        builder.add_node((b'key', ), b'data', ([(b'reference', )], ))
 
392
        builder.add_node((b'reference', ), b'data', ([],))
392
393
 
393
394
    def test_add_key_after_referencing_key_2_elements(self):
394
 
        builder = _mod_index.GraphIndexBuilder(reference_lists=1, key_elements=2)
395
 
        builder.add_node(('k', 'ey'), 'data', ([('reference', 'tokey')], ))
396
 
        builder.add_node(('reference', 'tokey'), 'data', ([],))
 
395
        builder = _mod_index.GraphIndexBuilder(
 
396
            reference_lists=1, key_elements=2)
 
397
        builder.add_node((b'k', b'ey'), b'data',
 
398
                         ([(b'reference', b'tokey')], ))
 
399
        builder.add_node((b'reference', b'tokey'), b'data', ([],))
397
400
 
398
401
    def test_set_optimize(self):
399
 
        builder = _mod_index.GraphIndexBuilder(reference_lists=1, key_elements=2)
 
402
        builder = _mod_index.GraphIndexBuilder(
 
403
            reference_lists=1, key_elements=2)
400
404
        builder.set_optimize(for_size=True)
401
405
        self.assertTrue(builder._optimize_for_size)
402
406
        builder.set_optimize(for_size=False)
406
410
class TestGraphIndex(tests.TestCaseWithMemoryTransport):
407
411
 
408
412
    def make_key(self, number):
409
 
        return (str(number) + 'X'*100,)
 
413
        return ((b'%d' % number) + b'X' * 100,)
410
414
 
411
415
    def make_value(self, number):
412
 
            return str(number) + 'Y'*100
 
416
        return (b'%d' % number) + b'Y' * 100
413
417
 
414
418
    def make_nodes(self, count=64):
415
419
        # generate a big enough index that we only read some of it on a typical
416
420
        # bisection lookup.
417
421
        nodes = []
418
422
        for counter in range(count):
419
 
            nodes.append((self.make_key(counter), self.make_value(counter), ()))
 
423
            nodes.append(
 
424
                (self.make_key(counter), self.make_value(counter), ()))
420
425
        return nodes
421
426
 
422
427
    def make_index(self, ref_lists=0, key_elements=1, nodes=[]):
423
 
        builder = _mod_index.GraphIndexBuilder(ref_lists, key_elements=key_elements)
 
428
        builder = _mod_index.GraphIndexBuilder(
 
429
            ref_lists, key_elements=key_elements)
424
430
        for key, value, references in nodes:
425
431
            builder.add_node(key, value, references)
426
432
        stream = builder.finish()
430
436
 
431
437
    def make_index_with_offset(self, ref_lists=0, key_elements=1, nodes=[],
432
438
                               offset=0):
433
 
        builder = _mod_index.GraphIndexBuilder(ref_lists, key_elements=key_elements)
 
439
        builder = _mod_index.GraphIndexBuilder(
 
440
            ref_lists, key_elements=key_elements)
434
441
        for key, value, references in nodes:
435
442
            builder.add_node(key, value, references)
436
443
        content = builder.finish().read()
437
444
        size = len(content)
438
445
        trans = self.get_transport()
439
 
        trans.put_bytes('index', (' '*offset) + content)
 
446
        trans.put_bytes('index', (b' ' * offset) + content)
440
447
        return _mod_index.GraphIndex(trans, 'index', size, offset=offset)
441
448
 
442
449
    def test_clear_cache(self):
447
454
 
448
455
    def test_open_bad_index_no_error(self):
449
456
        trans = self.get_transport()
450
 
        trans.put_bytes('name', "not an index\n")
 
457
        trans.put_bytes('name', b"not an index\n")
451
458
        idx = _mod_index.GraphIndex(trans, 'name', 13)
452
459
 
453
460
    def test_with_offset(self):
464
471
    def test_side_effect_buffering_with_offset(self):
465
472
        nodes = self.make_nodes(20)
466
473
        index = self.make_index_with_offset(offset=1234567, nodes=nodes)
467
 
        index._transport.recommended_page_size = lambda:64*1024
 
474
        index._transport.recommended_page_size = lambda: 64 * 1024
468
475
        subset_nodes = [nodes[0][0], nodes[10][0], nodes[19][0]]
469
476
        entries = [n[1] for n in index.iter_entries(subset_nodes)]
470
477
        self.assertEqual(sorted(subset_nodes), sorted(entries))
496
503
        # do a _lookup_keys_via_location call for the middle of the file, which
497
504
        # is what bisection uses.
498
505
        result = index._lookup_keys_via_location(
499
 
            [(index._size // 2, ('missing', ))])
 
506
            [(index._size // 2, (b'missing', ))])
500
507
        # this should have asked for a readv request, with adjust_for_latency,
501
508
        # and two regions: the header, and half-way into the file.
502
509
        self.assertEqual([
505
512
            index._transport._activity)
506
513
        # and the result should be that the key cannot be present, because this
507
514
        # is a trivial index.
508
 
        self.assertEqual([((index._size // 2, ('missing', )), False)],
509
 
            result)
 
515
        self.assertEqual([((index._size // 2, (b'missing', )), False)],
 
516
                         result)
510
517
        # And this should have caused the file to be fully buffered
511
518
        self.assertIsNot(None, index._nodes)
512
519
        self.assertEqual([], index._parsed_byte_map)
526
533
        # is what bisection uses.
527
534
        start_lookup = index._size // 2
528
535
        result = index._lookup_keys_via_location(
529
 
            [(start_lookup, ('40missing', ))])
 
536
            [(start_lookup, (b'40missing', ))])
530
537
        # this should have asked for a readv request, with adjust_for_latency,
531
538
        # and two regions: the header, and half-way into the file.
532
539
        self.assertEqual([
536
543
            index._transport._activity)
537
544
        # and the result should be that the key cannot be present, because this
538
545
        # is a trivial index.
539
 
        self.assertEqual([((start_lookup, ('40missing', )), False)],
540
 
            result)
 
546
        self.assertEqual([((start_lookup, (b'40missing', )), False)],
 
547
                         result)
541
548
        # And this should not have caused the file to be fully buffered
542
549
        self.assertIs(None, index._nodes)
543
550
        # And the regions of the file that have been parsed should be in the
544
551
        # parsed_byte_map and the parsed_key_map
545
552
        self.assertEqual([(0, 4008), (5046, 8996)], index._parsed_byte_map)
546
 
        self.assertEqual([(None, self.make_key(26)),
 
553
        self.assertEqual([((), self.make_key(26)),
547
554
                          (self.make_key(31), self.make_key(48))],
548
555
                         index._parsed_key_map)
549
556
 
550
557
    def test_parsing_non_adjacent_data_trims(self):
551
558
        index = self.make_index(nodes=self.make_nodes(64))
552
559
        result = index._lookup_keys_via_location(
553
 
            [(index._size // 2, ('40', ))])
 
560
            [(index._size // 2, (b'40', ))])
554
561
        # and the result should be that the key cannot be present, because key is
555
562
        # in the middle of the observed data from a 4K read - the smallest transport
556
563
        # will do today with this api.
557
 
        self.assertEqual([((index._size // 2, ('40', )), False)],
558
 
            result)
 
564
        self.assertEqual([((index._size // 2, (b'40', )), False)],
 
565
                         result)
559
566
        # and we should have a parse map that includes the header and the
560
567
        # region that was parsed after trimming.
561
568
        self.assertEqual([(0, 4008), (5046, 8996)], index._parsed_byte_map)
562
 
        self.assertEqual([(None, self.make_key(26)),
 
569
        self.assertEqual([((), self.make_key(26)),
563
570
                          (self.make_key(31), self.make_key(48))],
564
 
            index._parsed_key_map)
 
571
                         index._parsed_key_map)
565
572
 
566
573
    def test_parsing_data_handles_parsed_contained_regions(self):
567
574
        # the following patten creates a parsed region that is wholly within a
579
586
        # locations of both keys.
580
587
        index = self.make_index(nodes=self.make_nodes(128))
581
588
        result = index._lookup_keys_via_location(
582
 
            [(index._size // 2, ('40', ))])
 
589
            [(index._size // 2, (b'40', ))])
583
590
        # and we should have a parse map that includes the header and the
584
591
        # region that was parsed after trimming.
585
592
        self.assertEqual([(0, 4045), (11759, 15707)], index._parsed_byte_map)
586
 
        self.assertEqual([(None, self.make_key(116)),
 
593
        self.assertEqual([((), self.make_key(116)),
587
594
                          (self.make_key(35), self.make_key(51))],
588
 
            index._parsed_key_map)
 
595
                         index._parsed_key_map)
589
596
        # now ask for two keys, right before and after the parsed region
590
597
        result = index._lookup_keys_via_location(
591
598
            [(11450, self.make_key(34)), (15707, self.make_key(52))])
603
610
        # bisection lookup.
604
611
        index = self.make_index(nodes=self.make_nodes(64))
605
612
        # lookup the keys in the middle of the file
606
 
        result =index._lookup_keys_via_location(
607
 
            [(index._size // 2, ('40', ))])
 
613
        result = index._lookup_keys_via_location(
 
614
            [(index._size // 2, (b'40', ))])
608
615
        # check the parse map, this determines the test validity
609
616
        self.assertEqual([(0, 4008), (5046, 8996)], index._parsed_byte_map)
610
 
        self.assertEqual([(None, self.make_key(26)),
 
617
        self.assertEqual([((), self.make_key(26)),
611
618
                          (self.make_key(31), self.make_key(48))],
612
 
            index._parsed_key_map)
 
619
                         index._parsed_key_map)
613
620
        # reset the transport log
614
621
        del index._transport._activity[:]
615
622
        # now looking up a key in the portion of the file already parsed should
617
624
        # be in the index) - even when the byte location we ask for is outside
618
625
        # the parsed region
619
626
        result = index._lookup_keys_via_location(
620
 
            [(4000, ('40', ))])
621
 
        self.assertEqual([((4000, ('40', )), False)],
622
 
            result)
 
627
            [(4000, (b'40', ))])
 
628
        self.assertEqual([((4000, (b'40', )), False)],
 
629
                         result)
623
630
        self.assertEqual([], index._transport._activity)
624
631
 
625
632
    def test_lookup_present_key_answers_without_io_when_map_permits(self):
627
634
        # bisection lookup.
628
635
        index = self.make_index(nodes=self.make_nodes(64))
629
636
        # lookup the keys in the middle of the file
630
 
        result =index._lookup_keys_via_location(
631
 
            [(index._size // 2, ('40', ))])
 
637
        result = index._lookup_keys_via_location(
 
638
            [(index._size // 2, (b'40', ))])
632
639
        # check the parse map, this determines the test validity
633
640
        self.assertEqual([(0, 4008), (5046, 8996)], index._parsed_byte_map)
634
 
        self.assertEqual([(None, self.make_key(26)),
 
641
        self.assertEqual([((), self.make_key(26)),
635
642
                          (self.make_key(31), self.make_key(48))],
636
 
            index._parsed_key_map)
 
643
                         index._parsed_key_map)
637
644
        # reset the transport log
638
645
        del index._transport._activity[:]
639
646
        # now looking up a key in the portion of the file already parsed should
654
661
        index = self.make_index(nodes=self.make_nodes(64))
655
662
        # ask for the key in the middle, but a key that is located in the
656
663
        # unparsed region before the middle.
657
 
        result =index._lookup_keys_via_location(
658
 
            [(index._size // 2, ('30', ))])
 
664
        result = index._lookup_keys_via_location(
 
665
            [(index._size // 2, (b'30', ))])
659
666
        # check the parse map, this determines the test validity
660
667
        self.assertEqual([(0, 4008), (5046, 8996)], index._parsed_byte_map)
661
 
        self.assertEqual([(None, self.make_key(26)),
 
668
        self.assertEqual([((), self.make_key(26)),
662
669
                          (self.make_key(31), self.make_key(48))],
663
 
            index._parsed_key_map)
664
 
        self.assertEqual([((index._size // 2, ('30', )), -1)],
665
 
            result)
 
670
                         index._parsed_key_map)
 
671
        self.assertEqual([((index._size // 2, (b'30', )), -1)],
 
672
                         result)
666
673
 
667
674
    def test_lookup_key_above_probed_area(self):
668
675
        # generate a big enough index that we only read some of it on a typical
670
677
        index = self.make_index(nodes=self.make_nodes(64))
671
678
        # ask for the key in the middle, but a key that is located in the
672
679
        # unparsed region after the middle.
673
 
        result =index._lookup_keys_via_location(
674
 
            [(index._size // 2, ('50', ))])
 
680
        result = index._lookup_keys_via_location(
 
681
            [(index._size // 2, (b'50', ))])
675
682
        # check the parse map, this determines the test validity
676
683
        self.assertEqual([(0, 4008), (5046, 8996)], index._parsed_byte_map)
677
 
        self.assertEqual([(None, self.make_key(26)),
 
684
        self.assertEqual([((), self.make_key(26)),
678
685
                          (self.make_key(31), self.make_key(48))],
679
 
            index._parsed_key_map)
680
 
        self.assertEqual([((index._size // 2, ('50', )), +1)],
681
 
            result)
 
686
                         index._parsed_key_map)
 
687
        self.assertEqual([((index._size // 2, (b'50', )), +1)],
 
688
                         result)
682
689
 
683
690
    def test_lookup_key_resolves_references(self):
684
691
        # generate a big enough index that we only read some of it on a typical
686
693
        nodes = []
687
694
        for counter in range(99):
688
695
            nodes.append((self.make_key(counter), self.make_value(counter),
689
 
                ((self.make_key(counter + 20),),)  ))
 
696
                          ((self.make_key(counter + 20),),)))
690
697
        index = self.make_index(ref_lists=1, nodes=nodes)
691
698
        # lookup a key in the middle that does not exist, so that when we can
692
699
        # check that the referred-to-keys are not accessed automatically.
693
700
        index_size = index._size
694
701
        index_center = index_size // 2
695
702
        result = index._lookup_keys_via_location(
696
 
            [(index_center, ('40', ))])
 
703
            [(index_center, (b'40', ))])
697
704
        # check the parse map - only the start and middle should have been
698
705
        # parsed.
699
706
        self.assertEqual([(0, 4027), (10198, 14028)], index._parsed_byte_map)
700
 
        self.assertEqual([(None, self.make_key(17)),
 
707
        self.assertEqual([((), self.make_key(17)),
701
708
                          (self.make_key(44), self.make_key(5))],
702
 
            index._parsed_key_map)
 
709
                         index._parsed_key_map)
703
710
        # and check the transport activity likewise.
704
711
        self.assertEqual(
705
712
            [('readv', 'index', [(index_center, 800), (0, 200)], True,
706
 
                                  index_size)],
 
713
              index_size)],
707
714
            index._transport._activity)
708
715
        # reset the transport log for testing the reference lookup
709
716
        del index._transport._activity[:]
716
723
               ((self.make_key(65),),)))],
717
724
            result)
718
725
        self.assertEqual([('readv', 'index', [(15093, 800)], True, index_size)],
719
 
            index._transport._activity)
 
726
                         index._transport._activity)
720
727
 
721
728
    def test_lookup_key_can_buffer_all(self):
722
729
        nodes = []
723
730
        for counter in range(64):
724
731
            nodes.append((self.make_key(counter), self.make_value(counter),
725
 
                ((self.make_key(counter + 20),),)  ))
 
732
                          ((self.make_key(counter + 20),),)))
726
733
        index = self.make_index(ref_lists=1, nodes=nodes)
727
734
        # lookup a key in the middle that does not exist, so that when we can
728
735
        # check that the referred-to-keys are not accessed automatically.
729
736
        index_size = index._size
730
737
        index_center = index_size // 2
731
 
        result = index._lookup_keys_via_location([(index_center, ('40', ))])
 
738
        result = index._lookup_keys_via_location([(index_center, (b'40', ))])
732
739
        # check the parse map - only the start and middle should have been
733
740
        # parsed.
734
741
        self.assertEqual([(0, 3890), (6444, 10274)], index._parsed_byte_map)
735
 
        self.assertEqual([(None, self.make_key(25)),
 
742
        self.assertEqual([((), self.make_key(25)),
736
743
                          (self.make_key(37), self.make_key(52))],
737
 
            index._parsed_key_map)
 
744
                         index._parsed_key_map)
738
745
        # and check the transport activity likewise.
739
746
        self.assertEqual(
740
747
            [('readv', 'index', [(index_center, 800), (0, 200)], True,
741
 
                                  index_size)],
 
748
              index_size)],
742
749
            index._transport._activity)
743
750
        # reset the transport log for testing the reference lookup
744
751
        del index._transport._activity[:]
759
766
        self.assertEqual([], list(index.iter_all_entries()))
760
767
 
761
768
    def test_iter_all_entries_simple(self):
762
 
        index = self.make_index(nodes=[(('name', ), 'data', ())])
763
 
        self.assertEqual([(index, ('name', ), 'data')],
764
 
            list(index.iter_all_entries()))
 
769
        index = self.make_index(nodes=[((b'name', ), b'data', ())])
 
770
        self.assertEqual([(index, (b'name', ), b'data')],
 
771
                         list(index.iter_all_entries()))
765
772
 
766
773
    def test_iter_all_entries_simple_2_elements(self):
767
774
        index = self.make_index(key_elements=2,
768
 
            nodes=[(('name', 'surname'), 'data', ())])
769
 
        self.assertEqual([(index, ('name', 'surname'), 'data')],
770
 
            list(index.iter_all_entries()))
 
775
                                nodes=[((b'name', b'surname'), b'data', ())])
 
776
        self.assertEqual([(index, (b'name', b'surname'), b'data')],
 
777
                         list(index.iter_all_entries()))
771
778
 
772
779
    def test_iter_all_entries_references_resolved(self):
773
780
        index = self.make_index(1, nodes=[
774
 
            (('name', ), 'data', ([('ref', )], )),
775
 
            (('ref', ), 'refdata', ([], ))])
776
 
        self.assertEqual({(index, ('name', ), 'data', ((('ref',),),)),
777
 
            (index, ('ref', ), 'refdata', ((), ))},
778
 
            set(index.iter_all_entries()))
 
781
            ((b'name', ), b'data', ([(b'ref', )], )),
 
782
            ((b'ref', ), b'refdata', ([], ))])
 
783
        self.assertEqual({(index, (b'name', ), b'data', (((b'ref',),),)),
 
784
                          (index, (b'ref', ), b'refdata', ((), ))},
 
785
                         set(index.iter_all_entries()))
779
786
 
780
787
    def test_iter_entries_buffers_once(self):
781
788
        index = self.make_index(nodes=self.make_nodes(2))
821
828
 
822
829
    def test_iter_entries_references_resolved(self):
823
830
        index = self.make_index(1, nodes=[
824
 
            (('name', ), 'data', ([('ref', ), ('ref', )], )),
825
 
            (('ref', ), 'refdata', ([], ))])
826
 
        self.assertEqual({(index, ('name', ), 'data', ((('ref',), ('ref',)),)),
827
 
            (index, ('ref', ), 'refdata', ((), ))},
828
 
            set(index.iter_entries([('name',), ('ref',)])))
 
831
            ((b'name', ), b'data', ([(b'ref', ), (b'ref', )], )),
 
832
            ((b'ref', ), b'refdata', ([], ))])
 
833
        self.assertEqual({(index, (b'name', ), b'data', (((b'ref',), (b'ref',)),)),
 
834
                          (index, (b'ref', ), b'refdata', ((), ))},
 
835
                         set(index.iter_entries([(b'name',), (b'ref',)])))
829
836
 
830
837
    def test_iter_entries_references_2_refs_resolved(self):
831
838
        index = self.make_index(2, nodes=[
832
 
            (('name', ), 'data', ([('ref', )], [('ref', )])),
833
 
            (('ref', ), 'refdata', ([], []))])
834
 
        self.assertEqual({(index, ('name', ), 'data', ((('ref',),), (('ref',),))),
835
 
            (index, ('ref', ), 'refdata', ((), ()))},
836
 
            set(index.iter_entries([('name',), ('ref',)])))
 
839
            ((b'name', ), b'data', ([(b'ref', )], [(b'ref', )])),
 
840
            ((b'ref', ), b'refdata', ([], []))])
 
841
        self.assertEqual({(index, (b'name', ), b'data', (((b'ref',),), ((b'ref',),))),
 
842
                          (index, (b'ref', ), b'refdata', ((), ()))},
 
843
                         set(index.iter_entries([(b'name',), (b'ref',)])))
837
844
 
838
845
    def test_iteration_absent_skipped(self):
839
846
        index = self.make_index(1, nodes=[
840
 
            (('name', ), 'data', ([('ref', )], ))])
841
 
        self.assertEqual({(index, ('name', ), 'data', ((('ref',),),))},
842
 
            set(index.iter_all_entries()))
843
 
        self.assertEqual({(index, ('name', ), 'data', ((('ref',),),))},
844
 
            set(index.iter_entries([('name', )])))
845
 
        self.assertEqual([], list(index.iter_entries([('ref', )])))
 
847
            ((b'name', ), b'data', ([(b'ref', )], ))])
 
848
        self.assertEqual({(index, (b'name', ), b'data', (((b'ref',),),))},
 
849
                         set(index.iter_all_entries()))
 
850
        self.assertEqual({(index, (b'name', ), b'data', (((b'ref',),),))},
 
851
                         set(index.iter_entries([(b'name', )])))
 
852
        self.assertEqual([], list(index.iter_entries([(b'ref', )])))
846
853
 
847
854
    def test_iteration_absent_skipped_2_element_keys(self):
848
855
        index = self.make_index(1, key_elements=2, nodes=[
849
 
            (('name', 'fin'), 'data', ([('ref', 'erence')], ))])
850
 
        self.assertEqual({(index, ('name', 'fin'), 'data', ((('ref', 'erence'),),))},
851
 
            set(index.iter_all_entries()))
852
 
        self.assertEqual({(index, ('name', 'fin'), 'data', ((('ref', 'erence'),),))},
853
 
            set(index.iter_entries([('name', 'fin')])))
854
 
        self.assertEqual([], list(index.iter_entries([('ref', 'erence')])))
 
856
            ((b'name', b'fin'), b'data', ([(b'ref', b'erence')], ))])
 
857
        self.assertEqual([(index, (b'name', b'fin'), b'data', (((b'ref', b'erence'),),))],
 
858
                         list(index.iter_all_entries()))
 
859
        self.assertEqual([(index, (b'name', b'fin'), b'data', (((b'ref', b'erence'),),))],
 
860
                         list(index.iter_entries([(b'name', b'fin')])))
 
861
        self.assertEqual([], list(index.iter_entries([(b'ref', b'erence')])))
855
862
 
856
863
    def test_iter_all_keys(self):
857
864
        index = self.make_index(1, nodes=[
858
 
            (('name', ), 'data', ([('ref', )], )),
859
 
            (('ref', ), 'refdata', ([], ))])
860
 
        self.assertEqual({(index, ('name', ), 'data', ((('ref',),),)),
861
 
            (index, ('ref', ), 'refdata', ((), ))},
862
 
            set(index.iter_entries([('name', ), ('ref', )])))
 
865
            ((b'name', ), b'data', ([(b'ref', )], )),
 
866
            ((b'ref', ), b'refdata', ([], ))])
 
867
        self.assertEqual({(index, (b'name', ), b'data', (((b'ref',),),)),
 
868
                          (index, (b'ref', ), b'refdata', ((), ))},
 
869
                         set(index.iter_entries([(b'name', ), (b'ref', )])))
863
870
 
864
871
    def test_iter_nothing_empty(self):
865
872
        index = self.make_index()
867
874
 
868
875
    def test_iter_missing_entry_empty(self):
869
876
        index = self.make_index()
870
 
        self.assertEqual([], list(index.iter_entries([('a', )])))
 
877
        self.assertEqual([], list(index.iter_entries([(b'a', )])))
871
878
 
872
879
    def test_iter_missing_entry_empty_no_size(self):
873
880
        idx = self.make_index()
874
881
        idx = _mod_index.GraphIndex(idx._transport, 'index', None)
875
 
        self.assertEqual([], list(idx.iter_entries([('a', )])))
 
882
        self.assertEqual([], list(idx.iter_entries([(b'a', )])))
876
883
 
877
884
    def test_iter_key_prefix_1_element_key_None(self):
878
885
        index = self.make_index()
879
886
        self.assertRaises(_mod_index.BadIndexKey, list,
880
 
            index.iter_entries_prefix([(None, )]))
 
887
                          index.iter_entries_prefix([(None, )]))
881
888
 
882
889
    def test_iter_key_prefix_wrong_length(self):
883
890
        index = self.make_index()
884
891
        self.assertRaises(_mod_index.BadIndexKey, list,
885
 
            index.iter_entries_prefix([('foo', None)]))
 
892
                          index.iter_entries_prefix([(b'foo', None)]))
886
893
        index = self.make_index(key_elements=2)
887
894
        self.assertRaises(_mod_index.BadIndexKey, list,
888
 
            index.iter_entries_prefix([('foo', )]))
 
895
                          index.iter_entries_prefix([(b'foo', )]))
889
896
        self.assertRaises(_mod_index.BadIndexKey, list,
890
 
            index.iter_entries_prefix([('foo', None, None)]))
 
897
                          index.iter_entries_prefix([(b'foo', None, None)]))
891
898
 
892
899
    def test_iter_key_prefix_1_key_element_no_refs(self):
893
 
        index = self.make_index( nodes=[
894
 
            (('name', ), 'data', ()),
895
 
            (('ref', ), 'refdata', ())])
896
 
        self.assertEqual({(index, ('name', ), 'data'),
897
 
            (index, ('ref', ), 'refdata')},
898
 
            set(index.iter_entries_prefix([('name', ), ('ref', )])))
 
900
        index = self.make_index(nodes=[
 
901
            ((b'name', ), b'data', ()),
 
902
            ((b'ref', ), b'refdata', ())])
 
903
        self.assertEqual({(index, (b'name', ), b'data'),
 
904
                          (index, (b'ref', ), b'refdata')},
 
905
                         set(index.iter_entries_prefix([(b'name', ), (b'ref', )])))
899
906
 
900
907
    def test_iter_key_prefix_1_key_element_refs(self):
901
908
        index = self.make_index(1, nodes=[
902
 
            (('name', ), 'data', ([('ref', )], )),
903
 
            (('ref', ), 'refdata', ([], ))])
904
 
        self.assertEqual({(index, ('name', ), 'data', ((('ref',),),)),
905
 
            (index, ('ref', ), 'refdata', ((), ))},
906
 
            set(index.iter_entries_prefix([('name', ), ('ref', )])))
 
909
            ((b'name', ), b'data', ([(b'ref', )], )),
 
910
            ((b'ref', ), b'refdata', ([], ))])
 
911
        self.assertEqual({(index, (b'name', ), b'data', (((b'ref',),),)),
 
912
                          (index, (b'ref', ), b'refdata', ((), ))},
 
913
                         set(index.iter_entries_prefix([(b'name', ), (b'ref', )])))
907
914
 
908
915
    def test_iter_key_prefix_2_key_element_no_refs(self):
909
916
        index = self.make_index(key_elements=2, nodes=[
910
 
            (('name', 'fin1'), 'data', ()),
911
 
            (('name', 'fin2'), 'beta', ()),
912
 
            (('ref', 'erence'), 'refdata', ())])
913
 
        self.assertEqual({(index, ('name', 'fin1'), 'data'),
914
 
            (index, ('ref', 'erence'), 'refdata')},
915
 
            set(index.iter_entries_prefix([('name', 'fin1'), ('ref', 'erence')])))
916
 
        self.assertEqual({(index, ('name', 'fin1'), 'data'),
917
 
            (index, ('name', 'fin2'), 'beta')},
918
 
            set(index.iter_entries_prefix([('name', None)])))
 
917
            ((b'name', b'fin1'), b'data', ()),
 
918
            ((b'name', b'fin2'), b'beta', ()),
 
919
            ((b'ref', b'erence'), b'refdata', ())])
 
920
        self.assertEqual({(index, (b'name', b'fin1'), b'data'),
 
921
                          (index, (b'ref', b'erence'), b'refdata')},
 
922
                         set(index.iter_entries_prefix([(b'name', b'fin1'), (b'ref', b'erence')])))
 
923
        self.assertEqual({(index, (b'name', b'fin1'), b'data'),
 
924
                          (index, (b'name', b'fin2'), b'beta')},
 
925
                         set(index.iter_entries_prefix([(b'name', None)])))
919
926
 
920
927
    def test_iter_key_prefix_2_key_element_refs(self):
921
928
        index = self.make_index(1, key_elements=2, nodes=[
922
 
            (('name', 'fin1'), 'data', ([('ref', 'erence')], )),
923
 
            (('name', 'fin2'), 'beta', ([], )),
924
 
            (('ref', 'erence'), 'refdata', ([], ))])
925
 
        self.assertEqual({(index, ('name', 'fin1'), 'data', ((('ref', 'erence'),),)),
926
 
            (index, ('ref', 'erence'), 'refdata', ((), ))},
927
 
            set(index.iter_entries_prefix([('name', 'fin1'), ('ref', 'erence')])))
928
 
        self.assertEqual({(index, ('name', 'fin1'), 'data', ((('ref', 'erence'),),)),
929
 
            (index, ('name', 'fin2'), 'beta', ((), ))},
930
 
            set(index.iter_entries_prefix([('name', None)])))
 
929
            ((b'name', b'fin1'), b'data', ([(b'ref', b'erence')], )),
 
930
            ((b'name', b'fin2'), b'beta', ([], )),
 
931
            ((b'ref', b'erence'), b'refdata', ([], ))])
 
932
        self.assertEqual({(index, (b'name', b'fin1'), b'data', (((b'ref', b'erence'),),)),
 
933
                          (index, (b'ref', b'erence'), b'refdata', ((), ))},
 
934
                         set(index.iter_entries_prefix([(b'name', b'fin1'), (b'ref', b'erence')])))
 
935
        self.assertEqual({(index, (b'name', b'fin1'), b'data', (((b'ref', b'erence'),),)),
 
936
                          (index, (b'name', b'fin2'), b'beta', ((), ))},
 
937
                         set(index.iter_entries_prefix([(b'name', None)])))
931
938
 
932
939
    def test_key_count_empty(self):
933
940
        index = self.make_index()
934
941
        self.assertEqual(0, index.key_count())
935
942
 
936
943
    def test_key_count_one(self):
937
 
        index = self.make_index(nodes=[(('name', ), '', ())])
 
944
        index = self.make_index(nodes=[((b'name', ), b'', ())])
938
945
        self.assertEqual(1, index.key_count())
939
946
 
940
947
    def test_key_count_two(self):
941
948
        index = self.make_index(nodes=[
942
 
            (('name', ), '', ()), (('foo', ), '', ())])
 
949
            ((b'name', ), b'', ()), ((b'foo', ), b'', ())])
943
950
        self.assertEqual(2, index.key_count())
944
951
 
945
952
    def test_read_and_parse_tracks_real_read_value(self):
957
964
 
958
965
    def test_read_and_parse_triggers_buffer_all(self):
959
966
        index = self.make_index(key_elements=2, nodes=[
960
 
            (('name', 'fin1'), 'data', ()),
961
 
            (('name', 'fin2'), 'beta', ()),
962
 
            (('ref', 'erence'), 'refdata', ())])
 
967
            ((b'name', b'fin1'), b'data', ()),
 
968
            ((b'name', b'fin2'), b'beta', ()),
 
969
            ((b'ref', b'erence'), b'refdata', ())])
963
970
        self.assertTrue(index._size > 0)
964
971
        self.assertIs(None, index._nodes)
965
972
        index._read_and_parse([(0, index._size)])
967
974
 
968
975
    def test_validate_bad_index_errors(self):
969
976
        trans = self.get_transport()
970
 
        trans.put_bytes('name', "not an index\n")
 
977
        trans.put_bytes('name', b"not an index\n")
971
978
        idx = _mod_index.GraphIndex(trans, 'name', 13)
972
979
        self.assertRaises(_mod_index.BadIndexFormatSignature, idx.validate)
973
980
 
976
983
        trans = self.get_transport()
977
984
        content = trans.get_bytes('index')
978
985
        # change the options line to end with a rather than a parseable number
979
 
        new_content = content[:-2] + 'a\n\n'
 
986
        new_content = content[:-2] + b'a\n\n'
980
987
        trans.put_bytes('index', new_content)
981
988
        self.assertRaises(_mod_index.BadIndexOptions, idx.validate)
982
989
 
989
996
        self.assertRaises(_mod_index.BadIndexData, index.validate)
990
997
 
991
998
    def test_validate_missing_end_line_nonempty(self):
992
 
        index = self.make_index(2, nodes=[(('key', ), '', ([], []))])
 
999
        index = self.make_index(2, nodes=[((b'key', ), b'', ([], []))])
993
1000
        trans = self.get_transport()
994
1001
        content = trans.get_bytes('index')
995
1002
        # truncate the last byte
1001
1008
        index.validate()
1002
1009
 
1003
1010
    def test_validate_no_refs_content(self):
1004
 
        index = self.make_index(nodes=[(('key', ), 'value', ())])
 
1011
        index = self.make_index(nodes=[((b'key', ), b'value', ())])
1005
1012
        index.validate()
1006
1013
 
1007
1014
    # XXX: external_references tests are duplicated in test_btree_index.  We
1012
1019
 
1013
1020
    def test_external_references_no_results(self):
1014
1021
        index = self.make_index(ref_lists=1, nodes=[
1015
 
            (('key',), 'value', ([],))])
 
1022
            ((b'key',), b'value', ([],))])
1016
1023
        self.assertEqual(set(), index.external_references(0))
1017
1024
 
1018
1025
    def test_external_references_missing_ref(self):
1019
 
        missing_key = ('missing',)
 
1026
        missing_key = (b'missing',)
1020
1027
        index = self.make_index(ref_lists=1, nodes=[
1021
 
            (('key',), 'value', ([missing_key],))])
 
1028
            ((b'key',), b'value', ([missing_key],))])
1022
1029
        self.assertEqual({missing_key}, index.external_references(0))
1023
1030
 
1024
1031
    def test_external_references_multiple_ref_lists(self):
1025
 
        missing_key = ('missing',)
 
1032
        missing_key = (b'missing',)
1026
1033
        index = self.make_index(ref_lists=2, nodes=[
1027
 
            (('key',), 'value', ([], [missing_key]))])
 
1034
            ((b'key',), b'value', ([], [missing_key]))])
1028
1035
        self.assertEqual(set([]), index.external_references(0))
1029
1036
        self.assertEqual({missing_key}, index.external_references(1))
1030
1037
 
1031
1038
    def test_external_references_two_records(self):
1032
1039
        index = self.make_index(ref_lists=1, nodes=[
1033
 
            (('key-1',), 'value', ([('key-2',)],)),
1034
 
            (('key-2',), 'value', ([],)),
 
1040
            ((b'key-1',), b'value', ([(b'key-2',)],)),
 
1041
            ((b'key-2',), b'value', ([],)),
1035
1042
            ])
1036
1043
        self.assertEqual(set([]), index.external_references(0))
1037
1044
 
1038
1045
    def test__find_ancestors(self):
1039
 
        key1 = ('key-1',)
1040
 
        key2 = ('key-2',)
 
1046
        key1 = (b'key-1',)
 
1047
        key2 = (b'key-2',)
1041
1048
        index = self.make_index(ref_lists=1, key_elements=1, nodes=[
1042
 
            (key1, 'value', ([key2],)),
1043
 
            (key2, 'value', ([],)),
 
1049
            (key1, b'value', ([key2],)),
 
1050
            (key2, b'value', ([],)),
1044
1051
            ])
1045
1052
        parent_map = {}
1046
1053
        missing_keys = set()
1047
 
        search_keys = index._find_ancestors([key1], 0, parent_map, missing_keys)
 
1054
        search_keys = index._find_ancestors(
 
1055
            [key1], 0, parent_map, missing_keys)
1048
1056
        self.assertEqual({key1: (key2,)}, parent_map)
1049
1057
        self.assertEqual(set(), missing_keys)
1050
1058
        self.assertEqual({key2}, search_keys)
1055
1063
        self.assertEqual(set(), search_keys)
1056
1064
 
1057
1065
    def test__find_ancestors_w_missing(self):
1058
 
        key1 = ('key-1',)
1059
 
        key2 = ('key-2',)
1060
 
        key3 = ('key-3',)
 
1066
        key1 = (b'key-1',)
 
1067
        key2 = (b'key-2',)
 
1068
        key3 = (b'key-3',)
1061
1069
        index = self.make_index(ref_lists=1, key_elements=1, nodes=[
1062
 
            (key1, 'value', ([key2],)),
1063
 
            (key2, 'value', ([],)),
 
1070
            (key1, b'value', ([key2],)),
 
1071
            (key2, b'value', ([],)),
1064
1072
            ])
1065
1073
        parent_map = {}
1066
1074
        missing_keys = set()
1071
1079
        self.assertEqual(set(), search_keys)
1072
1080
 
1073
1081
    def test__find_ancestors_dont_search_known(self):
1074
 
        key1 = ('key-1',)
1075
 
        key2 = ('key-2',)
1076
 
        key3 = ('key-3',)
 
1082
        key1 = (b'key-1',)
 
1083
        key2 = (b'key-2',)
 
1084
        key3 = (b'key-3',)
1077
1085
        index = self.make_index(ref_lists=1, key_elements=1, nodes=[
1078
 
            (key1, 'value', ([key2],)),
1079
 
            (key2, 'value', ([key3],)),
1080
 
            (key3, 'value', ([],)),
 
1086
            (key1, b'value', ([key2],)),
 
1087
            (key2, b'value', ([key3],)),
 
1088
            (key3, b'value', ([],)),
1081
1089
            ])
1082
1090
        # We already know about key2, so we won't try to search for key3
1083
1091
        parent_map = {key2: (key3,)}
1101
1109
class TestCombinedGraphIndex(tests.TestCaseWithMemoryTransport):
1102
1110
 
1103
1111
    def make_index(self, name, ref_lists=0, key_elements=1, nodes=[]):
1104
 
        builder = _mod_index.GraphIndexBuilder(ref_lists, key_elements=key_elements)
 
1112
        builder = _mod_index.GraphIndexBuilder(
 
1113
            ref_lists, key_elements=key_elements)
1105
1114
        for key, value, references in nodes:
1106
1115
            builder.add_node(key, value, references)
1107
1116
        stream = builder.finish()
1119
1128
        :param missing: The underlying indexes to delete
1120
1129
        :return: (CombinedGraphIndex, reload_counter)
1121
1130
        """
1122
 
        idx1 = self.make_index('1', nodes=[(('1',), '', ())])
1123
 
        idx2 = self.make_index('2', nodes=[(('2',), '', ())])
 
1131
        idx1 = self.make_index('1', nodes=[((b'1',), b'', ())])
 
1132
        idx2 = self.make_index('2', nodes=[((b'2',), b'', ())])
1124
1133
        idx3 = self.make_index('3', nodes=[
1125
 
            (('1',), '', ()),
1126
 
            (('2',), '', ())])
 
1134
            ((b'1',), b'', ()),
 
1135
            ((b'2',), b'', ())])
1127
1136
 
1128
1137
        # total_reloads, num_changed, num_unchanged
1129
1138
        reload_counter = [0, 0, 0]
 
1139
 
1130
1140
        def reload():
1131
1141
            reload_counter[0] += 1
1132
1142
            new_indices = [idx3]
1149
1159
 
1150
1160
    def test_add_index(self):
1151
1161
        idx = _mod_index.CombinedGraphIndex([])
1152
 
        idx1 = self.make_index('name', 0, nodes=[(('key', ), '', ())])
 
1162
        idx1 = self.make_index('name', 0, nodes=[((b'key', ), b'', ())])
1153
1163
        idx.insert_index(0, idx1)
1154
 
        self.assertEqual([(idx1, ('key', ), '')],
 
1164
        self.assertEqual([(idx1, (b'key', ), b'')],
1155
1165
                         list(idx.iter_all_entries()))
1156
1166
 
1157
1167
    def test_clear_cache(self):
1170
1180
                return self._index.clear_cache()
1171
1181
 
1172
1182
        idx = _mod_index.CombinedGraphIndex([])
1173
 
        idx1 = self.make_index('name', 0, nodes=[(('key', ), '', ())])
 
1183
        idx1 = self.make_index('name', 0, nodes=[((b'key', ), b'', ())])
1174
1184
        idx.insert_index(0, ClearCacheProxy(idx1))
1175
 
        idx2 = self.make_index('name', 0, nodes=[(('key', ), '', ())])
 
1185
        idx2 = self.make_index('name', 0, nodes=[((b'key', ), b'', ())])
1176
1186
        idx.insert_index(1, ClearCacheProxy(idx2))
1177
1187
        # CombinedGraphIndex should call 'clear_cache()' on all children
1178
1188
        idx.clear_cache()
1188
1198
        self.assertEqual([], list(idx.iter_all_entries()))
1189
1199
 
1190
1200
    def test_iter_all_entries_simple(self):
1191
 
        idx1 = self.make_index('name', nodes=[(('name', ), 'data', ())])
 
1201
        idx1 = self.make_index('name', nodes=[((b'name', ), b'data', ())])
1192
1202
        idx = _mod_index.CombinedGraphIndex([idx1])
1193
 
        self.assertEqual([(idx1, ('name', ), 'data')],
1194
 
            list(idx.iter_all_entries()))
 
1203
        self.assertEqual([(idx1, (b'name', ), b'data')],
 
1204
                         list(idx.iter_all_entries()))
1195
1205
 
1196
1206
    def test_iter_all_entries_two_indices(self):
1197
 
        idx1 = self.make_index('name1', nodes=[(('name', ), 'data', ())])
1198
 
        idx2 = self.make_index('name2', nodes=[(('2', ), '', ())])
 
1207
        idx1 = self.make_index('name1', nodes=[((b'name', ), b'data', ())])
 
1208
        idx2 = self.make_index('name2', nodes=[((b'2', ), b'', ())])
1199
1209
        idx = _mod_index.CombinedGraphIndex([idx1, idx2])
1200
 
        self.assertEqual([(idx1, ('name', ), 'data'),
1201
 
                          (idx2, ('2', ), '')],
 
1210
        self.assertEqual([(idx1, (b'name', ), b'data'),
 
1211
                          (idx2, (b'2', ), b'')],
1202
1212
                         list(idx.iter_all_entries()))
1203
1213
 
1204
1214
    def test_iter_entries_two_indices_dup_key(self):
1205
 
        idx1 = self.make_index('name1', nodes=[(('name', ), 'data', ())])
1206
 
        idx2 = self.make_index('name2', nodes=[(('name', ), 'data', ())])
 
1215
        idx1 = self.make_index('name1', nodes=[((b'name', ), b'data', ())])
 
1216
        idx2 = self.make_index('name2', nodes=[((b'name', ), b'data', ())])
1207
1217
        idx = _mod_index.CombinedGraphIndex([idx1, idx2])
1208
 
        self.assertEqual([(idx1, ('name', ), 'data')],
1209
 
                         list(idx.iter_entries([('name', )])))
 
1218
        self.assertEqual([(idx1, (b'name', ), b'data')],
 
1219
                         list(idx.iter_entries([(b'name', )])))
1210
1220
 
1211
1221
    def test_iter_all_entries_two_indices_dup_key(self):
1212
 
        idx1 = self.make_index('name1', nodes=[(('name', ), 'data', ())])
1213
 
        idx2 = self.make_index('name2', nodes=[(('name', ), 'data', ())])
 
1222
        idx1 = self.make_index('name1', nodes=[((b'name', ), b'data', ())])
 
1223
        idx2 = self.make_index('name2', nodes=[((b'name', ), b'data', ())])
1214
1224
        idx = _mod_index.CombinedGraphIndex([idx1, idx2])
1215
 
        self.assertEqual([(idx1, ('name', ), 'data')],
 
1225
        self.assertEqual([(idx1, (b'name', ), b'data')],
1216
1226
                         list(idx.iter_all_entries()))
1217
1227
 
1218
1228
    def test_iter_key_prefix_2_key_element_refs(self):
1219
1229
        idx1 = self.make_index('1', 1, key_elements=2, nodes=[
1220
 
                (('name', 'fin1'), 'data', ([('ref', 'erence')], ))])
 
1230
            ((b'name', b'fin1'), b'data', ([(b'ref', b'erence')], ))])
1221
1231
        idx2 = self.make_index('2', 1, key_elements=2, nodes=[
1222
 
                (('name', 'fin2'), 'beta', ([], )),
1223
 
                (('ref', 'erence'), 'refdata', ([], ))])
 
1232
            ((b'name', b'fin2'), b'beta', ([], )),
 
1233
            ((b'ref', b'erence'), b'refdata', ([], ))])
1224
1234
        idx = _mod_index.CombinedGraphIndex([idx1, idx2])
1225
 
        self.assertEqual({(idx1, ('name', 'fin1'), 'data',
1226
 
                               ((('ref', 'erence'),),)),
1227
 
                              (idx2, ('ref', 'erence'), 'refdata', ((), ))},
1228
 
                         set(idx.iter_entries_prefix([('name', 'fin1'),
1229
 
                                                        ('ref', 'erence')])))
1230
 
        self.assertEqual({(idx1, ('name', 'fin1'), 'data',
1231
 
                               ((('ref', 'erence'),),)),
1232
 
                              (idx2, ('name', 'fin2'), 'beta', ((), ))},
1233
 
                         set(idx.iter_entries_prefix([('name', None)])))
 
1235
        self.assertEqual({(idx1, (b'name', b'fin1'), b'data',
 
1236
                           (((b'ref', b'erence'),),)),
 
1237
                          (idx2, (b'ref', b'erence'), b'refdata', ((), ))},
 
1238
                         set(idx.iter_entries_prefix([(b'name', b'fin1'),
 
1239
                                                      (b'ref', b'erence')])))
 
1240
        self.assertEqual({(idx1, (b'name', b'fin1'), b'data',
 
1241
                           (((b'ref', b'erence'),),)),
 
1242
                          (idx2, (b'name', b'fin2'), b'beta', ((), ))},
 
1243
                         set(idx.iter_entries_prefix([(b'name', None)])))
1234
1244
 
1235
1245
    def test_iter_nothing_empty(self):
1236
1246
        idx = _mod_index.CombinedGraphIndex([])
1242
1252
        self.assertEqual([], list(idx.iter_entries([])))
1243
1253
 
1244
1254
    def test_iter_all_keys(self):
1245
 
        idx1 = self.make_index('1', 1, nodes=[(('name', ), 'data',
1246
 
                                               ([('ref', )], ))])
1247
 
        idx2 = self.make_index('2', 1, nodes=[(('ref', ), 'refdata', ((), ))])
 
1255
        idx1 = self.make_index('1', 1, nodes=[((b'name', ), b'data',
 
1256
                                               ([(b'ref', )], ))])
 
1257
        idx2 = self.make_index(
 
1258
            '2', 1, nodes=[((b'ref', ), b'refdata', ((), ))])
1248
1259
        idx = _mod_index.CombinedGraphIndex([idx1, idx2])
1249
 
        self.assertEqual({(idx1, ('name', ), 'data', ((('ref', ), ), )),
1250
 
                              (idx2, ('ref', ), 'refdata', ((), ))},
1251
 
                         set(idx.iter_entries([('name', ), ('ref', )])))
 
1260
        self.assertEqual({(idx1, (b'name', ), b'data', (((b'ref', ), ), )),
 
1261
                          (idx2, (b'ref', ), b'refdata', ((), ))},
 
1262
                         set(idx.iter_entries([(b'name', ), (b'ref', )])))
1252
1263
 
1253
1264
    def test_iter_all_keys_dup_entry(self):
1254
 
        idx1 = self.make_index('1', 1, nodes=[(('name', ), 'data',
1255
 
                                                 ([('ref', )], )),
1256
 
                                                (('ref', ), 'refdata', ([], ))])
1257
 
        idx2 = self.make_index('2', 1, nodes=[(('ref', ), 'refdata', ([], ))])
 
1265
        idx1 = self.make_index('1', 1, nodes=[((b'name', ), b'data',
 
1266
                                               ([(b'ref', )], )),
 
1267
                                              ((b'ref', ), b'refdata', ([], ))])
 
1268
        idx2 = self.make_index(
 
1269
            '2', 1, nodes=[((b'ref', ), b'refdata', ([], ))])
1258
1270
        idx = _mod_index.CombinedGraphIndex([idx1, idx2])
1259
 
        self.assertEqual({(idx1, ('name', ), 'data', ((('ref',),),)),
1260
 
                              (idx1, ('ref', ), 'refdata', ((), ))},
1261
 
                         set(idx.iter_entries([('name', ), ('ref', )])))
 
1271
        self.assertEqual({(idx1, (b'name', ), b'data', (((b'ref',),),)),
 
1272
                          (idx1, (b'ref', ), b'refdata', ((), ))},
 
1273
                         set(idx.iter_entries([(b'name', ), (b'ref', )])))
1262
1274
 
1263
1275
    def test_iter_missing_entry_empty(self):
1264
1276
        idx = _mod_index.CombinedGraphIndex([])
1267
1279
    def test_iter_missing_entry_one_index(self):
1268
1280
        idx1 = self.make_index('1')
1269
1281
        idx = _mod_index.CombinedGraphIndex([idx1])
1270
 
        self.assertEqual([], list(idx.iter_entries([('a', )])))
 
1282
        self.assertEqual([], list(idx.iter_entries([(b'a', )])))
1271
1283
 
1272
1284
    def test_iter_missing_entry_two_index(self):
1273
1285
        idx1 = self.make_index('1')
1276
1288
        self.assertEqual([], list(idx.iter_entries([('a', )])))
1277
1289
 
1278
1290
    def test_iter_entry_present_one_index_only(self):
1279
 
        idx1 = self.make_index('1', nodes=[(('key', ), '', ())])
 
1291
        idx1 = self.make_index('1', nodes=[((b'key', ), b'', ())])
1280
1292
        idx2 = self.make_index('2', nodes=[])
1281
1293
        idx = _mod_index.CombinedGraphIndex([idx1, idx2])
1282
 
        self.assertEqual([(idx1, ('key', ), '')],
1283
 
                         list(idx.iter_entries([('key', )])))
 
1294
        self.assertEqual([(idx1, (b'key', ), b'')],
 
1295
                         list(idx.iter_entries([(b'key', )])))
1284
1296
        # and in the other direction
1285
1297
        idx = _mod_index.CombinedGraphIndex([idx2, idx1])
1286
 
        self.assertEqual([(idx1, ('key', ), '')],
1287
 
                         list(idx.iter_entries([('key', )])))
 
1298
        self.assertEqual([(idx1, (b'key', ), b'')],
 
1299
                         list(idx.iter_entries([(b'key', )])))
1288
1300
 
1289
1301
    def test_key_count_empty(self):
1290
1302
        idx1 = self.make_index('1', nodes=[])
1294
1306
 
1295
1307
    def test_key_count_sums_index_keys(self):
1296
1308
        idx1 = self.make_index('1', nodes=[
1297
 
            (('1',), '', ()),
1298
 
            (('2',), '', ())])
1299
 
        idx2 = self.make_index('2', nodes=[(('1',), '', ())])
 
1309
            ((b'1',), b'', ()),
 
1310
            ((b'2',), b'', ())])
 
1311
        idx2 = self.make_index('2', nodes=[((b'1',), b'', ())])
1300
1312
        idx = _mod_index.CombinedGraphIndex([idx1, idx2])
1301
1313
        self.assertEqual(3, idx.key_count())
1302
1314
 
1303
1315
    def test_validate_bad_child_index_errors(self):
1304
1316
        trans = self.get_transport()
1305
 
        trans.put_bytes('name', "not an index\n")
 
1317
        trans.put_bytes('name', b"not an index\n")
1306
1318
        idx1 = _mod_index.GraphIndex(trans, 'name', 13)
1307
1319
        idx = _mod_index.CombinedGraphIndex([idx1])
1308
1320
        self.assertRaises(_mod_index.BadIndexFormatSignature, idx.validate)
1333
1345
 
1334
1346
    def test_iter_entries_reloads(self):
1335
1347
        index, reload_counter = self.make_combined_index_with_missing()
1336
 
        result = list(index.iter_entries([('1',), ('2',), ('3',)]))
 
1348
        result = list(index.iter_entries([(b'1',), (b'2',), (b'3',)]))
1337
1349
        index3 = index._indices[0]
1338
 
        self.assertEqual([(index3, ('1',), ''), (index3, ('2',), '')],
1339
 
                         result)
 
1350
        self.assertEqual({(index3, (b'1',), b''), (index3, (b'2',), b'')},
 
1351
                         set(result))
1340
1352
        self.assertEqual([1, 1, 0], reload_counter)
1341
1353
 
1342
1354
    def test_iter_entries_reloads_midway(self):
1344
1356
        # through
1345
1357
        index, reload_counter = self.make_combined_index_with_missing(['2'])
1346
1358
        index1, index2 = index._indices
1347
 
        result = list(index.iter_entries([('1',), ('2',), ('3',)]))
 
1359
        result = list(index.iter_entries([(b'1',), (b'2',), (b'3',)]))
1348
1360
        index3 = index._indices[0]
1349
 
        # We had already yielded '1', so we just go on to the next, we should
1350
 
        # not yield '1' twice.
1351
 
        self.assertEqual([(index1, ('1',), ''), (index3, ('2',), '')],
 
1361
        # We had already yielded b'1', so we just go on to the next, we should
 
1362
        # not yield b'1' twice.
 
1363
        self.assertEqual([(index1, (b'1',), b''), (index3, (b'2',), b'')],
1352
1364
                         result)
1353
1365
        self.assertEqual([1, 1, 0], reload_counter)
1354
1366
 
1360
1372
 
1361
1373
    def test_iter_entries_reloads_and_fails(self):
1362
1374
        index, reload_counter = self.make_combined_index_with_missing(
1363
 
                                    ['1', '2', '3'])
 
1375
            ['1', '2', '3'])
1364
1376
        self.assertListRaises(errors.NoSuchFile, index.iter_entries, [('3',)])
1365
1377
        self.assertEqual([2, 1, 1], reload_counter)
1366
1378
 
1368
1380
        index, reload_counter = self.make_combined_index_with_missing()
1369
1381
        result = list(index.iter_all_entries())
1370
1382
        index3 = index._indices[0]
1371
 
        self.assertEqual([(index3, ('1',), ''), (index3, ('2',), '')],
1372
 
                         result)
 
1383
        self.assertEqual({(index3, (b'1',), b''), (index3, (b'2',), b'')},
 
1384
                         set(result))
1373
1385
        self.assertEqual([1, 1, 0], reload_counter)
1374
1386
 
1375
1387
    def test_iter_all_entries_reloads_midway(self):
1379
1391
        index3 = index._indices[0]
1380
1392
        # We had already yielded '1', so we just go on to the next, we should
1381
1393
        # not yield '1' twice.
1382
 
        self.assertEqual([(index1, ('1',), ''), (index3, ('2',), '')],
 
1394
        self.assertEqual([(index1, (b'1',), b''), (index3, (b'2',), b'')],
1383
1395
                         result)
1384
1396
        self.assertEqual([1, 1, 0], reload_counter)
1385
1397
 
1390
1402
 
1391
1403
    def test_iter_all_entries_reloads_and_fails(self):
1392
1404
        index, reload_counter = self.make_combined_index_with_missing(
1393
 
                                    ['1', '2', '3'])
 
1405
            ['1', '2', '3'])
1394
1406
        self.assertListRaises(errors.NoSuchFile, index.iter_all_entries)
1395
1407
 
1396
1408
    def test_iter_entries_prefix_reloads(self):
1397
1409
        index, reload_counter = self.make_combined_index_with_missing()
1398
 
        result = list(index.iter_entries_prefix([('1',)]))
 
1410
        result = list(index.iter_entries_prefix([(b'1',)]))
1399
1411
        index3 = index._indices[0]
1400
 
        self.assertEqual([(index3, ('1',), '')], result)
 
1412
        self.assertEqual([(index3, (b'1',), b'')], result)
1401
1413
        self.assertEqual([1, 1, 0], reload_counter)
1402
1414
 
1403
1415
    def test_iter_entries_prefix_reloads_midway(self):
1404
1416
        index, reload_counter = self.make_combined_index_with_missing(['2'])
1405
1417
        index1, index2 = index._indices
1406
 
        result = list(index.iter_entries_prefix([('1',)]))
 
1418
        result = list(index.iter_entries_prefix([(b'1',)]))
1407
1419
        index3 = index._indices[0]
1408
 
        # We had already yielded '1', so we just go on to the next, we should
1409
 
        # not yield '1' twice.
1410
 
        self.assertEqual([(index1, ('1',), '')], result)
 
1420
        # We had already yielded b'1', so we just go on to the next, we should
 
1421
        # not yield b'1' twice.
 
1422
        self.assertEqual([(index1, (b'1',), b'')], result)
1411
1423
        self.assertEqual([1, 1, 0], reload_counter)
1412
1424
 
1413
1425
    def test_iter_entries_prefix_no_reload(self):
1414
1426
        index, reload_counter = self.make_combined_index_with_missing()
1415
1427
        index._reload_func = None
1416
1428
        self.assertListRaises(errors.NoSuchFile, index.iter_entries_prefix,
1417
 
                                                 [('1',)])
 
1429
                              [(b'1',)])
1418
1430
 
1419
1431
    def test_iter_entries_prefix_reloads_and_fails(self):
1420
1432
        index, reload_counter = self.make_combined_index_with_missing(
1421
 
                                    ['1', '2', '3'])
 
1433
            ['1', '2', '3'])
1422
1434
        self.assertListRaises(errors.NoSuchFile, index.iter_entries_prefix,
1423
 
                                                 [('1',)])
1424
 
 
 
1435
                              [(b'1',)])
1425
1436
 
1426
1437
    def make_index_with_simple_nodes(self, name, num_nodes=1):
1427
1438
        """Make an index named after 'name', with keys named after 'name' too.
1429
1440
        Nodes will have a value of '' and no references.
1430
1441
        """
1431
1442
        nodes = [
1432
 
            (('index-%s-key-%s' % (name, n),), '', ())
1433
 
            for n in range(1, num_nodes+1)]
 
1443
            ((('index-%s-key-%s' % (name, n)).encode('ascii'),), b'', ())
 
1444
            for n in range(1, num_nodes + 1)]
1434
1445
        return self.make_index('index-%s' % name, 0, nodes=nodes)
1435
1446
 
1436
1447
    def test_reorder_after_iter_entries(self):
1437
1448
        # Four indices: [key1] in idx1, [key2,key3] in idx2, [] in idx3,
1438
1449
        # [key4] in idx4.
1439
1450
        idx = _mod_index.CombinedGraphIndex([])
1440
 
        idx.insert_index(0, self.make_index_with_simple_nodes('1'), '1')
1441
 
        idx.insert_index(1, self.make_index_with_simple_nodes('2'), '2')
1442
 
        idx.insert_index(2, self.make_index_with_simple_nodes('3'), '3')
1443
 
        idx.insert_index(3, self.make_index_with_simple_nodes('4'), '4')
 
1451
        idx.insert_index(0, self.make_index_with_simple_nodes('1'), b'1')
 
1452
        idx.insert_index(1, self.make_index_with_simple_nodes('2'), b'2')
 
1453
        idx.insert_index(2, self.make_index_with_simple_nodes('3'), b'3')
 
1454
        idx.insert_index(3, self.make_index_with_simple_nodes('4'), b'4')
1444
1455
        idx1, idx2, idx3, idx4 = idx._indices
1445
1456
        # Query a key from idx4 and idx2.
1446
1457
        self.assertLength(2, list(idx.iter_entries(
1447
 
            [('index-4-key-1',), ('index-2-key-1',)])))
 
1458
            [(b'index-4-key-1',), (b'index-2-key-1',)])))
1448
1459
        # Now idx2 and idx4 should be moved to the front (and idx1 should
1449
1460
        # still be before idx3).
1450
1461
        self.assertEqual([idx2, idx4, idx1, idx3], idx._indices)
1451
 
        self.assertEqual(['2', '4', '1', '3'], idx._index_names)
 
1462
        self.assertEqual([b'2', b'4', b'1', b'3'], idx._index_names)
1452
1463
 
1453
1464
    def test_reorder_propagates_to_siblings(self):
1454
1465
        # Two CombinedGraphIndex objects, with the same number of indicies with
1462
1473
        index2_1, index2_2 = cgi2._indices
1463
1474
        cgi1.set_sibling_indices([cgi2])
1464
1475
        # Trigger a reordering in cgi1.  cgi2 will be reordered as well.
1465
 
        list(cgi1.iter_entries([('index-1-2-key-1',)]))
 
1476
        list(cgi1.iter_entries([(b'index-1-2-key-1',)]))
1466
1477
        self.assertEqual([index2_2, index2_1], cgi2._indices)
1467
1478
        self.assertEqual(['two', 'one'], cgi2._index_names)
1468
1479
 
1486
1497
        self.assertRaises(errors.NoSuchFile, idx.validate)
1487
1498
 
1488
1499
    def test_find_ancestors_across_indexes(self):
1489
 
        key1 = ('key-1',)
1490
 
        key2 = ('key-2',)
1491
 
        key3 = ('key-3',)
1492
 
        key4 = ('key-4',)
 
1500
        key1 = (b'key-1',)
 
1501
        key2 = (b'key-2',)
 
1502
        key3 = (b'key-3',)
 
1503
        key4 = (b'key-4',)
1493
1504
        index1 = self.make_index('12', ref_lists=1, nodes=[
1494
 
            (key1, 'value', ([],)),
1495
 
            (key2, 'value', ([key1],)),
 
1505
            (key1, b'value', ([],)),
 
1506
            (key2, b'value', ([key1],)),
1496
1507
            ])
1497
1508
        index2 = self.make_index('34', ref_lists=1, nodes=[
1498
 
            (key3, 'value', ([key2],)),
1499
 
            (key4, 'value', ([key3],)),
 
1509
            (key3, b'value', ([key2],)),
 
1510
            (key4, b'value', ([key3],)),
1500
1511
            ])
1501
1512
        c_index = _mod_index.CombinedGraphIndex([index1, index2])
1502
1513
        parent_map, missing_keys = c_index.find_ancestry([key1], 0)
1510
1521
        self.assertEqual(set(), missing_keys)
1511
1522
 
1512
1523
    def test_find_ancestors_missing_keys(self):
1513
 
        key1 = ('key-1',)
1514
 
        key2 = ('key-2',)
1515
 
        key3 = ('key-3',)
1516
 
        key4 = ('key-4',)
 
1524
        key1 = (b'key-1',)
 
1525
        key2 = (b'key-2',)
 
1526
        key3 = (b'key-3',)
 
1527
        key4 = (b'key-4',)
1517
1528
        index1 = self.make_index('12', ref_lists=1, nodes=[
1518
 
            (key1, 'value', ([],)),
1519
 
            (key2, 'value', ([key1],)),
 
1529
            (key1, b'value', ([],)),
 
1530
            (key2, b'value', ([key1],)),
1520
1531
            ])
1521
1532
        index2 = self.make_index('34', ref_lists=1, nodes=[
1522
 
            (key3, 'value', ([key2],)),
 
1533
            (key3, b'value', ([key2],)),
1523
1534
            ])
1524
1535
        c_index = _mod_index.CombinedGraphIndex([index1, index2])
1525
1536
        # Searching for a key which is actually not present at all should
1530
1541
 
1531
1542
    def test_find_ancestors_no_indexes(self):
1532
1543
        c_index = _mod_index.CombinedGraphIndex([])
1533
 
        key1 = ('key-1',)
 
1544
        key1 = (b'key-1',)
1534
1545
        parent_map, missing_keys = c_index.find_ancestry([key1], 0)
1535
1546
        self.assertEqual({}, parent_map)
1536
1547
        self.assertEqual({key1}, missing_keys)
1537
1548
 
1538
1549
    def test_find_ancestors_ghost_parent(self):
1539
 
        key1 = ('key-1',)
1540
 
        key2 = ('key-2',)
1541
 
        key3 = ('key-3',)
1542
 
        key4 = ('key-4',)
 
1550
        key1 = (b'key-1',)
 
1551
        key2 = (b'key-2',)
 
1552
        key3 = (b'key-3',)
 
1553
        key4 = (b'key-4',)
1543
1554
        index1 = self.make_index('12', ref_lists=1, nodes=[
1544
 
            (key1, 'value', ([],)),
1545
 
            (key2, 'value', ([key1],)),
 
1555
            (key1, b'value', ([],)),
 
1556
            (key2, b'value', ([key1],)),
1546
1557
            ])
1547
1558
        index2 = self.make_index('34', ref_lists=1, nodes=[
1548
 
            (key4, 'value', ([key2, key3],)),
 
1559
            (key4, b'value', ([key2, key3],)),
1549
1560
            ])
1550
1561
        c_index = _mod_index.CombinedGraphIndex([index1, index2])
1551
1562
        # Searching for a key which is actually not present at all should
1559
1570
        idx = self.make_index('test', ref_lists=1, key_elements=1, nodes=[])
1560
1571
        parent_map = {}
1561
1572
        missing_keys = set()
1562
 
        search_keys = idx._find_ancestors([('one',), ('two',)], 0, parent_map,
 
1573
        search_keys = idx._find_ancestors([(b'one',), (b'two',)], 0, parent_map,
1563
1574
                                          missing_keys)
1564
1575
        self.assertEqual(set(), search_keys)
1565
1576
        self.assertEqual({}, parent_map)
1566
 
        self.assertEqual({('one',), ('two',)}, missing_keys)
 
1577
        self.assertEqual({(b'one',), (b'two',)}, missing_keys)
1567
1578
 
1568
1579
 
1569
1580
class TestInMemoryGraphIndex(tests.TestCaseWithMemoryTransport):
1570
1581
 
1571
1582
    def make_index(self, ref_lists=0, key_elements=1, nodes=[]):
1572
 
        result = _mod_index.InMemoryGraphIndex(ref_lists, key_elements=key_elements)
 
1583
        result = _mod_index.InMemoryGraphIndex(
 
1584
            ref_lists, key_elements=key_elements)
1573
1585
        result.add_nodes(nodes)
1574
1586
        return result
1575
1587
 
1576
1588
    def test_add_nodes_no_refs(self):
1577
1589
        index = self.make_index(0)
1578
 
        index.add_nodes([(('name', ), 'data')])
1579
 
        index.add_nodes([(('name2', ), ''), (('name3', ), '')])
 
1590
        index.add_nodes([((b'name', ), b'data')])
 
1591
        index.add_nodes([((b'name2', ), b''), ((b'name3', ), b'')])
1580
1592
        self.assertEqual({
1581
 
            (index, ('name', ), 'data'),
1582
 
            (index, ('name2', ), ''),
1583
 
            (index, ('name3', ), ''),
 
1593
            (index, (b'name', ), b'data'),
 
1594
            (index, (b'name2', ), b''),
 
1595
            (index, (b'name3', ), b''),
1584
1596
            }, set(index.iter_all_entries()))
1585
1597
 
1586
1598
    def test_add_nodes(self):
1587
1599
        index = self.make_index(1)
1588
 
        index.add_nodes([(('name', ), 'data', ([],))])
1589
 
        index.add_nodes([(('name2', ), '', ([],)), (('name3', ), '', ([('r', )],))])
 
1600
        index.add_nodes([((b'name', ), b'data', ([],))])
 
1601
        index.add_nodes([((b'name2', ), b'', ([],)),
 
1602
                         ((b'name3', ), b'', ([(b'r', )],))])
1590
1603
        self.assertEqual({
1591
 
            (index, ('name', ), 'data', ((),)),
1592
 
            (index, ('name2', ), '', ((),)),
1593
 
            (index, ('name3', ), '', ((('r', ), ), )),
 
1604
            (index, (b'name', ), b'data', ((),)),
 
1605
            (index, (b'name2', ), b'', ((),)),
 
1606
            (index, (b'name3', ), b'', (((b'r', ), ), )),
1594
1607
            }, set(index.iter_all_entries()))
1595
1608
 
1596
1609
    def test_iter_all_entries_empty(self):
1598
1611
        self.assertEqual([], list(index.iter_all_entries()))
1599
1612
 
1600
1613
    def test_iter_all_entries_simple(self):
1601
 
        index = self.make_index(nodes=[(('name', ), 'data')])
1602
 
        self.assertEqual([(index, ('name', ), 'data')],
1603
 
            list(index.iter_all_entries()))
 
1614
        index = self.make_index(nodes=[((b'name', ), b'data')])
 
1615
        self.assertEqual([(index, (b'name', ), b'data')],
 
1616
                         list(index.iter_all_entries()))
1604
1617
 
1605
1618
    def test_iter_all_entries_references(self):
1606
1619
        index = self.make_index(1, nodes=[
1607
 
            (('name', ), 'data', ([('ref', )], )),
1608
 
            (('ref', ), 'refdata', ([], ))])
1609
 
        self.assertEqual({(index, ('name', ), 'data', ((('ref', ),),)),
1610
 
            (index, ('ref', ), 'refdata', ((), ))},
1611
 
            set(index.iter_all_entries()))
 
1620
            ((b'name', ), b'data', ([(b'ref', )], )),
 
1621
            ((b'ref', ), b'refdata', ([], ))])
 
1622
        self.assertEqual({(index, (b'name', ), b'data', (((b'ref', ),),)),
 
1623
                          (index, (b'ref', ), b'refdata', ((), ))},
 
1624
                         set(index.iter_all_entries()))
1612
1625
 
1613
1626
    def test_iteration_absent_skipped(self):
1614
1627
        index = self.make_index(1, nodes=[
1615
 
            (('name', ), 'data', ([('ref', )], ))])
1616
 
        self.assertEqual({(index, ('name', ), 'data', ((('ref',),),))},
1617
 
            set(index.iter_all_entries()))
1618
 
        self.assertEqual({(index, ('name', ), 'data', ((('ref',),),))},
1619
 
            set(index.iter_entries([('name', )])))
1620
 
        self.assertEqual([], list(index.iter_entries([('ref', )])))
 
1628
            ((b'name', ), b'data', ([(b'ref', )], ))])
 
1629
        self.assertEqual({(index, (b'name', ), b'data', (((b'ref',),),))},
 
1630
                         set(index.iter_all_entries()))
 
1631
        self.assertEqual({(index, (b'name', ), b'data', (((b'ref',),),))},
 
1632
                         set(index.iter_entries([(b'name', )])))
 
1633
        self.assertEqual([], list(index.iter_entries([(b'ref', )])))
1621
1634
 
1622
1635
    def test_iter_all_keys(self):
1623
1636
        index = self.make_index(1, nodes=[
1624
 
            (('name', ), 'data', ([('ref', )], )),
1625
 
            (('ref', ), 'refdata', ([], ))])
1626
 
        self.assertEqual({(index, ('name', ), 'data', ((('ref',),),)),
1627
 
            (index, ('ref', ), 'refdata', ((), ))},
1628
 
            set(index.iter_entries([('name', ), ('ref', )])))
 
1637
            ((b'name', ), b'data', ([(b'ref', )], )),
 
1638
            ((b'ref', ), b'refdata', ([], ))])
 
1639
        self.assertEqual({(index, (b'name', ), b'data', (((b'ref',),),)),
 
1640
                          (index, (b'ref', ), b'refdata', ((), ))},
 
1641
                         set(index.iter_entries([(b'name', ), (b'ref', )])))
1629
1642
 
1630
1643
    def test_iter_key_prefix_1_key_element_no_refs(self):
1631
 
        index = self.make_index( nodes=[
1632
 
            (('name', ), 'data'),
1633
 
            (('ref', ), 'refdata')])
1634
 
        self.assertEqual({(index, ('name', ), 'data'),
1635
 
            (index, ('ref', ), 'refdata')},
1636
 
            set(index.iter_entries_prefix([('name', ), ('ref', )])))
 
1644
        index = self.make_index(nodes=[
 
1645
            ((b'name', ), b'data'),
 
1646
            ((b'ref', ), b'refdata')])
 
1647
        self.assertEqual({(index, (b'name', ), b'data'),
 
1648
                          (index, (b'ref', ), b'refdata')},
 
1649
                         set(index.iter_entries_prefix([(b'name', ), (b'ref', )])))
1637
1650
 
1638
1651
    def test_iter_key_prefix_1_key_element_refs(self):
1639
1652
        index = self.make_index(1, nodes=[
1640
 
            (('name', ), 'data', ([('ref', )], )),
1641
 
            (('ref', ), 'refdata', ([], ))])
1642
 
        self.assertEqual({(index, ('name', ), 'data', ((('ref',),),)),
1643
 
            (index, ('ref', ), 'refdata', ((), ))},
1644
 
            set(index.iter_entries_prefix([('name', ), ('ref', )])))
 
1653
            ((b'name', ), b'data', ([(b'ref', )], )),
 
1654
            ((b'ref', ), b'refdata', ([], ))])
 
1655
        self.assertEqual({(index, (b'name', ), b'data', (((b'ref',),),)),
 
1656
                          (index, (b'ref', ), b'refdata', ((), ))},
 
1657
                         set(index.iter_entries_prefix([(b'name', ), (b'ref', )])))
1645
1658
 
1646
1659
    def test_iter_key_prefix_2_key_element_no_refs(self):
1647
1660
        index = self.make_index(key_elements=2, nodes=[
1648
 
            (('name', 'fin1'), 'data'),
1649
 
            (('name', 'fin2'), 'beta'),
1650
 
            (('ref', 'erence'), 'refdata')])
1651
 
        self.assertEqual({(index, ('name', 'fin1'), 'data'),
1652
 
            (index, ('ref', 'erence'), 'refdata')},
1653
 
            set(index.iter_entries_prefix([('name', 'fin1'), ('ref', 'erence')])))
1654
 
        self.assertEqual({(index, ('name', 'fin1'), 'data'),
1655
 
            (index, ('name', 'fin2'), 'beta')},
1656
 
            set(index.iter_entries_prefix([('name', None)])))
 
1661
            ((b'name', b'fin1'), b'data'),
 
1662
            ((b'name', b'fin2'), b'beta'),
 
1663
            ((b'ref', b'erence'), b'refdata')])
 
1664
        self.assertEqual({(index, (b'name', b'fin1'), b'data'),
 
1665
                          (index, (b'ref', b'erence'), b'refdata')},
 
1666
                         set(index.iter_entries_prefix([(b'name', b'fin1'), (b'ref', b'erence')])))
 
1667
        self.assertEqual({(index, (b'name', b'fin1'), b'data'),
 
1668
                          (index, (b'name', b'fin2'), b'beta')},
 
1669
                         set(index.iter_entries_prefix([(b'name', None)])))
1657
1670
 
1658
1671
    def test_iter_key_prefix_2_key_element_refs(self):
1659
1672
        index = self.make_index(1, key_elements=2, nodes=[
1660
 
            (('name', 'fin1'), 'data', ([('ref', 'erence')], )),
1661
 
            (('name', 'fin2'), 'beta', ([], )),
1662
 
            (('ref', 'erence'), 'refdata', ([], ))])
1663
 
        self.assertEqual({(index, ('name', 'fin1'), 'data', ((('ref', 'erence'),),)),
1664
 
            (index, ('ref', 'erence'), 'refdata', ((), ))},
1665
 
            set(index.iter_entries_prefix([('name', 'fin1'), ('ref', 'erence')])))
1666
 
        self.assertEqual({(index, ('name', 'fin1'), 'data', ((('ref', 'erence'),),)),
1667
 
            (index, ('name', 'fin2'), 'beta', ((), ))},
1668
 
            set(index.iter_entries_prefix([('name', None)])))
 
1673
            ((b'name', b'fin1'), b'data', ([(b'ref', b'erence')], )),
 
1674
            ((b'name', b'fin2'), b'beta', ([], )),
 
1675
            ((b'ref', b'erence'), b'refdata', ([], ))])
 
1676
        self.assertEqual({(index, (b'name', b'fin1'), b'data', (((b'ref', b'erence'),),)),
 
1677
                          (index, (b'ref', b'erence'), b'refdata', ((), ))},
 
1678
                         set(index.iter_entries_prefix([(b'name', b'fin1'), (b'ref', b'erence')])))
 
1679
        self.assertEqual({(index, (b'name', b'fin1'), b'data', (((b'ref', b'erence'),),)),
 
1680
                          (index, (b'name', b'fin2'), b'beta', ((), ))},
 
1681
                         set(index.iter_entries_prefix([(b'name', None)])))
1669
1682
 
1670
1683
    def test_iter_nothing_empty(self):
1671
1684
        index = self.make_index()
1673
1686
 
1674
1687
    def test_iter_missing_entry_empty(self):
1675
1688
        index = self.make_index()
1676
 
        self.assertEqual([], list(index.iter_entries(['a'])))
 
1689
        self.assertEqual([], list(index.iter_entries([b'a'])))
1677
1690
 
1678
1691
    def test_key_count_empty(self):
1679
1692
        index = self.make_index()
1680
1693
        self.assertEqual(0, index.key_count())
1681
1694
 
1682
1695
    def test_key_count_one(self):
1683
 
        index = self.make_index(nodes=[(('name', ), '')])
 
1696
        index = self.make_index(nodes=[((b'name', ), b'')])
1684
1697
        self.assertEqual(1, index.key_count())
1685
1698
 
1686
1699
    def test_key_count_two(self):
1687
 
        index = self.make_index(nodes=[(('name', ), ''), (('foo', ), '')])
 
1700
        index = self.make_index(nodes=[((b'name', ), b''), ((b'foo', ), b'')])
1688
1701
        self.assertEqual(2, index.key_count())
1689
1702
 
1690
1703
    def test_validate_empty(self):
1692
1705
        index.validate()
1693
1706
 
1694
1707
    def test_validate_no_refs_content(self):
1695
 
        index = self.make_index(nodes=[(('key', ), 'value')])
 
1708
        index = self.make_index(nodes=[((b'key', ), b'value')])
1696
1709
        index.validate()
1697
1710
 
1698
1711
 
1700
1713
 
1701
1714
    def make_index(self, ref_lists=1, key_elements=2, nodes=[],
1702
1715
                   add_callback=False):
1703
 
        result = _mod_index.InMemoryGraphIndex(ref_lists, key_elements=key_elements)
 
1716
        result = _mod_index.InMemoryGraphIndex(
 
1717
            ref_lists, key_elements=key_elements)
1704
1718
        result.add_nodes(nodes)
1705
1719
        if add_callback:
1706
1720
            add_nodes_callback = result.add_nodes
1707
1721
        else:
1708
1722
            add_nodes_callback = None
1709
1723
        adapter = _mod_index.GraphIndexPrefixAdapter(
1710
 
            result, ('prefix', ), key_elements - 1,
 
1724
            result, (b'prefix', ), key_elements - 1,
1711
1725
            add_nodes_callback=add_nodes_callback)
1712
1726
        return result, adapter
1713
1727
 
1714
1728
    def test_add_node(self):
1715
1729
        index, adapter = self.make_index(add_callback=True)
1716
 
        adapter.add_node(('key',), 'value', ((('ref',),),))
1717
 
        self.assertEqual({(index, ('prefix', 'key'), 'value',
1718
 
                               ((('prefix', 'ref'),),))},
1719
 
            set(index.iter_all_entries()))
 
1730
        adapter.add_node((b'key',), b'value', (((b'ref',),),))
 
1731
        self.assertEqual({(index, (b'prefix', b'key'), b'value',
 
1732
                           (((b'prefix', b'ref'),),))},
 
1733
                         set(index.iter_all_entries()))
1720
1734
 
1721
1735
    def test_add_nodes(self):
1722
1736
        index, adapter = self.make_index(add_callback=True)
1723
1737
        adapter.add_nodes((
1724
 
            (('key',), 'value', ((('ref',),),)),
1725
 
            (('key2',), 'value2', ((),)),
 
1738
            ((b'key',), b'value', (((b'ref',),),)),
 
1739
            ((b'key2',), b'value2', ((),)),
1726
1740
            ))
1727
1741
        self.assertEqual({
1728
 
            (index, ('prefix', 'key2'), 'value2', ((),)),
1729
 
            (index, ('prefix', 'key'), 'value', ((('prefix', 'ref'),),))
 
1742
            (index, (b'prefix', b'key2'), b'value2', ((),)),
 
1743
            (index, (b'prefix', b'key'), b'value', (((b'prefix', b'ref'),),))
1730
1744
            },
1731
1745
            set(index.iter_all_entries()))
1732
1746
 
1733
1747
    def test_construct(self):
1734
1748
        idx = _mod_index.InMemoryGraphIndex()
1735
 
        adapter = _mod_index.GraphIndexPrefixAdapter(idx, ('prefix', ), 1)
 
1749
        adapter = _mod_index.GraphIndexPrefixAdapter(idx, (b'prefix', ), 1)
1736
1750
 
1737
1751
    def test_construct_with_callback(self):
1738
1752
        idx = _mod_index.InMemoryGraphIndex()
1739
 
        adapter = _mod_index.GraphIndexPrefixAdapter(idx, ('prefix', ), 1,
1740
 
                                                idx.add_nodes)
 
1753
        adapter = _mod_index.GraphIndexPrefixAdapter(idx, (b'prefix', ), 1,
 
1754
                                                     idx.add_nodes)
1741
1755
 
1742
1756
    def test_iter_all_entries_cross_prefix_map_errors(self):
1743
1757
        index, adapter = self.make_index(nodes=[
1744
 
            (('prefix', 'key1'), 'data1', ((('prefixaltered', 'key2'),),))])
1745
 
        self.assertRaises(_mod_index.BadIndexData, list, adapter.iter_all_entries())
 
1758
            ((b'prefix', b'key1'), b'data1', (((b'prefixaltered', b'key2'),),))])
 
1759
        self.assertRaises(_mod_index.BadIndexData, list,
 
1760
                          adapter.iter_all_entries())
1746
1761
 
1747
1762
    def test_iter_all_entries(self):
1748
1763
        index, adapter = self.make_index(nodes=[
1749
 
            (('notprefix', 'key1'), 'data', ((), )),
1750
 
            (('prefix', 'key1'), 'data1', ((), )),
1751
 
            (('prefix', 'key2'), 'data2', ((('prefix', 'key1'),),))])
1752
 
        self.assertEqual({(index, ('key1', ), 'data1', ((),)),
1753
 
            (index, ('key2', ), 'data2', ((('key1',),),))},
1754
 
            set(adapter.iter_all_entries()))
 
1764
            ((b'notprefix', b'key1'), b'data', ((), )),
 
1765
            ((b'prefix', b'key1'), b'data1', ((), )),
 
1766
            ((b'prefix', b'key2'), b'data2', (((b'prefix', b'key1'),),))])
 
1767
        self.assertEqual({(index, (b'key1', ), b'data1', ((),)),
 
1768
                          (index, (b'key2', ), b'data2', (((b'key1',),),))},
 
1769
                         set(adapter.iter_all_entries()))
1755
1770
 
1756
1771
    def test_iter_entries(self):
1757
1772
        index, adapter = self.make_index(nodes=[
1758
 
            (('notprefix', 'key1'), 'data', ((), )),
1759
 
            (('prefix', 'key1'), 'data1', ((), )),
1760
 
            (('prefix', 'key2'), 'data2', ((('prefix', 'key1'),),))])
 
1773
            ((b'notprefix', b'key1'), b'data', ((), )),
 
1774
            ((b'prefix', b'key1'), b'data1', ((), )),
 
1775
            ((b'prefix', b'key2'), b'data2', (((b'prefix', b'key1'),),))])
1761
1776
        # ask for many - get all
1762
 
        self.assertEqual({(index, ('key1', ), 'data1', ((),)),
1763
 
            (index, ('key2', ), 'data2', ((('key1', ),),))},
1764
 
            set(adapter.iter_entries([('key1', ), ('key2', )])))
 
1777
        self.assertEqual({(index, (b'key1', ), b'data1', ((),)),
 
1778
                          (index, (b'key2', ), b'data2', (((b'key1', ),),))},
 
1779
                         set(adapter.iter_entries([(b'key1', ), (b'key2', )])))
1765
1780
        # ask for one, get one
1766
 
        self.assertEqual({(index, ('key1', ), 'data1', ((),))},
1767
 
            set(adapter.iter_entries([('key1', )])))
 
1781
        self.assertEqual({(index, (b'key1', ), b'data1', ((),))},
 
1782
                         set(adapter.iter_entries([(b'key1', )])))
1768
1783
        # ask for missing, get none
1769
1784
        self.assertEqual(set(),
1770
 
            set(adapter.iter_entries([('key3', )])))
 
1785
                         set(adapter.iter_entries([(b'key3', )])))
1771
1786
 
1772
1787
    def test_iter_entries_prefix(self):
1773
1788
        index, adapter = self.make_index(key_elements=3, nodes=[
1774
 
            (('notprefix', 'foo', 'key1'), 'data', ((), )),
1775
 
            (('prefix', 'prefix2', 'key1'), 'data1', ((), )),
1776
 
            (('prefix', 'prefix2', 'key2'), 'data2', ((('prefix', 'prefix2', 'key1'),),))])
 
1789
            ((b'notprefix', b'foo', b'key1'), b'data', ((), )),
 
1790
            ((b'prefix', b'prefix2', b'key1'), b'data1', ((), )),
 
1791
            ((b'prefix', b'prefix2', b'key2'), b'data2', (((b'prefix', b'prefix2', b'key1'),),))])
1777
1792
        # ask for a prefix, get the results for just that prefix, adjusted.
1778
 
        self.assertEqual({(index, ('prefix2', 'key1', ), 'data1', ((),)),
1779
 
            (index, ('prefix2', 'key2', ), 'data2', ((('prefix2', 'key1', ),),))},
1780
 
            set(adapter.iter_entries_prefix([('prefix2', None)])))
 
1793
        self.assertEqual({(index, (b'prefix2', b'key1', ), b'data1', ((),)),
 
1794
                          (index, (b'prefix2', b'key2', ), b'data2', (((b'prefix2', b'key1', ),),))},
 
1795
                         set(adapter.iter_entries_prefix([(b'prefix2', None)])))
1781
1796
 
1782
1797
    def test_key_count_no_matching_keys(self):
1783
1798
        index, adapter = self.make_index(nodes=[
1784
 
            (('notprefix', 'key1'), 'data', ((), ))])
 
1799
            ((b'notprefix', b'key1'), b'data', ((), ))])
1785
1800
        self.assertEqual(0, adapter.key_count())
1786
1801
 
1787
1802
    def test_key_count_some_keys(self):
1788
1803
        index, adapter = self.make_index(nodes=[
1789
 
            (('notprefix', 'key1'), 'data', ((), )),
1790
 
            (('prefix', 'key1'), 'data1', ((), )),
1791
 
            (('prefix', 'key2'), 'data2', ((('prefix', 'key1'),),))])
 
1804
            ((b'notprefix', b'key1'), b'data', ((), )),
 
1805
            ((b'prefix', b'key1'), b'data1', ((), )),
 
1806
            ((b'prefix', b'key2'), b'data2', (((b'prefix', b'key1'),),))])
1792
1807
        self.assertEqual(2, adapter.key_count())
1793
1808
 
1794
1809
    def test_validate(self):
1795
1810
        index, adapter = self.make_index()
1796
1811
        calls = []
 
1812
 
1797
1813
        def validate():
1798
1814
            calls.append('called')
1799
1815
        index.validate = validate