/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
1
# Copyright (C) 2007, 2009, 2011, 2012, 2016 Canonical Ltd
2506.2.1 by Andrew Bennetts
Start implementing container format reading and writing.
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
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2506.2.1 by Andrew Bennetts
Start implementing container format reading and writing.
16
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
17
"""Tests for breezy.pack."""
2506.2.1 by Andrew Bennetts
Start implementing container format reading and writing.
18
6670.4.1 by Jelmer Vernooij
Update imports.
19
from .. import errors, tests
20
from ..bzr import (
21
    pack,
22
    )
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
23
from ..sixish import (
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
24
    BytesIO,
25
    )
2506.3.2 by Andrew Bennetts
Test docstring tweaks, inspired by looking over the output of jml's testdoc tool.
26
27
2916.2.11 by Andrew Bennetts
Add direct unit tests for ContainerSerialiser.
28
class TestContainerSerialiser(tests.TestCase):
29
    """Tests for the ContainerSerialiser class."""
30
31
    def test_construct(self):
32
        """Test constructing a ContainerSerialiser."""
33
        pack.ContainerSerialiser()
34
35
    def test_begin(self):
36
        serialiser = pack.ContainerSerialiser()
6803.2.5 by Martin
Make test_pack pass on Python 3
37
        self.assertEqual(b'Bazaar pack format 1 (introduced in 0.18)\n',
2916.2.11 by Andrew Bennetts
Add direct unit tests for ContainerSerialiser.
38
                         serialiser.begin())
39
40
    def test_end(self):
41
        serialiser = pack.ContainerSerialiser()
6803.2.5 by Martin
Make test_pack pass on Python 3
42
        self.assertEqual(b'E', serialiser.end())
2916.2.11 by Andrew Bennetts
Add direct unit tests for ContainerSerialiser.
43
44
    def test_bytes_record_no_name(self):
45
        serialiser = pack.ContainerSerialiser()
6803.2.5 by Martin
Make test_pack pass on Python 3
46
        record = serialiser.bytes_record(b'bytes', [])
47
        self.assertEqual(b'B5\n\nbytes', record)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
48
2916.2.11 by Andrew Bennetts
Add direct unit tests for ContainerSerialiser.
49
    def test_bytes_record_one_name_with_one_part(self):
50
        serialiser = pack.ContainerSerialiser()
6803.2.5 by Martin
Make test_pack pass on Python 3
51
        record = serialiser.bytes_record(b'bytes', [(b'name',)])
52
        self.assertEqual(b'B5\nname\n\nbytes', record)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
53
2916.2.11 by Andrew Bennetts
Add direct unit tests for ContainerSerialiser.
54
    def test_bytes_record_one_name_with_two_parts(self):
55
        serialiser = pack.ContainerSerialiser()
6803.2.5 by Martin
Make test_pack pass on Python 3
56
        record = serialiser.bytes_record(b'bytes', [(b'part1', b'part2')])
57
        self.assertEqual(b'B5\npart1\x00part2\n\nbytes', record)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
58
2916.2.11 by Andrew Bennetts
Add direct unit tests for ContainerSerialiser.
59
    def test_bytes_record_two_names(self):
60
        serialiser = pack.ContainerSerialiser()
6803.2.5 by Martin
Make test_pack pass on Python 3
61
        record = serialiser.bytes_record(b'bytes', [(b'name1',), (b'name2',)])
62
        self.assertEqual(b'B5\nname1\nname2\n\nbytes', record)
2916.2.11 by Andrew Bennetts
Add direct unit tests for ContainerSerialiser.
63
64
    def test_bytes_record_whitespace_in_name_part(self):
65
        serialiser = pack.ContainerSerialiser()
66
        self.assertRaises(
67
            errors.InvalidRecordError,
6803.2.5 by Martin
Make test_pack pass on Python 3
68
            serialiser.bytes_record, b'bytes', [(b'bad name',)])
2916.2.11 by Andrew Bennetts
Add direct unit tests for ContainerSerialiser.
69
6257.5.1 by Martin Pool
ContainerWriter: Avoid one possible large-string join
70
    def test_bytes_record_header(self):
71
        serialiser = pack.ContainerSerialiser()
6803.2.5 by Martin
Make test_pack pass on Python 3
72
        record = serialiser.bytes_header(32, [(b'name1',), (b'name2',)])
73
        self.assertEqual(b'B32\nname1\nname2\n\n', record)
6257.5.1 by Martin Pool
ContainerWriter: Avoid one possible large-string join
74
2916.2.11 by Andrew Bennetts
Add direct unit tests for ContainerSerialiser.
75
2506.3.2 by Andrew Bennetts
Test docstring tweaks, inspired by looking over the output of jml's testdoc tool.
76
class TestContainerWriter(tests.TestCase):
2506.2.1 by Andrew Bennetts
Start implementing container format reading and writing.
77
2916.2.12 by Andrew Bennetts
Refactor TestContainerWriter to be a little more concise.
78
    def setUp(self):
6552.1.3 by Vincent Ladeuil
Use super() instead of calling <base>.setup(self), as the original fix illustrated a too-easy-to-fall-into trap.
79
        super(TestContainerWriter, self).setUp()
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
80
        self.output = BytesIO()
2916.2.12 by Andrew Bennetts
Refactor TestContainerWriter to be a little more concise.
81
        self.writer = pack.ContainerWriter(self.output.write)
82
83
    def assertOutput(self, expected_output):
84
        """Assert that the output of self.writer ContainerWriter is equal to
85
        expected_output.
86
        """
87
        self.assertEqual(expected_output, self.output.getvalue())
88
2506.2.1 by Andrew Bennetts
Start implementing container format reading and writing.
89
    def test_construct(self):
90
        """Test constructing a ContainerWriter.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
91
2916.2.12 by Andrew Bennetts
Refactor TestContainerWriter to be a little more concise.
92
        This uses None as the output stream to show that the constructor
93
        doesn't try to use the output stream.
2506.2.1 by Andrew Bennetts
Start implementing container format reading and writing.
94
        """
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
95
        pack.ContainerWriter(None)
2506.2.1 by Andrew Bennetts
Start implementing container format reading and writing.
96
97
    def test_begin(self):
2506.3.2 by Andrew Bennetts
Test docstring tweaks, inspired by looking over the output of jml's testdoc tool.
98
        """The begin() method writes the container format marker line."""
2916.2.12 by Andrew Bennetts
Refactor TestContainerWriter to be a little more concise.
99
        self.writer.begin()
6803.2.5 by Martin
Make test_pack pass on Python 3
100
        self.assertOutput(b'Bazaar pack format 1 (introduced in 0.18)\n')
2506.2.1 by Andrew Bennetts
Start implementing container format reading and writing.
101
2698.1.1 by Robert Collins
Add records_written attribute to ContainerWriter's. (Robert Collins).
102
    def test_zero_records_written_after_begin(self):
103
        """After begin is written, 0 records have been written."""
2916.2.12 by Andrew Bennetts
Refactor TestContainerWriter to be a little more concise.
104
        self.writer.begin()
105
        self.assertEqual(0, self.writer.records_written)
2698.1.1 by Robert Collins
Add records_written attribute to ContainerWriter's. (Robert Collins).
106
2506.2.1 by Andrew Bennetts
Start implementing container format reading and writing.
107
    def test_end(self):
2506.3.2 by Andrew Bennetts
Test docstring tweaks, inspired by looking over the output of jml's testdoc tool.
108
        """The end() method writes an End Marker record."""
