/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
2506.2.1 by Andrew Bennetts
Start implementing container format reading and writing.
1
# Copyright (C) 2007 Canonical Ltd
2
#
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
2506.3.1 by Andrew Bennetts
More progress:
17
"""Tests for bzrlib.pack."""
2506.2.1 by Andrew Bennetts
Start implementing container format reading and writing.
18
19
20
from cStringIO import StringIO
21
2506.3.2 by Andrew Bennetts
Test docstring tweaks, inspired by looking over the output of jml's testdoc tool.
22
from bzrlib import pack, errors, tests
23
24
25
class TestContainerWriter(tests.TestCase):
2506.2.1 by Andrew Bennetts
Start implementing container format reading and writing.
26
27
    def test_construct(self):
28
        """Test constructing a ContainerWriter.
29
        
30
        This uses None as the output stream to show that the constructor doesn't
31
        try to use the output stream.
32
        """
2506.3.1 by Andrew Bennetts
More progress:
33
        writer = pack.ContainerWriter(None)
2506.2.1 by Andrew Bennetts
Start implementing container format reading and writing.
34
35
    def test_begin(self):
2506.3.2 by Andrew Bennetts
Test docstring tweaks, inspired by looking over the output of jml's testdoc tool.
36
        """The begin() method writes the container format marker line."""
2506.2.1 by Andrew Bennetts
Start implementing container format reading and writing.
37
        output = StringIO()
2506.3.1 by Andrew Bennetts
More progress:
38
        writer = pack.ContainerWriter(output.write)
2506.2.1 by Andrew Bennetts
Start implementing container format reading and writing.
39
        writer.begin()
2506.5.3 by Andrew Bennetts
Change format marker to use the word 'Bazaar' rather than 'bzr'.
40
        self.assertEqual('Bazaar pack format 1\n', output.getvalue())
2506.2.1 by Andrew Bennetts
Start implementing container format reading and writing.
41
42
    def test_end(self):
2506.3.2 by Andrew Bennetts
Test docstring tweaks, inspired by looking over the output of jml's testdoc tool.
43
        """The end() method writes an End Marker record."""
2506.2.1 by Andrew Bennetts
Start implementing container format reading and writing.
44
        output = StringIO()
2506.3.1 by Andrew Bennetts
More progress:
45
        writer = pack.ContainerWriter(output.write)
2506.2.1 by Andrew Bennetts
Start implementing container format reading and writing.
46
        writer.begin()
47
        writer.end()
2506.5.3 by Andrew Bennetts
Change format marker to use the word 'Bazaar' rather than 'bzr'.
48
        self.assertEqual('Bazaar pack format 1\nE', output.getvalue())
2506.2.1 by Andrew Bennetts
Start implementing container format reading and writing.
49
50
    def test_add_bytes_record_no_name(self):
51
        """Add a bytes record with no name."""
52
        output = StringIO()
2506.3.1 by Andrew Bennetts
More progress:
53
        writer = pack.ContainerWriter(output.write)
2506.2.1 by Andrew Bennetts
Start implementing container format reading and writing.
54
        writer.begin()
55
        writer.add_bytes_record('abc', names=[])
2506.5.3 by Andrew Bennetts
Change format marker to use the word 'Bazaar' rather than 'bzr'.
56
        self.assertEqual('Bazaar pack format 1\nB3\n\nabc', output.getvalue())
2506.2.1 by Andrew Bennetts
Start implementing container format reading and writing.
57
58
    def test_add_bytes_record_one_name(self):
59
        """Add a bytes record with one name."""
60
        output = StringIO()
2506.3.1 by Andrew Bennetts
More progress:
61
        writer = pack.ContainerWriter(output.write)
2506.2.1 by Andrew Bennetts
Start implementing container format reading and writing.
62
        writer.begin()
63
        writer.add_bytes_record('abc', names=['name1'])
2506.5.3 by Andrew Bennetts
Change format marker to use the word 'Bazaar' rather than 'bzr'.
64
        self.assertEqual('Bazaar pack format 1\nB3\nname1\n\nabc',
2506.2.1 by Andrew Bennetts
Start implementing container format reading and writing.
65
                         output.getvalue())
