122
134
TestBytesRecordReader. This test is here to ensure that
123
135
ContainerReader's integration with BytesRecordReader is working.
125
input = StringIO("bzr pack format 1\nB5\n\naaaaaE")
126
reader = pack.ContainerReader(input.read)
137
reader = self.get_reader_for("Bazaar pack format 1\nB5\n\naaaaaE")
127
138
expected_records = [([], 'aaaaa')]
128
self.assertEqual(expected_records, list(reader.iter_records()))
141
[(names, read_bytes(None))
142
for (names, read_bytes) in reader.iter_records()])
144
def test_validate_empty_container(self):
145
"""validate does not raise an error for a container with no records."""
146
reader = self.get_reader_for("Bazaar pack format 1\nE")
147
# No exception raised
150
def test_validate_non_empty_valid_container(self):
151
"""validate does not raise an error for a container with a valid record.
153
reader = self.get_reader_for("Bazaar pack format 1\nB3\nname\n\nabcE")
154
# No exception raised
157
def test_validate_bad_format(self):
158
"""validate raises an error for unrecognised format strings.
160
It may raise either UnexpectedEndOfContainerError or
161
UnknownContainerFormatError, depending on exactly what the string is.
163
inputs = ["", "x", "Bazaar pack format 1", "bad\n"]
165
reader = self.get_reader_for(input)
167
(errors.UnexpectedEndOfContainerError,
168
errors.UnknownContainerFormatError),
171
def test_validate_bad_record_marker(self):
172
"""validate raises UnknownRecordTypeError for unrecognised record
175
reader = self.get_reader_for("Bazaar pack format 1\nX")
176
self.assertRaises(errors.UnknownRecordTypeError, reader.validate)
178
def test_validate_data_after_end_marker(self):
179
"""validate raises ContainerHasExcessDataError if there are any bytes
180
after the end of the container.
182
reader = self.get_reader_for("Bazaar pack format 1\nEcrud")
184
errors.ContainerHasExcessDataError, reader.validate)
186
def test_validate_no_end_marker(self):
187
"""validate raises UnexpectedEndOfContainerError if there's no end of
188
container marker, even if the container up to this point has been valid.
190
reader = self.get_reader_for("Bazaar pack format 1\n")
192
errors.UnexpectedEndOfContainerError, reader.validate)
194
def test_validate_duplicate_name(self):
195
"""validate raises DuplicateRecordNameError if the same name occurs
196
multiple times in the container.
198
reader = self.get_reader_for(
199
"Bazaar pack format 1\n"
203
self.assertRaises(errors.DuplicateRecordNameError, reader.validate)
205
def test_validate_undecodeable_name(self):
206
"""Names that aren't valid UTF-8 cause validate to fail."""
207
reader = self.get_reader_for("Bazaar pack format 1\nB0\n\xcc\n\nE")
208
self.assertRaises(errors.InvalidRecordError, reader.validate)
131
211
class TestBytesRecordReader(tests.TestCase):
132
"""Tests for parsing Bytes records with BytesRecordReader."""
212
"""Tests for reading and validating Bytes records with BytesRecordReader."""
214
def get_reader_for(self, bytes):
215
stream = StringIO(bytes)
216
reader = pack.BytesRecordReader(stream.read)
134
219
def test_record_with_no_name(self):
135
220
"""Reading a Bytes record with no name returns an empty list of
138
input = StringIO("5\n\naaaaa")
139
reader = pack.BytesRecordReader(input.read)
140
names, bytes = reader.read()
223
reader = self.get_reader_for("5\n\naaaaa")
224
names, get_bytes = reader.read()
141
225
self.assertEqual([], names)
142
self.assertEqual('aaaaa', bytes)
226
self.assertEqual('aaaaa', get_bytes(None))
144
228
def test_record_with_one_name(self):
145
229
"""Reading a Bytes record with one name returns a list of just that
148
input = StringIO("5\nname1\n\naaaaa")
149
reader = pack.BytesRecordReader(input.read)
150
names, bytes = reader.read()
232
reader = self.get_reader_for("5\nname1\n\naaaaa")
233
names, get_bytes = reader.read()
151
234
self.assertEqual(['name1'], names)
152
self.assertEqual('aaaaa', bytes)
235
self.assertEqual('aaaaa', get_bytes(None))
154
237
def test_record_with_two_names(self):
155
238
"""Reading a Bytes record with two names returns a list of both names.
157
input = StringIO("5\nname1\nname2\n\naaaaa")
158
reader = pack.BytesRecordReader(input.read)
159
names, bytes = reader.read()
240
reader = self.get_reader_for("5\nname1\nname2\n\naaaaa")
241
names, get_bytes = reader.read()
160
242
self.assertEqual(['name1', 'name2'], names)
161
self.assertEqual('aaaaa', bytes)
243
self.assertEqual('aaaaa', get_bytes(None))
163
245
def test_invalid_length(self):
164
246
"""If the length-prefix is not a number, parsing raises
165
247
InvalidRecordError.
167
input = StringIO("not a number\n")
168
reader = pack.BytesRecordReader(input.read)
249
reader = self.get_reader_for("not a number\n")
169
250
self.assertRaises(errors.InvalidRecordError, reader.read)
171
252
def test_early_eof(self):
181
262
complete_record = "6\nname\n\nabcdef"
182
263
for count in range(0, len(complete_record)):
183
input = StringIO(complete_record[:count])
184
reader = pack.BytesRecordReader(input.read)
185
# We don't use assertRaises to make diagnosing failures easier.
264
incomplete_record = complete_record[:count]
265
reader = self.get_reader_for(incomplete_record)
266
# We don't use assertRaises to make diagnosing failures easier
267
# (assertRaises doesn't allow a custom failure message).
269
names, read_bytes = reader.read()
188
271
except errors.UnexpectedEndOfContainerError:
192
275
"UnexpectedEndOfContainerError not raised when parsing %r"
193
% (input.getvalue()))
276
% (incomplete_record,))
195
def test_initial(self):
278
def test_initial_eof(self):
196
279
"""EOF before any bytes read at all."""
198
reader = pack.BytesRecordReader(input.read)
280
reader = self.get_reader_for("")
199
281
self.assertRaises(errors.UnexpectedEndOfContainerError, reader.read)
201
def test_after_length(self):
283
def test_eof_after_length(self):
202
284
"""EOF after reading the length and before reading name(s)."""
203
input = StringIO("123\n")
204
reader = pack.BytesRecordReader(input.read)
285
reader = self.get_reader_for("123\n")
205
286
self.assertRaises(errors.UnexpectedEndOfContainerError, reader.read)
207
def test_during_name(self):
288
def test_eof_during_name(self):
208
289
"""EOF during reading a name."""
209
input = StringIO("123\nname")
210
reader = pack.BytesRecordReader(input.read)
290
reader = self.get_reader_for("123\nname")
211
291
self.assertRaises(errors.UnexpectedEndOfContainerError, reader.read)
214
# Other Bytes record parsing cases to test:
215
# - incomplete bytes (i.e. stream ends before $length bytes read)
216
# - _read_line encountering end of stream (at any time; during length,
217
# names, end of headers...)
293
def test_read_invalid_name_whitespace(self):
294
"""Names must have no whitespace."""
295
# A name with a space.
296
reader = self.get_reader_for("0\nbad name\n\n")
297
self.assertRaises(errors.InvalidRecordError, reader.read)
300
reader = self.get_reader_for("0\nbad\tname\n\n")
301
self.assertRaises(errors.InvalidRecordError, reader.read)
303
# A name with a vertical tab.
304
reader = self.get_reader_for("0\nbad\vname\n\n")
305
self.assertRaises(errors.InvalidRecordError, reader.read)
307
def test_validate_whitespace_in_name(self):
308
"""Names must have no whitespace."""
309
reader = self.get_reader_for("0\nbad name\n\n")
310
self.assertRaises(errors.InvalidRecordError, reader.validate)
312
def test_validate_interrupted_prelude(self):
313
"""EOF during reading a record's prelude causes validate to fail."""
314
reader = self.get_reader_for("")
316
errors.UnexpectedEndOfContainerError, reader.validate)
318
def test_validate_interrupted_body(self):
319
"""EOF during reading a record's body causes validate to fail."""
320
reader = self.get_reader_for("1\n\n")
322
errors.UnexpectedEndOfContainerError, reader.validate)
324
def test_validate_unparseable_length(self):
325
"""An unparseable record length causes validate to fail."""
326
reader = self.get_reader_for("\n\n")
328
errors.InvalidRecordError, reader.validate)
330
def test_validate_undecodeable_name(self):
331
"""Names that aren't valid UTF-8 cause validate to fail."""
332
reader = self.get_reader_for("0\n\xcc\n\n")
333
self.assertRaises(errors.InvalidRecordError, reader.validate)
335
def test_read_max_length(self):
336
"""If the max_length passed to the callable returned by read is not
337
None, then no more than that many bytes will be read.
339
reader = self.get_reader_for("6\n\nabcdef")
340
names, get_bytes = reader.read()
341
self.assertEqual('abc', get_bytes(3))
343
def test_read_no_max_length(self):
344
"""If the max_length passed to the callable returned by read is None,
345
then all the bytes in the record will be read.
347
reader = self.get_reader_for("6\n\nabcdef")
348
names, get_bytes = reader.read()
349
self.assertEqual('abcdef', get_bytes(None))
351
def test_repeated_read_calls(self):
352
"""Repeated calls to the callable returned from BytesRecordReader.read
353
will not read beyond the end of the record.
355
reader = self.get_reader_for("6\n\nabcdefB3\nnext-record\nXXX")
356
names, get_bytes = reader.read()
357
self.assertEqual('abcdef', get_bytes(None))
358
self.assertEqual('', get_bytes(None))
359
self.assertEqual('', get_bytes(99))