2916.2.12 by Andrew Bennetts
Refactor TestContainerWriter to be a little more concise.
109
        self.writer.begin()
110
        self.writer.end()
6803.2.5 by Martin
Make test_pack pass on Python 3
111
        self.assertOutput(b'Bazaar pack format 1 (introduced in 0.18)\nE')
2506.2.1 by Andrew Bennetts
Start implementing container format reading and writing.
112
2698.1.1 by Robert Collins
Add records_written attribute to ContainerWriter's. (Robert Collins).
113
    def test_empty_end_does_not_add_a_record_to_records_written(self):
114
        """The end() method does not count towards the records written."""
2916.2.12 by Andrew Bennetts
Refactor TestContainerWriter to be a little more concise.
115
        self.writer.begin()
116
        self.writer.end()
117
        self.assertEqual(0, self.writer.records_written)
2698.1.1 by Robert Collins
Add records_written attribute to ContainerWriter's. (Robert Collins).
118
119
    def test_non_empty_end_does_not_add_a_record_to_records_written(self):
120
        """The end() method does not count towards the records written."""
2916.2.12 by Andrew Bennetts
Refactor TestContainerWriter to be a little more concise.
121
        self.writer.begin()
6803.2.5 by Martin
Make test_pack pass on Python 3
122
        self.writer.add_bytes_record(b'foo', names=[])
2916.2.12 by Andrew Bennetts
Refactor TestContainerWriter to be a little more concise.
123
        self.writer.end()
124
        self.assertEqual(1, self.writer.records_written)
2698.1.1 by Robert Collins
Add records_written attribute to ContainerWriter's. (Robert Collins).
125
2506.2.1 by Andrew Bennetts
Start implementing container format reading and writing.
126
    def test_add_bytes_record_no_name(self):
127
        """Add a bytes record with no name."""
2916.2.12 by Andrew Bennetts
Refactor TestContainerWriter to be a little more concise.
128
        self.writer.begin()
6803.2.5 by Martin
Make test_pack pass on Python 3
129
        offset, length = self.writer.add_bytes_record(b'abc', names=[])
2661.2.1 by Robert Collins
* ``bzrlib.pack.ContainerWriter`` now returns an offset, length tuple to
130
        self.assertEqual((42, 7), (offset, length))
2916.2.12 by Andrew Bennetts
Refactor TestContainerWriter to be a little more concise.
131
        self.assertOutput(
6803.2.5 by Martin
Make test_pack pass on Python 3
132
            b'Bazaar pack format 1 (introduced in 0.18)\nB3\n\nabc')
2506.2.1 by Andrew Bennetts
Start implementing container format reading and writing.
133
134
    def test_add_bytes_record_one_name(self):
135
        """Add a bytes record with one name."""
2916.2.12 by Andrew Bennetts
Refactor TestContainerWriter to be a little more concise.
136
        self.writer.begin()
6257.5.1 by Martin Pool
ContainerWriter: Avoid one possible large-string join
137
2916.2.12 by Andrew Bennetts
Refactor TestContainerWriter to be a little more concise.
138
        offset, length = self.writer.add_bytes_record(
6803.2.5 by Martin
Make test_pack pass on Python 3
139
            b'abc', names=[(b'name1', )])
2661.2.1 by Robert Collins
* ``bzrlib.pack.ContainerWriter`` now returns an offset, length tuple to
140
        self.assertEqual((42, 13), (offset, length))
2916.2.12 by Andrew Bennetts
Refactor TestContainerWriter to be a little more concise.
141
        self.assertOutput(
6803.2.5 by Martin
Make test_pack pass on Python 3
142
            b'Bazaar pack format 1 (introduced in 0.18)\n'
143
            b'B3\nname1\n\nabc')
2916.2.12 by Andrew Bennetts
Refactor TestContainerWriter to be a little more concise.
144
6257.5.1 by Martin Pool
ContainerWriter: Avoid one possible large-string join
145
    def test_add_bytes_record_split_writes(self):
146
        """Write a large record which does multiple IOs"""
147
148
        writes = []
149
        real_write = self.writer.write_func
150
6803.2.5 by Martin
Make test_pack pass on Python 3
151
        def record_writes(data):
152
            writes.append(data)
153
            return real_write(data)
6257.5.1 by Martin Pool
ContainerWriter: Avoid one possible large-string join
154
155
        self.writer.write_func = record_writes
156
        self.writer._JOIN_WRITES_THRESHOLD = 2
157
158
        self.writer.begin()
159
        offset, length = self.writer.add_bytes_record(
6803.2.5 by Martin
Make test_pack pass on Python 3
160
            b'abcabc', names=[(b'name1', )])
6257.5.1 by Martin Pool
ContainerWriter: Avoid one possible large-string join
161
        self.assertEqual((42, 16), (offset, length))
162
        self.assertOutput(
6803.2.5 by Martin
Make test_pack pass on Python 3
163
            b'Bazaar pack format 1 (introduced in 0.18)\n'
164
            b'B6\nname1\n\nabcabc')
6257.5.1 by Martin Pool
ContainerWriter: Avoid one possible large-string join
165
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
166
        self.assertEqual([
6803.2.5 by Martin
Make test_pack pass on Python 3
167
            b'Bazaar pack format 1 (introduced in 0.18)\n',
168
            b'B6\nname1\n\n',
169
            b'abcabc'],
6257.5.1 by Martin Pool
ContainerWriter: Avoid one possible large-string join
170
            writes)
171
2916.2.12 by Andrew Bennetts
Refactor TestContainerWriter to be a little more concise.
172
    def test_add_bytes_record_two_names(self):
173
        """Add a bytes record with two names."""
174
        self.writer.begin()
175
        offset, length = self.writer.add_bytes_record(
6803.2.5 by Martin
Make test_pack pass on Python 3
176
            b'abc', names=[(b'name1', ), (b'name2', )])
2916.2.12 by Andrew Bennetts
Refactor TestContainerWriter to be a little more concise.
177
        self.assertEqual((42, 19), (offset, length))
178
        self.assertOutput(
6803.2.5 by Martin
Make test_pack pass on Python 3
179
            b'Bazaar pack format 1 (introduced in 0.18)\n'
180
            b'B3\nname1\nname2\n\nabc')
2916.2.12 by Andrew Bennetts
Refactor TestContainerWriter to be a little more concise.
181
182
    def test_add_bytes_record_two_names(self):
183
        """Add a bytes record with two names."""
184
        self.writer.begin()
185
        offset, length = self.writer.add_bytes_record(
6803.2.5 by Martin
Make test_pack pass on Python 3
186
            b'abc', names=[(b'name1', ), (b'name2', )])
2916.2.12 by Andrew Bennetts
Refactor TestContainerWriter to be a little more concise.
187
        self.assertEqual((42, 19), (offset, length))
188
        self.assertOutput(
6803.2.5 by Martin
Make test_pack pass on Python 3
189
            b'Bazaar pack format 1 (introduced in 0.18)\n'
190
            b'B3\nname1\nname2\n\nabc')
2682.1.1 by Robert Collins
* The ``bzrlib.pack`` interface has changed to use tuples of bytestrings
191
192
    def test_add_bytes_record_two_element_name(self):
193
        """Add a bytes record with a two-element name."""
2916.2.12 by Andrew Bennetts
Refactor TestContainerWriter to be a little more concise.
194
        self.writer.begin()
