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