66
67
    def test_add_bytes_record_two_names(self):
68
        """Add a bytes record with two names."""
69
        output = StringIO()
2506.3.1 by Andrew Bennetts
More progress:
70
        writer = pack.ContainerWriter(output.write)
2506.2.1 by Andrew Bennetts
Start implementing container format reading and writing.
71
        writer.begin()
72
        writer.add_bytes_record('abc', names=['name1', 'name2'])
2506.5.3 by Andrew Bennetts
Change format marker to use the word 'Bazaar' rather than 'bzr'.
73
        self.assertEqual('Bazaar pack format 1\nB3\nname1\nname2\n\nabc',
2506.2.1 by Andrew Bennetts
Start implementing container format reading and writing.
74
                         output.getvalue())
75
2506.5.2 by Andrew Bennetts
Raise InvalidRecordError on invalid names.
76
    def test_add_bytes_record_invalid_name(self):
77
        """Adding a Bytes record with a name with whitespace in it raises
78
        InvalidRecordError.
79
        """
80
        output = StringIO()
81
        writer = pack.ContainerWriter(output.write)
82
        writer.begin()
83
        self.assertRaises(
84
            errors.InvalidRecordError,
85
            writer.add_bytes_record, 'abc', names=['bad name'])
86
2506.2.1 by Andrew Bennetts
Start implementing container format reading and writing.
87
2506.3.2 by Andrew Bennetts
Test docstring tweaks, inspired by looking over the output of jml's testdoc tool.
88
class TestContainerReader(tests.TestCase):
2506.2.1 by Andrew Bennetts
Start implementing container format reading and writing.
89
2506.2.6 by Andrew Bennetts
Add validate method to ContainerReader and BytesRecordReader.
90
    def get_reader_for(self, bytes):
91
        stream = StringIO(bytes)
92
        reader = pack.ContainerReader(stream.read)
93
        return reader
94
2506.2.1 by Andrew Bennetts
Start implementing container format reading and writing.
95
    def test_construct(self):
96
        """Test constructing a ContainerReader.
97
        
98
        This uses None as the output stream to show that the constructor doesn't
99
        try to use the input stream.
100
        """
2506.3.1 by Andrew Bennetts
More progress:
101
        reader = pack.ContainerReader(None)
2506.2.1 by Andrew Bennetts
Start implementing container format reading and writing.
102
103
    def test_empty_container(self):
104
        """Read an empty container."""
2506.2.6 by Andrew Bennetts
Add validate method to ContainerReader and BytesRecordReader.
105
        reader = self.get_reader_for("Bazaar pack format 1\nE")
2506.2.1 by Andrew Bennetts
Start implementing container format reading and writing.
106
        self.assertEqual([], list(reader.iter_records()))
107
108
    def test_unknown_format(self):
109
        """Unrecognised container formats raise UnknownContainerFormatError."""
2506.2.6 by Andrew Bennetts
Add validate method to ContainerReader and BytesRecordReader.
110
        reader = self.get_reader_for("unknown format\n")
2506.2.1 by Andrew Bennetts
Start implementing container format reading and writing.
111
        self.assertRaises(
112
            errors.UnknownContainerFormatError, reader.iter_records)
113
114
    def test_unexpected_end_of_container(self):
115
        """Containers that don't end with an End Marker record should cause
116
        UnexpectedEndOfContainerError to be raised.
117
        """
2506.2.6 by Andrew Bennetts
Add validate method to ContainerReader and BytesRecordReader.
118
        reader = self.get_reader_for("Bazaar pack format 1\n")
2506.2.1 by Andrew Bennetts
Start implementing container format reading and writing.
119
        iterator = reader.iter_records()
120
        self.assertRaises(
121
            errors.UnexpectedEndOfContainerError, iterator.next)
122
123
    def test_unknown_record_type(self):
124
        """Unknown record types cause UnknownRecordTypeError to be raised."""