195
        offset, length = self.writer.add_bytes_record(
6803.2.5 by Martin
Make test_pack pass on Python 3
196
            b'abc', names=[(b'name1', b'name2')])
2682.1.1 by Robert Collins
* The ``bzrlib.pack`` interface has changed to use tuples of bytestrings
197
        self.assertEqual((42, 19), (offset, length))
2916.2.12 by Andrew Bennetts
Refactor TestContainerWriter to be a little more concise.
198
        self.assertOutput(
6803.2.5 by Martin
Make test_pack pass on Python 3
199
            b'Bazaar pack format 1 (introduced in 0.18)\n'
200
            b'B3\nname1\x00name2\n\nabc')
2506.2.1 by Andrew Bennetts
Start implementing container format reading and writing.
201
2661.2.1 by Robert Collins
* ``bzrlib.pack.ContainerWriter`` now returns an offset, length tuple to
202
    def test_add_second_bytes_record_gets_higher_offset(self):
2916.2.12 by Andrew Bennetts
Refactor TestContainerWriter to be a little more concise.
203
        self.writer.begin()
6803.2.5 by Martin
Make test_pack pass on Python 3
204
        self.writer.add_bytes_record(b'abc', names=[])
205
        offset, length = self.writer.add_bytes_record(b'abc', names=[])
2661.2.1 by Robert Collins
* ``bzrlib.pack.ContainerWriter`` now returns an offset, length tuple to
206
        self.assertEqual((49, 7), (offset, length))
2916.2.12 by Andrew Bennetts
Refactor TestContainerWriter to be a little more concise.
207
        self.assertOutput(
6803.2.5 by Martin
Make test_pack pass on Python 3
208
            b'Bazaar pack format 1 (introduced in 0.18)\n'
209
            b'B3\n\nabc'
210
            b'B3\n\nabc')
2661.2.1 by Robert Collins
* ``bzrlib.pack.ContainerWriter`` now returns an offset, length tuple to
211
2506.5.2 by Andrew Bennetts
Raise InvalidRecordError on invalid names.
212
    def test_add_bytes_record_invalid_name(self):
213
        """Adding a Bytes record with a name with whitespace in it raises
214
        InvalidRecordError.
215
        """
2916.2.12 by Andrew Bennetts
Refactor TestContainerWriter to be a little more concise.
216
        self.writer.begin()
2506.5.2 by Andrew Bennetts
Raise InvalidRecordError on invalid names.
217
        self.assertRaises(
218
            errors.InvalidRecordError,
6803.2.5 by Martin
Make test_pack pass on Python 3
219
            self.writer.add_bytes_record, b'abc', names=[(b'bad name', )])
2506.5.2 by Andrew Bennetts
Raise InvalidRecordError on invalid names.
220
2698.1.1 by Robert Collins
Add records_written attribute to ContainerWriter's. (Robert Collins).
221
    def test_add_bytes_records_add_to_records_written(self):
222
        """Adding a Bytes record increments the records_written counter."""
2916.2.12 by Andrew Bennetts
Refactor TestContainerWriter to be a little more concise.
223
        self.writer.begin()
6803.2.5 by Martin
Make test_pack pass on Python 3
224
        self.writer.add_bytes_record(b'foo', names=[])
2916.2.12 by Andrew Bennetts
Refactor TestContainerWriter to be a little more concise.
225
        self.assertEqual(1, self.writer.records_written)
6803.2.5 by Martin
Make test_pack pass on Python 3
226
        self.writer.add_bytes_record(b'foo', names=[])
2916.2.12 by Andrew Bennetts
Refactor TestContainerWriter to be a little more concise.
227
        self.assertEqual(2, self.writer.records_written)
2698.1.1 by Robert Collins
Add records_written attribute to ContainerWriter's. (Robert Collins).
228
2506.2.1 by Andrew Bennetts
Start implementing container format reading and writing.
229
2506.3.2 by Andrew Bennetts
Test docstring tweaks, inspired by looking over the output of jml's testdoc tool.
230
class TestContainerReader(tests.TestCase):
2916.2.13 by Andrew Bennetts
Improve some docstrings.
231
    """Tests for the ContainerReader.
232
233
    The ContainerReader reads format 1 containers, so these tests explicitly
234
    test how it reacts to format 1 data.  If a new version of the format is
235
    added, then separate tests for that format should be added.
236
    """
2506.2.1 by Andrew Bennetts
Start implementing container format reading and writing.
237
6803.2.5 by Martin
Make test_pack pass on Python 3
238
    def get_reader_for(self, data):
239
        stream = BytesIO(data)
2535.3.26 by Andrew Bennetts
Revert merge of container-format changes rejected for bzr.dev (i.e. undo andrew.bennetts@canonical.com-20070717044423-cetp5spep142xsr4).
240
        reader = pack.ContainerReader(stream)
2506.2.6 by Andrew Bennetts
Add validate method to ContainerReader and BytesRecordReader.
241
        return reader
242
2506.2.1 by Andrew Bennetts
Start implementing container format reading and writing.
243
    def test_construct(self):
244
        """Test constructing a ContainerReader.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
245
6257.5.1 by Martin Pool
ContainerWriter: Avoid one possible large-string join
246
        This uses None as the output stream to show that the constructor
247
        doesn't try to use the input stream.
2506.2.1 by Andrew Bennetts
Start implementing container format reading and writing.
248
        """
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
249
        pack.ContainerReader(None)
2506.2.1 by Andrew Bennetts
Start implementing container format reading and writing.
250
251
    def test_empty_container(self):
252
        """Read an empty container."""
2506.2.10 by Andrew Bennetts
Add '(introduced in 0.18)' to pack format string.
253
        reader = self.get_reader_for(
6803.2.5 by Martin
Make test_pack pass on Python 3
254
            b"Bazaar pack format 1 (introduced in 0.18)\nE")
2506.2.1 by Andrew Bennetts
Start implementing container format reading and writing.
255
        self.assertEqual([], list(reader.iter_records()))
256
257
    def test_unknown_format(self):
258
        """Unrecognised container formats raise UnknownContainerFormatError."""
6803.2.5 by Martin
Make test_pack pass on Python 3
259
        reader = self.get_reader_for(b"unknown format\n")
2506.2.1 by Andrew Bennetts
Start implementing container format reading and writing.
260
        self.assertRaises(
261
            errors.UnknownContainerFormatError, reader.iter_records)
262
263
    def test_unexpected_end_of_container(self):
264
        """Containers that don't end with an End Marker record should cause
265
        UnexpectedEndOfContainerError to be raised.
266
        """
2506.2.10 by Andrew Bennetts
Add '(introduced in 0.18)' to pack format string.
267
        reader = self.get_reader_for(
6803.2.5 by Martin
Make test_pack pass on Python 3
268
            b"Bazaar pack format 1 (introduced in 0.18)\n")
2506.2.1 by Andrew Bennetts
Start implementing container format reading and writing.
269
        iterator = reader.iter_records()
270
        self.assertRaises(
6634.2.1 by Martin
Apply 2to3 next fixer and make compatible
271
            errors.UnexpectedEndOfContainerError, next, iterator)
2506.2.1 by Andrew Bennetts
Start implementing container format reading and writing.
272
273
    def test_unknown_record_type(self):
274
        """Unknown record types cause UnknownRecordTypeError to be raised."""
2506.2.10 by Andrew Bennetts
Add '(introduced in 0.18)' to pack format string.
275
        reader = self.get_reader_for(
6803.2.5 by Martin
Make test_pack pass on Python 3
276
            b"Bazaar pack format 1 (introduced in 0.18)\nX")
