~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_rio.py

Merge bzr.dev (and fix NEWS)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006, 2007, 2009, 2010, 2011, 2016 Canonical Ltd
 
1
# Copyright (C) 2005, 2006 by Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
12
12
#
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
16
 
17
17
"""Tests for rio serialization
18
18
 
22
22
but this depends on the transport.
23
23
"""
24
24
 
25
 
import re
 
25
import cStringIO
 
26
import os
 
27
import sys
26
28
from tempfile import TemporaryFile
27
29
 
28
 
from bzrlib import (
29
 
    rio,
30
 
    )
31
 
from bzrlib.tests import TestCase
32
 
from bzrlib.rio import (
33
 
    RioReader,
34
 
    Stanza,
35
 
    read_stanza,
36
 
    read_stanzas,
37
 
    rio_file,
38
 
    )
 
30
from bzrlib.tests import TestCaseInTempDir, TestCase
 
31
from bzrlib.rio import (RioWriter, Stanza, read_stanza, read_stanzas, rio_file,
 
32
                        RioReader)
39
33
 
40
34
 
41
35
class TestRio(TestCase):
46
40
        self.assertTrue('number' in s)
47
41
        self.assertFalse('color' in s)
48
42
        self.assertFalse('42' in s)
49
 
        self.assertEqual(list(s.iter_pairs()),
 
43
        self.assertEquals(list(s.iter_pairs()),
50
44
                [('name', 'fred'), ('number', '42')])
51
 
        self.assertEqual(s.get('number'), '42')
52
 
        self.assertEqual(s.get('name'), 'fred')
 
45
        self.assertEquals(s.get('number'), '42')
 
46
        self.assertEquals(s.get('name'), 'fred')
53
47
 
54
48
    def test_value_checks(self):
55
49
        """rio checks types on construction"""
56
50
        # these aren't enforced at construction time
57
51
        ## self.assertRaises(ValueError,
58
52
        ##        Stanza, complex=42 + 3j)
59
 
        ## self.assertRaises(ValueError,
 
53
        ## self.assertRaises(ValueError, 
60
54
        ##        Stanza, several=range(10))
61
55
 
62
56
    def test_empty_value(self):
68
62
    def test_to_lines(self):
69
63
        """Write simple rio stanza to string"""
70
64
        s = Stanza(number='42', name='fred')
71
 
        self.assertEqual(list(s.to_lines()),
 
65
        self.assertEquals(list(s.to_lines()),
72
66
                ['name: fred\n',
73
67
                 'number: 42\n'])
74
68
 
76
70
        """Convert rio Stanza to dictionary"""
77
71
        s = Stanza(number='42', name='fred')
78
72
        sd = s.as_dict()
79
 
        self.assertEqual(sd, dict(number='42', name='fred'))
 
73
        self.assertEquals(sd, dict(number='42', name='fred'))
80
74
 
81
75
    def test_to_file(self):
82
76
        """Write rio to file"""
102
96
''')
103
97
        tmpf.seek(0)
104
98
        s2 = read_stanza(tmpf)
105
 
        self.assertEqual(s, s2)
 
99
        self.assertEquals(s, s2)
106
100
 
107
101
    def test_read_stanza(self):
108
102
        """Load stanza from string"""
115
109
        s = read_stanza(lines)
116
110
        self.assertTrue('revision' in s)
117
111
        self.assertEqualDiff(s.get('revision'), 'mbp@sourcefrog.net-123-abc')
118
 
        self.assertEqual(list(s.iter_pairs()),
 
112
        self.assertEquals(list(s.iter_pairs()),
119
113
                [('revision', 'mbp@sourcefrog.net-123-abc'),
120
114
                 ('timestamp', '1130653962'),
121
115
                 ('timezone', '36000'),
122
116
                 ('committer', "Martin Pool <mbp@test.sourcefrog.net>")])
123
 
        self.assertEqual(len(s), 4)
 
117
        self.assertEquals(len(s), 4)
124
118
 
125
119
    def test_repeated_field(self):
126
120
        """Repeated field in rio"""
127
121
        s = Stanza()
128
 
        for k, v in [('a', '10'), ('b', '20'), ('a', '100'), ('b', '200'),
 
122
        for k, v in [('a', '10'), ('b', '20'), ('a', '100'), ('b', '200'), 
129
123
                     ('a', '1000'), ('b', '2000')]:
130
124
            s.add(k, v)
131
125
        s2 = read_stanza(s.to_lines())
132
 
        self.assertEqual(s, s2)
133
 
        self.assertEqual(s.get_all('a'), map(str, [10, 100, 1000]))
134
 
        self.assertEqual(s.get_all('b'), map(str, [20, 200, 2000]))
 
126
        self.assertEquals(s, s2)
 
127
        self.assertEquals(s.get_all('a'), map(str, [10, 100, 1000]))
 
128
        self.assertEquals(s.get_all('b'), map(str, [20, 200, 2000]))
135
129
 
136
130
    def test_backslash(self):
137
131
        s = Stanza(q='\\')
138
132
        t = s.to_string()
139
133
        self.assertEqualDiff(t, 'q: \\\n')
140
134
        s2 = read_stanza(s.to_lines())
141
 
        self.assertEqual(s, s2)
 
135
        self.assertEquals(s, s2)
142
136
 
143
137
    def test_blank_line(self):
144
138
        s = Stanza(none='', one='\n', two='\n\n')
145
139
        self.assertEqualDiff(s.to_string(), """\
146
 
none:\x20
147
 
one:\x20
 
140
none: 
 
141
one: 
148
142
\t
149
 
two:\x20
 
143
two: 
150
144
\t
151
145
\t
152
146
""")
153
147
        s2 = read_stanza(s.to_lines())
154
 
        self.assertEqual(s, s2)
 
148
        self.assertEquals(s, s2)
155
149
 
156
150
    def test_whitespace_value(self):
157
151
        s = Stanza(space=' ', tabs='\t\t\t', combo='\n\t\t\n')
158
152
        self.assertEqualDiff(s.to_string(), """\
159
 
combo:\x20
 
153
combo: 
160
154
\t\t\t
161
155
\t
162
 
space:\x20\x20
 
156
space:  
163
157
tabs: \t\t\t
164
158
""")
165
159
        s2 = read_stanza(s.to_lines())
166
 
        self.assertEqual(s, s2)
 
160
        self.assertEquals(s, s2)
167
161
        self.rio_file_stanzas([s])
168
162
 
169
163
    def test_quoted(self):
170
164
        """rio quoted string cases"""
171
 
        s = Stanza(q1='"hello"',
172
 
                   q2=' "for',
 
165
        s = Stanza(q1='"hello"', 
 
166
                   q2=' "for', 
173
167
                   q3='\n\n"for"\n',
174
168
                   q4='for\n"\nfor',
175
169
                   q5='\n',
176
 
                   q6='"',
 
170
                   q6='"', 
177
171
                   q7='""',
178
172
                   q8='\\',
179
173
                   q9='\\"\\"',
180
174
                   )
181
175
        s2 = read_stanza(s.to_lines())
182
 
        self.assertEqual(s, s2)
 
176
        self.assertEquals(s, s2)
183
177
        # apparent bug in read_stanza
184
178
        # s3 = read_stanza(self.stanzas_to_str([s]))
185
 
        # self.assertEqual(s, s3)
 
179
        # self.assertEquals(s, s3)
186
180
 
187
181
    def test_read_empty(self):
188
182
        """Detect end of rio file"""
189
183
        s = read_stanza([])
190
184
        self.assertEqual(s, None)
191
185
        self.assertTrue(s is None)
192
 
 
193
 
    def test_read_nul_byte(self):
194
 
        """File consisting of a nul byte causes an error."""
195
 
        self.assertRaises(ValueError, read_stanza, ['\0'])
196
 
 
197
 
    def test_read_nul_bytes(self):
198
 
        """File consisting of many nul bytes causes an error."""
199
 
        self.assertRaises(ValueError, read_stanza, ['\0' * 100])
200
 
 
 
186
        
201
187
    def test_read_iter(self):
202
188
        """Read several stanzas from file"""
203
189
        tmpf = TemporaryFile()
214
200
        reader = read_stanzas(tmpf)
215
201
        read_iter = iter(reader)
216
202
        stuff = list(reader)
217
 
        self.assertEqual(stuff,
 
203
        self.assertEqual(stuff, 
218
204
                [ Stanza(version_header='1'),
219
205
                  Stanza(name="foo", val='123'),
220
206
                  Stanza(name="bar", val='129319'), ])
238
224
""")
239
225
        tmpf.seek(0)
240
226
        s = read_stanza(tmpf)
241
 
        self.assertEqual(s, Stanza(version_header='1'))
 
227
        self.assertEquals(s, Stanza(version_header='1'))
242
228
        s = read_stanza(tmpf)
243
 
        self.assertEqual(s, Stanza(name="foo", val='123'))
 
229
        self.assertEquals(s, Stanza(name="foo", val='123'))
244
230
        s = read_stanza(tmpf)
245
231
        self.assertEqualDiff(s.get('name'), 'quoted')
246
232
        self.assertEqualDiff(s.get('address'), '  "Willowglen"\n  42 Wallaby Way\n  Sydney')
247
233
        s = read_stanza(tmpf)
248
 
        self.assertEqual(s, Stanza(name="bar", val='129319'))
 
234
        self.assertEquals(s, Stanza(name="bar", val='129319'))
249
235
        s = read_stanza(tmpf)
250
 
        self.assertEqual(s, None)
 
236
        self.assertEquals(s, None)
251
237
        self.check_rio_file(tmpf)
252
238
 
253
239
    def check_rio_file(self, real_file):
254
240
        real_file.seek(0)
255
241
        read_write = rio_file(RioReader(real_file)).read()
256
242
        real_file.seek(0)
257
 
        self.assertEqual(read_write, real_file.read())
 
243
        self.assertEquals(read_write, real_file.read())
258
244
 
259
245
    @staticmethod
260
246
    def stanzas_to_str(stanzas):
269
255
        tmpf.write('''\
270
256
s: "one"
271
257
 
272
 
s:\x20
 
258
s: 
273
259
\t"one"
274
260
\t
275
261
 
279
265
 
280
266
s: """
281
267
 
282
 
s:\x20
 
268
s: 
283
269
\t
284
270
 
285
271
s: \\
286
272
 
287
 
s:\x20
 
273
s: 
288
274
\t\\
289
275
\t\\\\
290
276
\t
315
301
        for expected in expected_vals:
316
302
            stanza = read_stanza(tmpf)
317
303
            self.rio_file_stanzas([stanza])
318
 
            self.assertEqual(len(stanza), 1)
 
304
            self.assertEquals(len(stanza), 1)
319
305
            self.assertEqualDiff(stanza.get('s'), expected)
320
306
 
321
307
    def test_write_empty_stanza(self):
322
308
        """Write empty stanza"""
323
309
        l = list(Stanza().to_lines())
324
 
        self.assertEqual(l, [])
 
310
        self.assertEquals(l, [])
325
311
 
326
312
    def test_rio_raises_type_error(self):
327
313
        """TypeError on adding invalid type to Stanza"""
334
320
        self.assertRaises(TypeError, s.add, 10, {})
335
321
 
336
322
    def test_rio_unicode(self):
 
323
        # intentionally use cStringIO which doesn't accomodate unencoded unicode objects
 
324
        sio = cStringIO.StringIO()
337
325
        uni_data = u'\N{KATAKANA LETTER O}'
338
326
        s = Stanza(foo=uni_data)
339
 
        self.assertEqual(s.get('foo'), uni_data)
 
327
        self.assertEquals(s.get('foo'), uni_data)
340
328
        raw_lines = s.to_lines()
341
 
        self.assertEqual(raw_lines,
 
329
        self.assertEquals(raw_lines,
342
330
                ['foo: ' + uni_data.encode('utf-8') + '\n'])
343
331
        new_s = read_stanza(raw_lines)
344
 
        self.assertEqual(new_s.get('foo'), uni_data)
345
 
 
346
 
    def test_rio_to_unicode(self):
347
 
        uni_data = u'\N{KATAKANA LETTER O}'
348
 
        s = Stanza(foo=uni_data)
349
 
        unicode_str = s.to_unicode()
350
 
        self.assertEqual(u'foo: %s\n' % (uni_data,), unicode_str)
351
 
        new_s = rio.read_stanza_unicode(unicode_str.splitlines(True))
352
 
        self.assertEqual(uni_data, new_s.get('foo'))
353
 
 
354
 
    def test_nested_rio_unicode(self):
355
 
        uni_data = u'\N{KATAKANA LETTER O}'
356
 
        s = Stanza(foo=uni_data)
357
 
        parent_stanza = Stanza(child=s.to_unicode())
358
 
        raw_lines = parent_stanza.to_lines()
359
 
        self.assertEqual(['child: foo: ' + uni_data.encode('utf-8') + '\n',
360
 
                          '\t\n',
361
 
                         ], raw_lines)
362
 
        new_parent = read_stanza(raw_lines)
363
 
        child_text = new_parent.get('child')
364
 
        self.assertEqual(u'foo: %s\n' % uni_data, child_text)
365
 
        new_child = rio.read_stanza_unicode(child_text.splitlines(True))
366
 
        self.assertEqual(uni_data, new_child.get('foo'))
367
 
 
368
 
    def mail_munge(self, lines, dos_nl=True):
369
 
        new_lines = []
370
 
        for line in lines:
371
 
            line = re.sub(' *\n', '\n', line)
372
 
            if dos_nl:
373
 
                line = re.sub('([^\r])\n', '\\1\r\n', line)
374
 
            new_lines.append(line)
375
 
        return new_lines
376
 
 
377
 
    def test_patch_rio(self):
378
 
        stanza = Stanza(data='#\n\r\\r ', space=' ' * 255, hash='#' * 255)
379
 
        lines = rio.to_patch_lines(stanza)
380
 
        for line in lines:
381
 
            self.assertContainsRe(line, '^# ')
382
 
            self.assertTrue(72 >= len(line))
383
 
        for line in rio.to_patch_lines(stanza, max_width=12):
384
 
            self.assertTrue(12 >= len(line))
385
 
        new_stanza = rio.read_patch_stanza(self.mail_munge(lines,
386
 
                                                           dos_nl=False))
387
 
        lines = self.mail_munge(lines)
388
 
        new_stanza = rio.read_patch_stanza(lines)
389
 
        self.assertEqual('#\n\r\\r ', new_stanza.get('data'))
390
 
        self.assertEqual(' '* 255, new_stanza.get('space'))
391
 
        self.assertEqual('#'* 255, new_stanza.get('hash'))
392
 
 
393
 
    def test_patch_rio_linebreaks(self):
394
 
        stanza = Stanza(breaktest='linebreak -/'*30)
395
 
        self.assertContainsRe(rio.to_patch_lines(stanza, 71)[0],
396
 
                              'linebreak\\\\\n')
397
 
        stanza = Stanza(breaktest='linebreak-/'*30)
398
 
        self.assertContainsRe(rio.to_patch_lines(stanza, 70)[0],
399
 
                              'linebreak-\\\\\n')
400
 
        stanza = Stanza(breaktest='linebreak/'*30)
401
 
        self.assertContainsRe(rio.to_patch_lines(stanza, 70)[0],
402
 
                              'linebreak\\\\\n')
 
332
        self.assertEquals(new_s.get('foo'), uni_data)
 
333