2506.2.6 by Andrew Bennetts
Add validate method to ContainerReader and BytesRecordReader.
125
        reader = self.get_reader_for("Bazaar pack format 1\nX")
2506.2.1 by Andrew Bennetts
Start implementing container format reading and writing.
126
        iterator = reader.iter_records()
127
        self.assertRaises(
128
            errors.UnknownRecordTypeError, iterator.next)
129
2506.3.1 by Andrew Bennetts
More progress:
130
    def test_container_with_one_unnamed_record(self):
131
        """Read a container with one Bytes record.
132
        
2506.3.2 by Andrew Bennetts
Test docstring tweaks, inspired by looking over the output of jml's testdoc tool.
133
        Parsing Bytes records is more thoroughly exercised by
134
        TestBytesRecordReader.  This test is here to ensure that
135
        ContainerReader's integration with BytesRecordReader is working.
2506.3.1 by Andrew Bennetts
More progress:
136
        """
2506.2.6 by Andrew Bennetts
Add validate method to ContainerReader and BytesRecordReader.
137
        reader = self.get_reader_for("Bazaar pack format 1\nB5\n\naaaaaE")
2506.2.1 by Andrew Bennetts
Start implementing container format reading and writing.
138
        expected_records = [([], 'aaaaa')]
2506.6.1 by Andrew Bennetts
Return a callable instead of a str from read, and add more validation.
139
        self.assertEqual(
140
            expected_records,
141
            [(names, read_bytes(None))
142
             for (names, read_bytes) in reader.iter_records()])
2506.2.1 by Andrew Bennetts
Start implementing container format reading and writing.
143
2506.2.6 by Andrew Bennetts
Add validate method to ContainerReader and BytesRecordReader.
144
    def test_validate_empty_container(self):
2506.6.1 by Andrew Bennetts
Return a callable instead of a str from read, and add more validation.
145
        """validate does not raise an error for a container with no records."""
2506.2.6 by Andrew Bennetts
Add validate method to ContainerReader and BytesRecordReader.
146
        reader = self.get_reader_for("Bazaar pack format 1\nE")
147
        # No exception raised
148
        reader.validate()
149
150
    def test_validate_non_empty_valid_container(self):
2506.6.1 by Andrew Bennetts
Return a callable instead of a str from read, and add more validation.
151
        """validate does not raise an error for a container with a valid record.
152
        """
2506.2.6 by Andrew Bennetts
Add validate method to ContainerReader and BytesRecordReader.
153
        reader = self.get_reader_for("Bazaar pack format 1\nB3\nname\n\nabcE")
154
        # No exception raised
155
        reader.validate()
156
157
    def test_validate_bad_format(self):
2506.6.1 by Andrew Bennetts
Return a callable instead of a str from read, and add more validation.
158
        """validate raises an error for unrecognised format strings.
159
160
        It may raise either UnexpectedEndOfContainerError or
161
        UnknownContainerFormatError, depending on exactly what the string is.
162
        """
2506.2.6 by Andrew Bennetts
Add validate method to ContainerReader and BytesRecordReader.
163
        inputs = ["", "x", "Bazaar pack format 1", "bad\n"]
164
        for input in inputs:
165
            reader = self.get_reader_for(input)
166
            self.assertRaises(
167
                (errors.UnexpectedEndOfContainerError,
168
                 errors.UnknownContainerFormatError),
169
                reader.validate)
170
171
    def test_validate_bad_record_marker(self):
2506.6.1 by Andrew Bennetts
Return a callable instead of a str from read, and add more validation.
172
        """validate raises UnknownRecordTypeError for unrecognised record
173
        types.
174
        """
2506.2.6 by Andrew Bennetts
Add validate method to ContainerReader and BytesRecordReader.
175
        reader = self.get_reader_for("Bazaar pack format 1\nX")
176
        self.assertRaises(errors.UnknownRecordTypeError, reader.validate)
177
178
    def test_validate_data_after_end_marker(self):
2506.6.1 by Andrew Bennetts
Return a callable instead of a str from read, and add more validation.
179
        """validate raises ContainerHasExcessDataError if there are any bytes
180
        after the end of the container.
181
        """