2506.2.1 by Andrew Bennetts
Start implementing container format reading and writing.
277
        iterator = reader.iter_records()
278
        self.assertRaises(
6634.2.1 by Martin
Apply 2to3 next fixer and make compatible
279
            errors.UnknownRecordTypeError, next, iterator)
2506.2.1 by Andrew Bennetts
Start implementing container format reading and writing.
280
2506.3.1 by Andrew Bennetts
More progress:
281
    def test_container_with_one_unnamed_record(self):
282
        """Read a container with one Bytes record.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
283
2506.3.2 by Andrew Bennetts
Test docstring tweaks, inspired by looking over the output of jml's testdoc tool.
284
        Parsing Bytes records is more thoroughly exercised by
285
        TestBytesRecordReader.  This test is here to ensure that
286
        ContainerReader's integration with BytesRecordReader is working.
2506.3.1 by Andrew Bennetts
More progress:
287
        """
2506.2.10 by Andrew Bennetts
Add '(introduced in 0.18)' to pack format string.
288
        reader = self.get_reader_for(
6803.2.5 by Martin
Make test_pack pass on Python 3
289
            b"Bazaar pack format 1 (introduced in 0.18)\nB5\n\naaaaaE")
290
        expected_records = [([], b'aaaaa')]
2506.6.1 by Andrew Bennetts
Return a callable instead of a str from read, and add more validation.
291
        self.assertEqual(
292
            expected_records,
293
            [(names, read_bytes(None))
294
             for (names, read_bytes) in reader.iter_records()])
2506.2.1 by Andrew Bennetts
Start implementing container format reading and writing.
295
2506.2.6 by Andrew Bennetts
Add validate method to ContainerReader and BytesRecordReader.
296
    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.
297
        """validate does not raise an error for a container with no records."""
6257.5.1 by Martin Pool
ContainerWriter: Avoid one possible large-string join
298
        reader = self.get_reader_for(
6803.2.5 by Martin
Make test_pack pass on Python 3
299
            b"Bazaar pack format 1 (introduced in 0.18)\nE")
2506.2.6 by Andrew Bennetts
Add validate method to ContainerReader and BytesRecordReader.
300
        # No exception raised
301
        reader.validate()
302
303
    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.
304
        """validate does not raise an error for a container with a valid record.
305
        """
2506.2.10 by Andrew Bennetts
Add '(introduced in 0.18)' to pack format string.
306
        reader = self.get_reader_for(
6803.2.5 by Martin
Make test_pack pass on Python 3
307
            b"Bazaar pack format 1 (introduced in 0.18)\nB3\nname\n\nabcE")
2506.2.6 by Andrew Bennetts
Add validate method to ContainerReader and BytesRecordReader.
308
        # No exception raised
309
        reader.validate()
310
311
    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.
312
        """validate raises an error for unrecognised format strings.
313
314
        It may raise either UnexpectedEndOfContainerError or
315
        UnknownContainerFormatError, depending on exactly what the string is.
316
        """
6803.2.5 by Martin
Make test_pack pass on Python 3
317
        inputs = [
318
            b"", b"x", b"Bazaar pack format 1 (introduced in 0.18)", b"bad\n"]
2506.2.6 by Andrew Bennetts
Add validate method to ContainerReader and BytesRecordReader.
319
        for input in inputs:
320
            reader = self.get_reader_for(input)
321
            self.assertRaises(
322
                (errors.UnexpectedEndOfContainerError,
323
                 errors.UnknownContainerFormatError),
324
                reader.validate)
325
326
    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.
327
        """validate raises UnknownRecordTypeError for unrecognised record
328
        types.
329
        """
2506.2.10 by Andrew Bennetts
Add '(introduced in 0.18)' to pack format string.
330
        reader = self.get_reader_for(
6803.2.5 by Martin
Make test_pack pass on Python 3
331
            b"Bazaar pack format 1 (introduced in 0.18)\nX")
2506.2.6 by Andrew Bennetts
Add validate method to ContainerReader and BytesRecordReader.
332
        self.assertRaises(errors.UnknownRecordTypeError, reader.validate)
333
334
    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.
335
        """validate raises ContainerHasExcessDataError if there are any bytes
336
        after the end of the container.
337
        """
2506.2.10 by Andrew Bennetts
Add '(introduced in 0.18)' to pack format string.
338
        reader = self.get_reader_for(
6803.2.5 by Martin
Make test_pack pass on Python 3
339
            b"Bazaar pack format 1 (introduced in 0.18)\nEcrud")
2506.2.6 by Andrew Bennetts
Add validate method to ContainerReader and BytesRecordReader.
340
        self.assertRaises(
341
            errors.ContainerHasExcessDataError, reader.validate)
342
343
    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.
344
        """validate raises UnexpectedEndOfContainerError if there's no end of
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
345
        container marker, even if the container up to this point has been
346
        valid.
2506.6.1 by Andrew Bennetts
Return a callable instead of a str from read, and add more validation.
347
        """
2506.2.10 by Andrew Bennetts
Add '(introduced in 0.18)' to pack format string.
348
        reader = self.get_reader_for(
6803.2.5 by Martin
Make test_pack pass on Python 3
349
            b"Bazaar pack format 1 (introduced in 0.18)\n")
2506.2.6 by Andrew Bennetts
Add validate method to ContainerReader and BytesRecordReader.
350
        self.assertRaises(
351
            errors.UnexpectedEndOfContainerError, reader.validate)
352
2506.6.1 by Andrew Bennetts
Return a callable instead of a str from read, and add more validation.
353
    def test_validate_duplicate_name(self):
354
        """validate raises DuplicateRecordNameError if the same name occurs
355
        multiple times in the container.
356
        """
357
        reader = self.get_reader_for(
6803.2.5 by Martin
Make test_pack pass on Python 3
358
            b"Bazaar pack format 1 (introduced in 0.18)\n"
359
            b"B0\nname\n\n"
360
            b"B0\nname\n\n"
361
            b"E")
2506.6.1 by Andrew Bennetts
Return a callable instead of a str from read, and add more validation.
362
        self.assertRaises(errors.DuplicateRecordNameError, reader.validate)
363
364
    def test_validate_undecodeable_name(self):
365
        """Names that aren't valid UTF-8 cause validate to fail."""
2506.2.10 by Andrew Bennetts
Add '(introduced in 0.18)' to pack format string.
366
        reader = self.get_reader_for(
6803.2.5 by Martin
Make test_pack pass on Python 3
367
            b"Bazaar pack format 1 (introduced in 0.18)\nB0\n\xcc\n\nE")
2506.6.1 by Andrew Bennetts
Return a callable instead of a str from read, and add more validation.
368
        self.assertRaises(errors.InvalidRecordError, reader.validate)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
369
2506.3.1 by Andrew Bennetts
More progress:
370
2506.3.2 by Andrew Bennetts
Test docstring tweaks, inspired by looking over the output of jml's testdoc tool.
371
class TestBytesRecordReader(tests.TestCase):
2916.2.13 by Andrew Bennetts
Improve some docstrings.
372
    """Tests for reading and validating Bytes records with
373
    BytesRecordReader.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
374
2916.2.13 by Andrew Bennetts
Improve some docstrings.
375
    Like TestContainerReader, this explicitly tests the reading of format 1
376
    data.  If a new version of the format is added, then a separate set of
377
    tests for reading that format should be added.
378
    """
