~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_rio.py

  • Committer: Tarmac
  • Author(s): Vincent Ladeuil, Patch Queue Manager, Jelmer Vernooij
  • Date: 2017-01-17 16:20:41 UTC
  • mfrom: (6619.1.2 trunk)
  • Revision ID: tarmac-20170117162041-oo62uk1qsmgc9j31
Merge 2.7 into trunk including fixes for bugs #1622039, #1644003, #1579093 and #1645017. [r=vila]

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005 by Canonical Ltd
 
1
# Copyright (C) 2005, 2006, 2007, 2009, 2010, 2011, 2016 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 os
26
 
import sys
 
25
import re
27
26
from tempfile import TemporaryFile
28
27
 
29
 
from bzrlib.tests import TestCaseInTempDir, TestCase
30
 
from bzrlib.rio import RioWriter, Stanza, read_stanza, read_stanzas
 
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
    )
31
39
 
32
40
 
33
41
class TestRio(TestCase):
38
46
        self.assertTrue('number' in s)
39
47
        self.assertFalse('color' in s)
40
48
        self.assertFalse('42' in s)
41
 
        self.assertEquals(list(s.iter_pairs()),
 
49
        self.assertEqual(list(s.iter_pairs()),
42
50
                [('name', 'fred'), ('number', '42')])
43
 
        self.assertEquals(s.get('number'), '42')
44
 
        self.assertEquals(s.get('name'), 'fred')
 
51
        self.assertEqual(s.get('number'), '42')
 
52
        self.assertEqual(s.get('name'), 'fred')
45
53
 
46
54
    def test_value_checks(self):
47
55
        """rio checks types on construction"""
48
56
        # these aren't enforced at construction time
49
57
        ## self.assertRaises(ValueError,
50
58
        ##        Stanza, complex=42 + 3j)
51
 
        ## self.assertRaises(ValueError, 
 
59
        ## self.assertRaises(ValueError,
52
60
        ##        Stanza, several=range(10))
53
61
 
54
62
    def test_empty_value(self):
60
68
    def test_to_lines(self):
61
69
        """Write simple rio stanza to string"""
62
70
        s = Stanza(number='42', name='fred')
63
 
        self.assertEquals(list(s.to_lines()),
 
71
        self.assertEqual(list(s.to_lines()),
64
72
                ['name: fred\n',
65
73
                 'number: 42\n'])
66
74
 
 
75
    def test_as_dict(self):
 
76
        """Convert rio Stanza to dictionary"""
 
77
        s = Stanza(number='42', name='fred')
 
78
        sd = s.as_dict()
 
79
        self.assertEqual(sd, dict(number='42', name='fred'))
 
80
 
67
81
    def test_to_file(self):
68
82
        """Write rio to file"""
69
83
        tmpf = TemporaryFile()
88
102
''')
89
103
        tmpf.seek(0)
90
104
        s2 = read_stanza(tmpf)
91
 
        self.assertEquals(s, s2)
 
105
        self.assertEqual(s, s2)
92
106
 
93
107
    def test_read_stanza(self):
94
108
        """Load stanza from string"""
101
115
        s = read_stanza(lines)
102
116
        self.assertTrue('revision' in s)
103
117
        self.assertEqualDiff(s.get('revision'), 'mbp@sourcefrog.net-123-abc')
104
 
        self.assertEquals(list(s.iter_pairs()),
 
118
        self.assertEqual(list(s.iter_pairs()),
105
119
                [('revision', 'mbp@sourcefrog.net-123-abc'),
106
120
                 ('timestamp', '1130653962'),
107
121
                 ('timezone', '36000'),
108
122
                 ('committer', "Martin Pool <mbp@test.sourcefrog.net>")])
109
 
        self.assertEquals(len(s), 4)
 
123
        self.assertEqual(len(s), 4)
110
124
 
111
125
    def test_repeated_field(self):
112
126
        """Repeated field in rio"""
113
127
        s = Stanza()
114
 
        for k, v in [('a', '10'), ('b', '20'), ('a', '100'), ('b', '200'), 
 
128
        for k, v in [('a', '10'), ('b', '20'), ('a', '100'), ('b', '200'),
115
129
                     ('a', '1000'), ('b', '2000')]:
116
130
            s.add(k, v)
117
131
        s2 = read_stanza(s.to_lines())
118
 
        self.assertEquals(s, s2)
119
 
        self.assertEquals(s.get_all('a'), map(str, [10, 100, 1000]))
120
 
        self.assertEquals(s.get_all('b'), map(str, [20, 200, 2000]))
 
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]))
121
135
 
122
136
    def test_backslash(self):
123
137
        s = Stanza(q='\\')
124
138
        t = s.to_string()
125
139
        self.assertEqualDiff(t, 'q: \\\n')
126
140
        s2 = read_stanza(s.to_lines())
127
 
        self.assertEquals(s, s2)
 
141
        self.assertEqual(s, s2)
128
142
 
129
143
    def test_blank_line(self):
130
144
        s = Stanza(none='', one='\n', two='\n\n')
131
145
        self.assertEqualDiff(s.to_string(), """\
132
 
none: 
133
 
one: 
 
146
none:\x20
 
147
one:\x20
134
148
\t
135
 
two: 
 
149
two:\x20
136
150
\t
137
151
\t
138
152
""")
139
153
        s2 = read_stanza(s.to_lines())
140
 
        self.assertEquals(s, s2)
 
154
        self.assertEqual(s, s2)
141
155
 
142
156
    def test_whitespace_value(self):
143
157
        s = Stanza(space=' ', tabs='\t\t\t', combo='\n\t\t\n')
144
158
        self.assertEqualDiff(s.to_string(), """\
145
 
combo: 
 
159
combo:\x20
146
160
\t\t\t
147
161
\t
148
 
space:  
 
162
space:\x20\x20
149
163
tabs: \t\t\t
150
164
""")
151
165
        s2 = read_stanza(s.to_lines())
152
 
        self.assertEquals(s, s2)
 
166
        self.assertEqual(s, s2)
 
167
        self.rio_file_stanzas([s])
153
168
 
154
169
    def test_quoted(self):
155
170
        """rio quoted string cases"""
156
 
        s = Stanza(q1='"hello"', 
157
 
                   q2=' "for', 
 
171
        s = Stanza(q1='"hello"',
 
172
                   q2=' "for',
158
173
                   q3='\n\n"for"\n',
159
174
                   q4='for\n"\nfor',
160
175
                   q5='\n',
161
 
                   q6='"', 
 
176
                   q6='"',
162
177
                   q7='""',
163
178
                   q8='\\',
164
179
                   q9='\\"\\"',
165
180
                   )
166
181
        s2 = read_stanza(s.to_lines())
167
 
        self.assertEquals(s, s2)
 
182
        self.assertEqual(s, s2)
 
183
        # apparent bug in read_stanza
 
184
        # s3 = read_stanza(self.stanzas_to_str([s]))
 
185
        # self.assertEqual(s, s3)
168
186
 
169
187
    def test_read_empty(self):
170
188
        """Detect end of rio file"""
171
189
        s = read_stanza([])
172
190
        self.assertEqual(s, None)
173
191
        self.assertTrue(s is None)
174
 
        
 
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
 
175
201
    def test_read_iter(self):
176
202
        """Read several stanzas from file"""
177
203
        tmpf = TemporaryFile()
188
214
        reader = read_stanzas(tmpf)
189
215
        read_iter = iter(reader)
190
216
        stuff = list(reader)
191
 
        self.assertEqual(stuff, 
 
217
        self.assertEqual(stuff,
192
218
                [ Stanza(version_header='1'),
193
219
                  Stanza(name="foo", val='123'),
194
220
                  Stanza(name="bar", val='129319'), ])
212
238
""")
213
239
        tmpf.seek(0)
214
240
        s = read_stanza(tmpf)
215
 
        self.assertEquals(s, Stanza(version_header='1'))
 
241
        self.assertEqual(s, Stanza(version_header='1'))
216
242
        s = read_stanza(tmpf)
217
 
        self.assertEquals(s, Stanza(name="foo", val='123'))
 
243
        self.assertEqual(s, Stanza(name="foo", val='123'))
218
244
        s = read_stanza(tmpf)
219
245
        self.assertEqualDiff(s.get('name'), 'quoted')
220
246
        self.assertEqualDiff(s.get('address'), '  "Willowglen"\n  42 Wallaby Way\n  Sydney')
221
247
        s = read_stanza(tmpf)
222
 
        self.assertEquals(s, Stanza(name="bar", val='129319'))
 
248
        self.assertEqual(s, Stanza(name="bar", val='129319'))
223
249
        s = read_stanza(tmpf)
224
 
        self.assertEquals(s, None)
 
250
        self.assertEqual(s, None)
 
251
        self.check_rio_file(tmpf)
 
252
 
 
253
    def check_rio_file(self, real_file):
 
254
        real_file.seek(0)
 
255
        read_write = rio_file(RioReader(real_file)).read()
 
256
        real_file.seek(0)
 
257
        self.assertEqual(read_write, real_file.read())
 
258
 
 
259
    @staticmethod
 
260
    def stanzas_to_str(stanzas):
 
261
        return rio_file(stanzas).read()
 
262
 
 
263
    def rio_file_stanzas(self, stanzas):
 
264
        new_stanzas = list(RioReader(rio_file(stanzas)))
 
265
        self.assertEqual(new_stanzas, stanzas)
225
266
 
226
267
    def test_tricky_quoted(self):
227
268
        tmpf = TemporaryFile()
228
269
        tmpf.write('''\
229
270
s: "one"
230
271
 
231
 
s: 
 
272
s:\x20
232
273
\t"one"
233
274
\t
234
275
 
238
279
 
239
280
s: """
240
281
 
241
 
s: 
 
282
s:\x20
242
283
\t
243
284
 
244
285
s: \\
245
286
 
246
 
s: 
 
287
s:\x20
247
288
\t\\
248
289
\t\\\\
249
290
\t
273
314
            ]
274
315
        for expected in expected_vals:
275
316
            stanza = read_stanza(tmpf)
276
 
            self.assertEquals(len(stanza), 1)
 
317
            self.rio_file_stanzas([stanza])
 
318
            self.assertEqual(len(stanza), 1)
277
319
            self.assertEqualDiff(stanza.get('s'), expected)
278
320
 
279
321
    def test_write_empty_stanza(self):
280
322
        """Write empty stanza"""
281
323
        l = list(Stanza().to_lines())
282
 
        self.assertEquals(l, [])
 
324
        self.assertEqual(l, [])
 
325
 
 
326
    def test_rio_raises_type_error(self):
 
327
        """TypeError on adding invalid type to Stanza"""
 
328
        s = Stanza()
 
329
        self.assertRaises(TypeError, s.add, 'foo', {})
 
330
 
 
331
    def test_rio_raises_type_error_key(self):
 
332
        """TypeError on adding invalid type to Stanza"""
 
333
        s = Stanza()
 
334
        self.assertRaises(TypeError, s.add, 10, {})
 
335
 
 
336
    def test_rio_unicode(self):
 
337
        uni_data = u'\N{KATAKANA LETTER O}'
 
338
        s = Stanza(foo=uni_data)
 
339
        self.assertEqual(s.get('foo'), uni_data)
 
340
        raw_lines = s.to_lines()
 
341
        self.assertEqual(raw_lines,
 
342
                ['foo: ' + uni_data.encode('utf-8') + '\n'])
 
343
        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')