2506.2.6 by Andrew Bennetts
Add validate method to ContainerReader and BytesRecordReader.
182
        reader = self.get_reader_for("Bazaar pack format 1\nEcrud")
183
        self.assertRaises(
184
            errors.ContainerHasExcessDataError, reader.validate)
185
186
    def test_validate_no_end_marker(self):
2506.6.1 by Andrew Bennetts
Return a callable instead of a str from read, and add more validation.
187
        """validate raises UnexpectedEndOfContainerError if there's no end of
188
        container marker, even if the container up to this point has been valid.
189
        """
2506.2.6 by Andrew Bennetts
Add validate method to ContainerReader and BytesRecordReader.
190
        reader = self.get_reader_for("Bazaar pack format 1\n")
191
        self.assertRaises(
192
            errors.UnexpectedEndOfContainerError, reader.validate)
193
2506.6.1 by Andrew Bennetts
Return a callable instead of a str from read, and add more validation.
194
    def test_validate_duplicate_name(self):
195
        """validate raises DuplicateRecordNameError if the same name occurs
196
        multiple times in the container.
197
        """
198
        reader = self.get_reader_for(
199
            "Bazaar pack format 1\n"
200
            "B0\nname\n\n"
201
            "B0\nname\n\n"
202
            "E")
203
        self.assertRaises(errors.DuplicateRecordNameError, reader.validate)
204
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)
209
        
2506.3.1 by Andrew Bennetts
More progress:
210
2506.3.2 by Andrew Bennetts
Test docstring tweaks, inspired by looking over the output of jml's testdoc tool.
211
class TestBytesRecordReader(tests.TestCase):
2506.6.1 by Andrew Bennetts
Return a callable instead of a str from read, and add more validation.
212
    """Tests for reading and validating Bytes records with BytesRecordReader."""
2506.3.1 by Andrew Bennetts
More progress:
213
2506.2.6 by Andrew Bennetts
Add validate method to ContainerReader and BytesRecordReader.
214
    def get_reader_for(self, bytes):
215
        stream = StringIO(bytes)
216
        reader = pack.BytesRecordReader(stream.read)
217
        return reader
218
2506.3.1 by Andrew Bennetts
More progress:
219
    def test_record_with_no_name(self):
220
        """Reading a Bytes record with no name returns an empty list of
221
        names.
222
        """
2506.2.6 by Andrew Bennetts
Add validate method to ContainerReader and BytesRecordReader.
223
        reader = self.get_reader_for("5\n\naaaaa")
2506.6.1 by Andrew Bennetts
Return a callable instead of a str from read, and add more validation.
224
        names, get_bytes = reader.read()
2506.3.1 by Andrew Bennetts
More progress:
225
        self.assertEqual([], names)
2506.6.1 by Andrew Bennetts
Return a callable instead of a str from read, and add more validation.
226
        self.assertEqual('aaaaa', get_bytes(None))
2506.3.1 by Andrew Bennetts
More progress:
227
228
    def test_record_with_one_name(self):
229
        """Reading a Bytes record with one name returns a list of just that
230
        name.
231
        """
2506.2.6 by Andrew Bennetts
Add validate method to ContainerReader and BytesRecordReader.
232
        reader = self.get_reader_for("5\nname1\n\naaaaa")
2506.6.1 by Andrew Bennetts
Return a callable instead of a str from read, and add more validation.
233
        names, get_bytes = reader.read()
2506.3.1 by Andrew Bennetts
More progress:
234
        self.assertEqual(['name1'], names)
2506.6.1 by Andrew Bennetts
Return a callable instead of a str from read, and add more validation.
235
        self.assertEqual('aaaaa', get_bytes(None))
2506.3.1 by Andrew Bennetts
More progress:
236
237
    def test_record_with_two_names(self):
238
        """Reading a Bytes record with two names returns a list of both names.
239
        """
2506.2.6 by Andrew Bennetts
Add validate method to ContainerReader and BytesRecordReader.
240
        reader = self.get_reader_for("5\nname1\nname2\n\naaaaa")