2506.3.1 by Andrew Bennetts
More progress:
379
6803.2.5 by Martin
Make test_pack pass on Python 3
380
    def get_reader_for(self, data):
381
        stream = BytesIO(data)
2535.3.26 by Andrew Bennetts
Revert merge of container-format changes rejected for bzr.dev (i.e. undo andrew.bennetts@canonical.com-20070717044423-cetp5spep142xsr4).
382
        reader = pack.BytesRecordReader(stream)
2506.2.6 by Andrew Bennetts
Add validate method to ContainerReader and BytesRecordReader.
383
        return reader
384
2506.3.1 by Andrew Bennetts
More progress:
385
    def test_record_with_no_name(self):
386
        """Reading a Bytes record with no name returns an empty list of
387
        names.
388
        """
6803.2.5 by Martin
Make test_pack pass on Python 3
389
        reader = self.get_reader_for(b"5\n\naaaaa")
2506.6.1 by Andrew Bennetts
Return a callable instead of a str from read, and add more validation.
390
        names, get_bytes = reader.read()
2506.3.1 by Andrew Bennetts
More progress:
391
        self.assertEqual([], names)
6803.2.5 by Martin
Make test_pack pass on Python 3
392
        self.assertEqual(b'aaaaa', get_bytes(None))
2506.3.1 by Andrew Bennetts
More progress:
393
394
    def test_record_with_one_name(self):
395
        """Reading a Bytes record with one name returns a list of just that
396
        name.
397
        """
6803.2.5 by Martin
Make test_pack pass on Python 3
398
        reader = self.get_reader_for(b"5\nname1\n\naaaaa")
2506.6.1 by Andrew Bennetts
Return a callable instead of a str from read, and add more validation.
399
        names, get_bytes = reader.read()
6803.2.5 by Martin
Make test_pack pass on Python 3
400
        self.assertEqual([(b'name1', )], names)
401
        self.assertEqual(b'aaaaa', get_bytes(None))
2506.3.1 by Andrew Bennetts
More progress:
402
403
    def test_record_with_two_names(self):
404
        """Reading a Bytes record with two names returns a list of both names.
405
        """
6803.2.5 by Martin
Make test_pack pass on Python 3
406
        reader = self.get_reader_for(b"5\nname1\nname2\n\naaaaa")
2506.6.1 by Andrew Bennetts
Return a callable instead of a str from read, and add more validation.
407
        names, get_bytes = reader.read()
6803.2.5 by Martin
Make test_pack pass on Python 3
408
        self.assertEqual([(b'name1', ), (b'name2', )], names)
409
        self.assertEqual(b'aaaaa', get_bytes(None))
2682.1.1 by Robert Collins
* The ``bzrlib.pack`` interface has changed to use tuples of bytestrings
410
411
    def test_record_with_two_part_names(self):
412
        """Reading a Bytes record with a two_part name reads both."""
6803.2.5 by Martin
Make test_pack pass on Python 3
413
        reader = self.get_reader_for(b"5\nname1\x00name2\n\naaaaa")
2682.1.1 by Robert Collins
* The ``bzrlib.pack`` interface has changed to use tuples of bytestrings
414
        names, get_bytes = reader.read()
6803.2.5 by Martin
Make test_pack pass on Python 3
415
        self.assertEqual([(b'name1', b'name2', )], names)
416
        self.assertEqual(b'aaaaa', get_bytes(None))
2506.3.1 by Andrew Bennetts
More progress:
417
418
    def test_invalid_length(self):
419
        """If the length-prefix is not a number, parsing raises
420
        InvalidRecordError.
421
        """
6803.2.5 by Martin
Make test_pack pass on Python 3
422
        reader = self.get_reader_for(b"not a number\n")
2506.3.1 by Andrew Bennetts
More progress:
423
        self.assertRaises(errors.InvalidRecordError, reader.read)
2506.2.1 by Andrew Bennetts
Start implementing container format reading and writing.
424
2506.3.3 by Andrew Bennetts
Deal with EOF in the middle of a bytes record.
425
    def test_early_eof(self):
426
        """Tests for premature EOF occuring during parsing Bytes records with
427
        BytesRecordReader.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
428
2506.3.3 by Andrew Bennetts
Deal with EOF in the middle of a bytes record.
429
        A incomplete container might be interrupted at any point.  The
430
        BytesRecordReader needs to cope with the input stream running out no
431
        matter where it is in the parsing process.
432
433
        In all cases, UnexpectedEndOfContainerError should be raised.
434
        """
6803.2.5 by Martin
Make test_pack pass on Python 3
435
        complete_record = b"6\nname\n\nabcdef"
2506.3.3 by Andrew Bennetts
Deal with EOF in the middle of a bytes record.
436
        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.
437
            incomplete_record = complete_record[:count]
438
            reader = self.get_reader_for(incomplete_record)
439
            # We don't use assertRaises to make diagnosing failures easier
440
            # (assertRaises doesn't allow a custom failure message).
2506.3.3 by Andrew Bennetts
Deal with EOF in the middle of a bytes record.
441
            try:
2506.6.1 by Andrew Bennetts
Return a callable instead of a str from read, and add more validation.
442
                names, read_bytes = reader.read()
443
                read_bytes(None)
2506.3.3 by Andrew Bennetts
Deal with EOF in the middle of a bytes record.
444
            except errors.UnexpectedEndOfContainerError:
445
                pass
446
            else:
447
                self.fail(
448
                    "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.
449
                    % (incomplete_record,))
2506.3.3 by Andrew Bennetts
Deal with EOF in the middle of a bytes record.
450
2506.5.2 by Andrew Bennetts
Raise InvalidRecordError on invalid names.
451
    def test_initial_eof(self):
2506.3.3 by Andrew Bennetts
Deal with EOF in the middle of a bytes record.
452
        """EOF before any bytes read at all."""
6803.2.5 by Martin
Make test_pack pass on Python 3
453
        reader = self.get_reader_for(b"")
2506.3.3 by Andrew Bennetts
Deal with EOF in the middle of a bytes record.
454
        self.assertRaises(errors.UnexpectedEndOfContainerError, reader.read)
455
2506.5.2 by Andrew Bennetts
Raise InvalidRecordError on invalid names.
456
    def test_eof_after_length(self):
2506.3.3 by Andrew Bennetts
Deal with EOF in the middle of a bytes record.
457
        """EOF after reading the length and before reading name(s)."""
6803.2.5 by Martin
Make test_pack pass on Python 3
458
        reader = self.get_reader_for(b"123\n")
2506.3.3 by Andrew Bennetts
Deal with EOF in the middle of a bytes record.
459
        self.assertRaises(errors.UnexpectedEndOfContainerError, reader.read)
460
2506.5.2 by Andrew Bennetts
Raise InvalidRecordError on invalid names.
461
    def test_eof_during_name(self):
2506.3.3 by Andrew Bennetts
Deal with EOF in the middle of a bytes record.
462
        """EOF during reading a name."""
6803.2.5 by Martin
Make test_pack pass on Python 3
463
        reader = self.get_reader_for(b"123\nname")
2506.3.3 by Andrew Bennetts
Deal with EOF in the middle of a bytes record.
464
        self.assertRaises(errors.UnexpectedEndOfContainerError, reader.read)
465
2535.3.26 by Andrew Bennetts
Revert merge of container-format changes rejected for bzr.dev (i.e. undo andrew.bennetts@canonical.com-20070717044423-cetp5spep142xsr4).
466
    def test_read_invalid_name_whitespace(self):
467
        """Names must have no whitespace."""
468
        # A name with a space.
6803.2.5 by Martin
Make test_pack pass on Python 3
469
        reader = self.get_reader_for(b"0\nbad name\n\n")
2535.3.26 by Andrew Bennetts
Revert merge of container-format changes rejected for bzr.dev (i.e. undo andrew.bennetts@canonical.com-20070717044423-cetp5spep142xsr4).
470
        self.assertRaises(errors.InvalidRecordError, reader.read)
471
472
        # A name with a tab.
6803.2.5 by Martin
Make test_pack pass on Python 3
473
        reader = self.get_reader_for(b"0\nbad\tname\n\n")
2535.3.26 by Andrew Bennetts
Revert merge of container-format changes rejected for bzr.dev (i.e. undo andrew.bennetts@canonical.com-20070717044423-cetp5spep142xsr4).
474
        self.assertRaises(errors.InvalidRecordError, reader.read)
475
476
        # A name with a vertical tab.
6803.2.5 by Martin
Make test_pack pass on Python 3
477
        reader = self.get_reader_for(b"0\nbad\vname\n\n")
2535.3.26 by Andrew Bennetts
Revert merge of container-format changes rejected for bzr.dev (i.e. undo andrew.bennetts@canonical.com-20070717044423-cetp5spep142xsr4).
478
        self.assertRaises(errors.InvalidRecordError, reader.read)
479
480
    def test_validate_whitespace_in_name(self):
481
        """Names must have no whitespace."""
6803.2.5 by Martin
Make test_pack pass on Python 3
482
        reader = self.get_reader_for(b"0\nbad name\n\n")
2535.3.26 by Andrew Bennetts
Revert merge of container-format changes rejected for bzr.dev (i.e. undo andrew.bennetts@canonical.com-20070717044423-cetp5spep142xsr4).
483
        self.assertRaises(errors.InvalidRecordError, reader.validate)
484
2506.2.6 by Andrew Bennetts
Add validate method to ContainerReader and BytesRecordReader.
485
    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.
486
        """EOF during reading a record's prelude causes validate to fail."""
6803.2.5 by Martin
Make test_pack pass on Python 3
487
        reader = self.get_reader_for(b"")
2506.2.6 by Andrew Bennetts
Add validate method to ContainerReader and BytesRecordReader.
488
        self.assertRaises(
489
            errors.UnexpectedEndOfContainerError, reader.validate)
490
491
    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.
492
        """EOF during reading a record's body causes validate to fail."""
6803.2.5 by Martin
Make test_pack pass on Python 3
493
        reader = self.get_reader_for(b"1\n\n")
2506.2.6 by Andrew Bennetts
Add validate method to ContainerReader and BytesRecordReader.
494
        self.assertRaises(
495
            errors.UnexpectedEndOfContainerError, reader.validate)
496
497
    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.
498
        """An unparseable record length causes validate to fail."""
6803.2.5 by Martin
Make test_pack pass on Python 3
499
        reader = self.get_reader_for(b"\n\n")
2506.2.6 by Andrew Bennetts
Add validate method to ContainerReader and BytesRecordReader.
500
        self.assertRaises(
501
            errors.InvalidRecordError, reader.validate)
502
2506.6.1 by Andrew Bennetts
Return a callable instead of a str from read, and add more validation.
503
    def test_validate_undecodeable_name(self):
504
        """Names that aren't valid UTF-8 cause validate to fail."""
6803.2.5 by Martin
Make test_pack pass on Python 3
505
        reader = self.get_reader_for(b"0\n\xcc\n\n")
2506.6.1 by Andrew Bennetts
Return a callable instead of a str from read, and add more validation.
506
        self.assertRaises(errors.InvalidRecordError, reader.validate)
507
508
    def test_read_max_length(self):
509
        """If the max_length passed to the callable returned by read is not
510
        None, then no more than that many bytes will be read.
511
        """
6803.2.5 by Martin
Make test_pack pass on Python 3
512
        reader = self.get_reader_for(b"6\n\nabcdef")
2506.6.1 by Andrew Bennetts
Return a callable instead of a str from read, and add more validation.
513
        names, get_bytes = reader.read()
6803.2.5 by Martin
Make test_pack pass on Python 3
514
        self.assertEqual(b'abc', get_bytes(3))
2506.6.1 by Andrew Bennetts
Return a callable instead of a str from read, and add more validation.
515
516
    def test_read_no_max_length(self):
517
        """If the max_length passed to the callable returned by read is None,
518
        then all the bytes in the record will be read.
519
        """
6803.2.5 by Martin
Make test_pack pass on Python 3
520
        reader = self.get_reader_for(b"6\n\nabcdef")
2506.6.1 by Andrew Bennetts
Return a callable instead of a str from read, and add more validation.
521
        names, get_bytes = reader.read()
6803.2.5 by Martin
Make test_pack pass on Python 3
522
        self.assertEqual(b'abcdef', get_bytes(None))
2506.6.1 by Andrew Bennetts
Return a callable instead of a str from read, and add more validation.
523
524
    def test_repeated_read_calls(self):
525
        """Repeated calls to the callable returned from BytesRecordReader.read
526
        will not read beyond the end of the record.
527
        """
6803.2.5 by Martin
Make test_pack pass on Python 3
528
        reader = self.get_reader_for(b"6\n\nabcdefB3\nnext-record\nXXX")
2506.6.1 by Andrew Bennetts
Return a callable instead of a str from read, and add more validation.
529
        names, get_bytes = reader.read()
6803.2.5 by Martin
Make test_pack pass on Python 3
530
        self.assertEqual(b'abcdef', get_bytes(None))
531
        self.assertEqual(b'', get_bytes(None))
532
        self.assertEqual(b'', get_bytes(99))
2506.6.1 by Andrew Bennetts
Return a callable instead of a str from read, and add more validation.
533
534
2661.2.3 by Robert Collins
Review feedback.
535
class TestMakeReadvReader(tests.TestCaseWithTransport):
2661.2.2 by Robert Collins
* ``bzrlib.pack.make_readv_reader`` allows readv based access to pack
536
537
    def test_read_skipping_records(self):
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
538
        pack_data = BytesIO()
2661.2.2 by Robert Collins
* ``bzrlib.pack.make_readv_reader`` allows readv based access to pack
539
        writer = pack.ContainerWriter(pack_data.write)
540
        writer.begin()
541
        memos = []
6803.2.5 by Martin
Make test_pack pass on Python 3
542
        memos.append(writer.add_bytes_record(b'abc', names=[]))
543
        memos.append(writer.add_bytes_record(b'def', names=[(b'name1', )]))
544
        memos.append(writer.add_bytes_record(b'ghi', names=[(b'name2', )]))
545
        memos.append(writer.add_bytes_record(b'jkl', names=[]))
2661.2.2 by Robert Collins
* ``bzrlib.pack.make_readv_reader`` allows readv based access to pack
546
        writer.end()
547
        transport = self.get_transport()
7045.3.1 by Jelmer Vernooij
Fix another ~500 tests.
548
        transport.put_bytes('mypack', pack_data.getvalue())
2661.2.2 by Robert Collins
* ``bzrlib.pack.make_readv_reader`` allows readv based access to pack
549
        requested_records = [memos[0], memos[2]]
7045.3.1 by Jelmer Vernooij
Fix another ~500 tests.
550
        reader = pack.make_readv_reader(transport, 'mypack', requested_records)