2506.6.1 by Andrew Bennetts
Return a callable instead of a str from read, and add more validation.
241
        names, get_bytes = reader.read()
2506.3.1 by Andrew Bennetts
More progress:
242
        self.assertEqual(['name1', 'name2'], names)
2506.6.1 by Andrew Bennetts
Return a callable instead of a str from read, and add more validation.
243
        self.assertEqual('aaaaa', get_bytes(None))
2506.3.1 by Andrew Bennetts
More progress:
244
245
    def test_invalid_length(self):
246
        """If the length-prefix is not a number, parsing raises
247
        InvalidRecordError.
248
        """
2506.2.6 by Andrew Bennetts
Add validate method to ContainerReader and BytesRecordReader.
249
        reader = self.get_reader_for("not a number\n")
2506.3.1 by Andrew Bennetts
More progress:
250
        self.assertRaises(errors.InvalidRecordError, reader.read)
2506.2.1 by Andrew Bennetts
Start implementing container format reading and writing.
251
2506.3.3 by Andrew Bennetts
Deal with EOF in the middle of a bytes record.
252
    def test_early_eof(self):
253
        """Tests for premature EOF occuring during parsing Bytes records with
254
        BytesRecordReader.
255
        
256
        A incomplete container might be interrupted at any point.  The
257
        BytesRecordReader needs to cope with the input stream running out no
258
        matter where it is in the parsing process.
259
260
        In all cases, UnexpectedEndOfContainerError should be raised.
261
        """
262
        complete_record = "6\nname\n\nabcdef"
263
        for count in range(0, len(complete_record)):
2506.6.1 by Andrew Bennetts
Return a callable instead of a str from read, and add more validation.
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).
2506.3.3 by Andrew Bennetts
Deal with EOF in the middle of a bytes record.
268
            try:
2506.6.1 by Andrew Bennetts
Return a callable instead of a str from read, and add more validation.
269
                names, read_bytes = reader.read()
270
                read_bytes(None)
2506.3.3 by Andrew Bennetts
Deal with EOF in the middle of a bytes record.
271
            except errors.UnexpectedEndOfContainerError:
272
                pass
273
            else:
274
                self.fail(
275
                    "UnexpectedEndOfContainerError not raised when parsing %r"
2506.6.1 by Andrew Bennetts
Return a callable instead of a str from read, and add more validation.
276
                    % (incomplete_record,))
2506.3.3 by Andrew Bennetts
Deal with EOF in the middle of a bytes record.
277
2506.5.2 by Andrew Bennetts
Raise InvalidRecordError on invalid names.
278
    def test_initial_eof(self):
2506.3.3 by Andrew Bennetts
Deal with EOF in the middle of a bytes record.
279
        """EOF before any bytes read at all."""
2506.2.6 by Andrew Bennetts
Add validate method to ContainerReader and BytesRecordReader.
280
        reader = self.get_reader_for("")
2506.3.3 by Andrew Bennetts
Deal with EOF in the middle of a bytes record.
281
        self.assertRaises(errors.UnexpectedEndOfContainerError, reader.read)
282
2506.5.2 by Andrew Bennetts
Raise InvalidRecordError on invalid names.
283
    def test_eof_after_length(self):
2506.3.3 by Andrew Bennetts
Deal with EOF in the middle of a bytes record.
284
        """EOF after reading the length and before reading name(s)."""
2506.2.6 by Andrew Bennetts
Add validate method to ContainerReader and BytesRecordReader.
285
        reader = self.get_reader_for("123\n")
2506.3.3 by Andrew Bennetts
Deal with EOF in the middle of a bytes record.
286
        self.assertRaises(errors.UnexpectedEndOfContainerError, reader.read)
287
2506.5.2 by Andrew Bennetts
Raise InvalidRecordError on invalid names.
288
    def test_eof_during_name(self):
2506.3.3 by Andrew Bennetts
Deal with EOF in the middle of a bytes record.
289
        """EOF during reading a name."""
2506.2.6 by Andrew Bennetts
Add validate method to ContainerReader and BytesRecordReader.
290
        reader = self.get_reader_for("123\nname")