2661.2.2 by Robert Collins
* ``bzrlib.pack.make_readv_reader`` allows readv based access to pack
551
        result = []
552
        for names, reader_func in reader.iter_records():
553
            result.append((names, reader_func(None)))
6803.2.5 by Martin
Make test_pack pass on Python 3
554
        self.assertEqual([([], b'abc'), ([(b'name2', )], b'ghi')], result)
2661.2.2 by Robert Collins
* ``bzrlib.pack.make_readv_reader`` allows readv based access to pack
555
556
557
class TestReadvFile(tests.TestCaseWithTransport):
2661.2.3 by Robert Collins
Review feedback.
558
    """Tests of the ReadVFile class.
559
560
    Error cases are deliberately undefined: this code adapts the underlying
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
561
    transport interface to a single 'streaming read' interface as
2661.2.3 by Robert Collins
Review feedback.
562
    ContainerReader needs.
563
    """
2661.2.2 by Robert Collins
* ``bzrlib.pack.make_readv_reader`` allows readv based access to pack
564
565
    def test_read_bytes(self):
2661.2.3 by Robert Collins
Review feedback.
566
        """Test reading of both single bytes and all bytes in a hunk."""
2661.2.2 by Robert Collins
* ``bzrlib.pack.make_readv_reader`` allows readv based access to pack
567
        transport = self.get_transport()
7045.3.1 by Jelmer Vernooij
Fix another ~500 tests.
568
        transport.put_bytes('sample', b'0123456789')
7143.15.2 by Jelmer Vernooij
Run autopep8.
569
        f = pack.ReadVFile(transport.readv(
570
            'sample', [(0, 1), (1, 2), (4, 1), (6, 2)]))
2661.2.2 by Robert Collins
* ``bzrlib.pack.make_readv_reader`` allows readv based access to pack
571
        results = []
572
        results.append(f.read(1))
573
        results.append(f.read(2))
574
        results.append(f.read(1))
575
        results.append(f.read(1))
576
        results.append(f.read(1))
6803.2.5 by Martin
Make test_pack pass on Python 3
577
        self.assertEqual([b'0', b'12', b'4', b'6', b'7'], results)
2661.2.2 by Robert Collins
* ``bzrlib.pack.make_readv_reader`` allows readv based access to pack
578
579
    def test_readline(self):
2661.2.3 by Robert Collins
Review feedback.
580
        """Test using readline() as ContainerReader does.
581
582
        This is always within a readv hunk, never across it.
583
        """
2661.2.2 by Robert Collins
* ``bzrlib.pack.make_readv_reader`` allows readv based access to pack
584
        transport = self.get_transport()
7045.3.1 by Jelmer Vernooij
Fix another ~500 tests.
585
        transport.put_bytes('sample', b'0\n2\n4\n')
586
        f = pack.ReadVFile(transport.readv('sample', [(0, 2), (2, 4)]))
2661.2.2 by Robert Collins
* ``bzrlib.pack.make_readv_reader`` allows readv based access to pack
587
        results = []
588
        results.append(f.readline())
589
        results.append(f.readline())
590
        results.append(f.readline())
6803.2.5 by Martin
Make test_pack pass on Python 3
591
        self.assertEqual([b'0\n', b'2\n', b'4\n'], results)
2661.2.2 by Robert Collins
* ``bzrlib.pack.make_readv_reader`` allows readv based access to pack
592
593
    def test_readline_and_read(self):
2661.2.3 by Robert Collins
Review feedback.
594
        """Test exercising one byte reads, readline, and then read again."""
2661.2.2 by Robert Collins
* ``bzrlib.pack.make_readv_reader`` allows readv based access to pack
595
        transport = self.get_transport()
7045.3.1 by Jelmer Vernooij
Fix another ~500 tests.
596
        transport.put_bytes('sample', b'0\n2\n4\n')
597
        f = pack.ReadVFile(transport.readv('sample', [(0, 6)]))
2661.2.2 by Robert Collins
* ``bzrlib.pack.make_readv_reader`` allows readv based access to pack
598
        results = []
599
        results.append(f.read(1))
600
        results.append(f.readline())
601
        results.append(f.read(4))
6803.2.5 by Martin
Make test_pack pass on Python 3
602
        self.assertEqual([b'0', b'\n', b'2\n4\n'], results)
2916.2.1 by Andrew Bennetts
Initial implementation of a 'push' parser for the container format.
603
604
605
class PushParserTestCase(tests.TestCase):
2916.2.13 by Andrew Bennetts
Improve some docstrings.
606
    """Base class for TestCases involving ContainerPushParser."""
2916.2.1 by Andrew Bennetts
Initial implementation of a 'push' parser for the container format.
607
608
    def make_parser_expecting_record_type(self):
609
        parser = pack.ContainerPushParser()
6803.2.5 by Martin
Make test_pack pass on Python 3
610
        parser.accept_bytes(b"Bazaar pack format 1 (introduced in 0.18)\n")
2916.2.1 by Andrew Bennetts
Initial implementation of a 'push' parser for the container format.
611
        return parser
612
613
    def make_parser_expecting_bytes_record(self):
614
        parser = pack.ContainerPushParser()
6803.2.5 by Martin
Make test_pack pass on Python 3
615
        parser.accept_bytes(b"Bazaar pack format 1 (introduced in 0.18)\nB")
2916.2.1 by Andrew Bennetts
Initial implementation of a 'push' parser for the container format.
616
        return parser
617
6803.2.5 by Martin
Make test_pack pass on Python 3
618
    def assertRecordParsing(self, expected_record, data):
2916.2.13 by Andrew Bennetts
Improve some docstrings.
619
        """Assert that 'bytes' is parsed as a given bytes record.
620
621
        :param expected_record: A tuple of (names, bytes).
622
        """
2916.2.1 by Andrew Bennetts
Initial implementation of a 'push' parser for the container format.
623
        parser = self.make_parser_expecting_bytes_record()
6803.2.5 by Martin
Make test_pack pass on Python 3
624
        parser.accept_bytes(data)
2916.2.1 by Andrew Bennetts
Initial implementation of a 'push' parser for the container format.
625
        parsed_records = parser.read_pending_records()
626
        self.assertEqual([expected_record], parsed_records)
627
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
628
2916.2.1 by Andrew Bennetts
Initial implementation of a 'push' parser for the container format.
629
class TestContainerPushParser(PushParserTestCase):
2916.2.13 by Andrew Bennetts
Improve some docstrings.
630
    """Tests for ContainerPushParser.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
631
2916.2.13 by Andrew Bennetts
Improve some docstrings.
632
    The ContainerPushParser reads format 1 containers, so these tests
633
    explicitly test how it reacts to format 1 data.  If a new version of the
634
    format is added, then separate tests for that format should be added.
635
    """
2916.2.1 by Andrew Bennetts
Initial implementation of a 'push' parser for the container format.
636
637
    def test_construct(self):
638
        """ContainerPushParser can be constructed."""
639
        pack.ContainerPushParser()
640
641
    def test_multiple_records_at_once(self):
2916.2.2 by Andrew Bennetts
Add a couple of docstrings to the tests.
642
        """If multiple records worth of data are fed to the parser in one
643
        string, the parser will correctly parse all the records.
644
645
        (A naive implementation might stop after parsing the first record.)
646
        """
2916.2.1 by Andrew Bennetts
Initial implementation of a 'push' parser for the container format.
647
        parser = self.make_parser_expecting_record_type()
6803.2.5 by Martin
Make test_pack pass on Python 3
648
        parser.accept_bytes(b"B5\nname1\n\nbody1B5\nname2\n\nbody2")
2916.2.1 by Andrew Bennetts
Initial implementation of a 'push' parser for the container format.
649
        self.assertEqual(
6803.2.5 by Martin
Make test_pack pass on Python 3
650
            [([(b'name1',)], b'body1'), ([(b'name2',)], b'body2')],
2916.2.1 by Andrew Bennetts
Initial implementation of a 'push' parser for the container format.
651
            parser.read_pending_records())
652
4464.1.1 by Aaron Bentley
ContainerPushParser.accept_bytes handles zero-length records correctly.
653
    def test_multiple_empty_records_at_once(self):
654
        """If multiple empty records worth of data are fed to the parser in one
655
        string, the parser will correctly parse all the records.
656
657
        (A naive implementation might stop after parsing the first empty
658
        record, because the buffer size had not changed.)
659
        """
660
        parser = self.make_parser_expecting_record_type()
6803.2.5 by Martin
Make test_pack pass on Python 3
661
        parser.accept_bytes(b"B0\nname1\n\nB0\nname2\n\n")
4464.1.1 by Aaron Bentley
ContainerPushParser.accept_bytes handles zero-length records correctly.
662
        self.assertEqual(
6803.2.5 by Martin
Make test_pack pass on Python 3
663
            [([(b'name1',)], b''), ([(b'name2',)], b'')],
4464.1.1 by Aaron Bentley
ContainerPushParser.accept_bytes handles zero-length records correctly.
664
            parser.read_pending_records())
665
2916.2.1 by Andrew Bennetts
Initial implementation of a 'push' parser for the container format.
666
667
class TestContainerPushParserBytesParsing(PushParserTestCase):
2916.2.13 by Andrew Bennetts
Improve some docstrings.
668
    """Tests for reading Bytes records with ContainerPushParser.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
669
2916.2.13 by Andrew Bennetts
Improve some docstrings.
670
    The ContainerPushParser reads format 1 containers, so these tests
671
    explicitly test how it reacts to format 1 data.  If a new version of the
672
    format is added, then separate tests for that format should be added.
673
    """
2916.2.1 by Andrew Bennetts
Initial implementation of a 'push' parser for the container format.
674
675
    def test_record_with_no_name(self):
676
        """Reading a Bytes record with no name returns an empty list of
677
        names.
678
        """
6803.2.5 by Martin
Make test_pack pass on Python 3
679
        self.assertRecordParsing(([], b'aaaaa'), b"5\n\naaaaa")
2916.2.1 by Andrew Bennetts
Initial implementation of a 'push' parser for the container format.
680
681
    def test_record_with_one_name(self):
682
        """Reading a Bytes record with one name returns a list of just that
683
        name.
684
        """
685
        self.assertRecordParsing(
6803.2.5 by Martin
Make test_pack pass on Python 3
686
            ([(b'name1', )], b'aaaaa'),
687
            b"5\nname1\n\naaaaa")
2916.2.1 by Andrew Bennetts
Initial implementation of a 'push' parser for the container format.
688
689
    def test_record_with_two_names(self):
690
        """Reading a Bytes record with two names returns a list of both names.
691
        """
692
        self.assertRecordParsing(
6803.2.5 by Martin
Make test_pack pass on Python 3
693
            ([(b'name1', ), (b'name2', )], b'aaaaa'),
694
            b"5\nname1\nname2\n\naaaaa")
2916.2.1 by Andrew Bennetts
Initial implementation of a 'push' parser for the container format.
695
696
    def test_record_with_two_part_names(self):
697
        """Reading a Bytes record with a two_part name reads both."""
698
        self.assertRecordParsing(
6803.2.5 by Martin
Make test_pack pass on Python 3
699
            ([(b'name1', b'name2')], b'aaaaa'),
700
            b"5\nname1\x00name2\n\naaaaa")
2916.2.1 by Andrew Bennetts
Initial implementation of a 'push' parser for the container format.
701
702
    def test_invalid_length(self):
703
        """If the length-prefix is not a number, parsing raises
704
        InvalidRecordError.
705
        """
706
        parser = self.make_parser_expecting_bytes_record()
707
        self.assertRaises(
6803.2.5 by Martin
Make test_pack pass on Python 3
708
            errors.InvalidRecordError, parser.accept_bytes, b"not a number\n")
2916.2.1 by Andrew Bennetts
Initial implementation of a 'push' parser for the container format.
709
710
    def test_incomplete_record(self):
711
        """If the bytes seen so far don't form a complete record, then there
712
        will be nothing returned by read_pending_records.
713
        """
714
        parser = self.make_parser_expecting_bytes_record()
6803.2.5 by Martin
Make test_pack pass on Python 3
715
        parser.accept_bytes(b"5\n\nabcd")
2916.2.1 by Andrew Bennetts
Initial implementation of a 'push' parser for the container format.
716
        self.assertEqual([], parser.read_pending_records())
717
718
    def test_accept_nothing(self):
719
        """The edge case of parsing an empty string causes no error."""
720
        parser = self.make_parser_expecting_bytes_record()
6803.2.5 by Martin
Make test_pack pass on Python 3
721
        parser.accept_bytes(b"")
2916.2.1 by Andrew Bennetts
Initial implementation of a 'push' parser for the container format.
722
6803.2.5 by Martin
Make test_pack pass on Python 3
723
    def assertInvalidRecord(self, data):
724
        """Assert that parsing the given bytes raises InvalidRecordError."""
2916.2.1 by Andrew Bennetts
Initial implementation of a 'push' parser for the container format.
725
        parser = self.make_parser_expecting_bytes_record()
726
        self.assertRaises(
6803.2.5 by Martin
Make test_pack pass on Python 3
727
            errors.InvalidRecordError, parser.accept_bytes, data)
2916.2.1 by Andrew Bennetts
Initial implementation of a 'push' parser for the container format.
728
729
    def test_read_invalid_name_whitespace(self):
730
        """Names must have no whitespace."""
731
        # A name with a space.
6803.2.5 by Martin
Make test_pack pass on Python 3
732
        self.assertInvalidRecord(b"0\nbad name\n\n")
2916.2.1 by Andrew Bennetts
Initial implementation of a 'push' parser for the container format.
733
734
        # A name with a tab.
6803.2.5 by Martin
Make test_pack pass on Python 3
735
        self.assertInvalidRecord(b"0\nbad\tname\n\n")
2916.2.1 by Andrew Bennetts
Initial implementation of a 'push' parser for the container format.
736
737
        # A name with a vertical tab.
6803.2.5 by Martin
Make test_pack pass on Python 3
738
        self.assertInvalidRecord(b"0\nbad\vname\n\n")
2916.2.1 by Andrew Bennetts
Initial implementation of a 'push' parser for the container format.
739
740
    def test_repeated_read_pending_records(self):
741
        """read_pending_records will not return the same record twice."""
742
        parser = self.make_parser_expecting_bytes_record()
6803.2.5 by Martin
Make test_pack pass on Python 3
743
        parser.accept_bytes(b"6\n\nabcdef")
744
        self.assertEqual([([], b'abcdef')], parser.read_pending_records())
2916.2.1 by Andrew Bennetts
Initial implementation of a 'push' parser for the container format.
745
        self.assertEqual([], parser.read_pending_records())