2506.3.3 by Andrew Bennetts
Deal with EOF in the middle of a bytes record.
291
        self.assertRaises(errors.UnexpectedEndOfContainerError, reader.read)
292
2506.6.1 by Andrew Bennetts
Return a callable instead of a str from read, and add more validation.
293
    def test_read_invalid_name_whitespace(self):
2506.5.2 by Andrew Bennetts
Raise InvalidRecordError on invalid names.
294
        """Names must have no whitespace."""
295
        # A name with a space.
2506.2.6 by Andrew Bennetts
Add validate method to ContainerReader and BytesRecordReader.
296
        reader = self.get_reader_for("0\nbad name\n\n")
2506.5.2 by Andrew Bennetts
Raise InvalidRecordError on invalid names.
297
        self.assertRaises(errors.InvalidRecordError, reader.read)
298
299
        # A name with a tab.
2506.2.6 by Andrew Bennetts
Add validate method to ContainerReader and BytesRecordReader.
300
        reader = self.get_reader_for("0\nbad\tname\n\n")
2506.5.2 by Andrew Bennetts
Raise InvalidRecordError on invalid names.
301
        self.assertRaises(errors.InvalidRecordError, reader.read)
302
303
        # A name with a vertical tab.
2506.2.6 by Andrew Bennetts
Add validate method to ContainerReader and BytesRecordReader.
304
        reader = self.get_reader_for("0\nbad\vname\n\n")
2506.5.2 by Andrew Bennetts
Raise InvalidRecordError on invalid names.
305
        self.assertRaises(errors.InvalidRecordError, reader.read)
306
2506.2.6 by Andrew Bennetts
Add validate method to ContainerReader and BytesRecordReader.
307
    def test_validate_whitespace_in_name(self):
2506.6.1 by Andrew Bennetts
Return a callable instead of a str from read, and add more validation.
308
        """Names must have no whitespace."""
309
        reader = self.get_reader_for("0\nbad name\n\n")
2506.2.6 by Andrew Bennetts
Add validate method to ContainerReader and BytesRecordReader.
310
        self.assertRaises(errors.InvalidRecordError, reader.validate)
311
312
    def test_validate_interrupted_prelude(self):
2506.6.1 by Andrew Bennetts
Return a callable instead of a str from read, and add more validation.
313
        """EOF during reading a record's prelude causes validate to fail."""
2506.2.6 by Andrew Bennetts
Add validate method to ContainerReader and BytesRecordReader.
314
        reader = self.get_reader_for("")
315
        self.assertRaises(
316
            errors.UnexpectedEndOfContainerError, reader.validate)
317
318
    def test_validate_interrupted_body(self):
2506.6.1 by Andrew Bennetts
Return a callable instead of a str from read, and add more validation.
319
        """EOF during reading a record's body causes validate to fail."""
2506.2.6 by Andrew Bennetts
Add validate method to ContainerReader and BytesRecordReader.
320
        reader = self.get_reader_for("1\n\n")
321
        self.assertRaises(
322
            errors.UnexpectedEndOfContainerError, reader.validate)
323
324
    def test_validate_unparseable_length(self):
2506.6.1 by Andrew Bennetts
Return a callable instead of a str from read, and add more validation.
325
        """An unparseable record length causes validate to fail."""
2506.2.6 by Andrew Bennetts
Add validate method to ContainerReader and BytesRecordReader.
326
        reader = self.get_reader_for("\n\n")
327
        self.assertRaises(
328
            errors.InvalidRecordError, reader.validate)
329
2506.6.1 by Andrew Bennetts
Return a callable instead of a str from read, and add more validation.
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)
334
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.
338
        """
339
        reader = self.get_reader_for("6\n\nabcdef")
340
        names, get_bytes = reader.read()
341
        self.assertEqual('abc', get_bytes(3))
342
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.
346
        """
347
        reader = self.get_reader_for("6\n\nabcdef")
348
        names, get_bytes = reader.read()
349
        self.assertEqual('abcdef', get_bytes(None))
350
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.
354
        """
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))
360
361