~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_rio.py

  • Committer: Martin Pool
  • Date: 2005-11-28 08:03:42 UTC
  • mto: (1185.33.61 bzr.dev)
  • mto: This revision was merged to the branch mainline in revision 1518.
  • Revision ID: mbp@sourcefrog.net-20051128080342-b7db3190dca90484
[broken] start converting basic_io to more rfc822-like format

Suggestions from mailing list:
 
  no double quotes
  no cute right-alignment
  no escaping
  just indent continuation lines

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006 Canonical Ltd
 
1
# Copyright (C) 2005 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
22
22
but this depends on the transport.
23
23
"""
24
24
 
25
 
import cStringIO
26
25
import os
27
 
import re
28
26
import sys
29
27
from tempfile import TemporaryFile
30
28
 
31
 
from bzrlib import (
32
 
    rio,
33
 
    )
34
29
from bzrlib.tests import TestCaseInTempDir, TestCase
35
 
from bzrlib.rio import (RioWriter, Stanza, read_stanza, read_stanzas, rio_file,
36
 
                        RioReader)
 
30
from bzrlib.rio import RioWriter, Stanza, read_stanza, read_stanzas
37
31
 
38
32
 
39
33
class TestRio(TestCase):
40
34
 
41
35
    def test_stanza(self):
42
36
        """Construct rio stanza in memory"""
43
 
        s = Stanza(number='42', name="fred")
 
37
        s = Stanza(number=42, name="fred")
44
38
        self.assertTrue('number' in s)
45
39
        self.assertFalse('color' in s)
46
 
        self.assertFalse('42' in s)
 
40
        self.assertFalse(42 in s)
47
41
        self.assertEquals(list(s.iter_pairs()),
48
 
                [('name', 'fred'), ('number', '42')])
49
 
        self.assertEquals(s.get('number'), '42')
 
42
                [('name', 'fred'), ('number', 42)])
 
43
        self.assertEquals(s.get('number'), 42)
50
44
        self.assertEquals(s.get('name'), 'fred')
51
45
 
52
46
    def test_value_checks(self):
65
59
 
66
60
    def test_to_lines(self):
67
61
        """Write simple rio stanza to string"""
68
 
        s = Stanza(number='42', name='fred')
 
62
        s = Stanza(number=42, name='fred')
69
63
        self.assertEquals(list(s.to_lines()),
70
64
                ['name: fred\n',
71
65
                 'number: 42\n'])
72
66
 
73
 
    def test_as_dict(self):
74
 
        """Convert rio Stanza to dictionary"""
75
 
        s = Stanza(number='42', name='fred')
76
 
        sd = s.as_dict()
77
 
        self.assertEquals(sd, dict(number='42', name='fred'))
78
 
 
79
67
    def test_to_file(self):
80
68
        """Write rio to file"""
81
69
        tmpf = TemporaryFile()
82
 
        s = Stanza(a_thing='something with "quotes like \\"this\\""', number='42', name='fred')
 
70
        s = Stanza(a_thing='something with "quotes like \\"this\\""', number=42, name='fred')
83
71
        s.write(tmpf)
84
72
        tmpf.seek(0)
85
73
        self.assertEqualDiff(tmpf.read(), r'''
89
77
'''[1:])
90
78
 
91
79
    def test_multiline_string(self):
 
80
        """Write rio with multiline string"""
 
81
        tmpf = TemporaryFile()
 
82
        s = Stanza(a=123, motto="war is peace\nfreedom is slavery\nignorance is strength\n",
 
83
                   charlie_horse=456)
 
84
        s.write(tmpf)
 
85
        tmp.seek(0)
 
86
        self.assertEqualDiff(tmpf.read(), r'''\
 
87
            a 123
 
88
        motto "war is peace
 
89
freedom is slavery
 
90
ignorance is strength
 
91
"
 
92
charlie_horse 456
 
93
''')
 
94
 
 
95
    def test_multiline_string(self):
92
96
        tmpf = TemporaryFile()
93
97
        s = Stanza(motto="war is peace\nfreedom is slavery\nignorance is strength")
94
98
        s.write(tmpf)
131
135
        self.assertEquals(s.get_all('a'), map(str, [10, 100, 1000]))
132
136
        self.assertEquals(s.get_all('b'), map(str, [20, 200, 2000]))
133
137
 
134
 
    def test_backslash(self):
 
138
    def test_longint(self):
 
139
        """rio packing long integers"""
 
140
        s = Stanza(x=-12345678901234567890,
 
141
                   y=1<<100)
 
142
        lines = s.to_lines()
 
143
        s2 = read_stanza(lines)
 
144
        self.assertEquals(s, s2)
 
145
 
 
146
    def test_quoted_0(self):
 
147
        """Backslash quoted cases"""
135
148
        s = Stanza(q='\\')
136
149
        t = s.to_string()
137
 
        self.assertEqualDiff(t, 'q: \\\n')
138
 
        s2 = read_stanza(s.to_lines())
139
 
        self.assertEquals(s, s2)
140
 
 
141
 
    def test_blank_line(self):
142
 
        s = Stanza(none='', one='\n', two='\n\n')
143
 
        self.assertEqualDiff(s.to_string(), """\
144
 
none: 
145
 
one: 
146
 
\t
147
 
two: 
148
 
\t
149
 
\t
150
 
""")
151
 
        s2 = read_stanza(s.to_lines())
152
 
        self.assertEquals(s, s2)
153
 
 
154
 
    def test_whitespace_value(self):
155
 
        s = Stanza(space=' ', tabs='\t\t\t', combo='\n\t\t\n')
156
 
        self.assertEqualDiff(s.to_string(), """\
157
 
combo: 
158
 
\t\t\t
159
 
\t
160
 
space:  
161
 
tabs: \t\t\t
162
 
""")
163
 
        s2 = read_stanza(s.to_lines())
164
 
        self.assertEquals(s, s2)
165
 
        self.rio_file_stanzas([s])
166
 
 
 
150
        self.assertEqualDiff(t, 'q "\\\\"\n')
 
151
        s2 = read_stanza(s.to_lines())
 
152
        self.assertEquals(s, s2)
 
153
 
 
154
    def test_quoted_1(self):
 
155
        """Backslash quoted cases"""
 
156
        s = Stanza(q=r'\"\"')
 
157
        self.assertEqualDiff(s.to_string(), r'q "\\\"\\\""' + '\n')
 
158
 
 
159
    def test_quoted_4(self):
 
160
        s = Stanza(q=r'""""')
 
161
        t = s.to_string()
 
162
        self.assertEqualDiff(t, r'q "\"\"\"\""' + '\n')
 
163
        s2 = read_stanza(s.to_lines())
 
164
        self.assertEquals(s, s2)
 
165
 
 
166
    def test_quoted_5(self):
 
167
        s = Stanza(q=r'\\\\\"')
 
168
        t = s.to_string()
 
169
        s2 = read_stanza(s.to_lines())
 
170
        self.assertEquals(s, s2)
 
171
 
 
172
    def test_quoted_6(self):
 
173
        qval = r'''
 
174
                "
 
175
                \"
 
176
'''
 
177
        s = Stanza(q=qval)
 
178
        t = s.to_string()
 
179
        self.log(t)
 
180
        s2 = read_stanza(s.to_lines())
 
181
        self.assertEquals(s2['q'], qval)
 
182
        
 
183
    def test_quoted_7(self):
 
184
        qval = r'''
 
185
                "
 
186
                \"
 
187
                \\"
 
188
trailing stuff'''
 
189
        s = Stanza(q=qval)
 
190
        t = s.to_string()
 
191
        self.log(t)
 
192
        s2 = read_stanza(s.to_lines())
 
193
        self.assertEquals(s2['q'], qval)
 
194
        
 
195
    def test_quoted_8(self):
 
196
        qval = r'''trailing
 
197
        quote"'''
 
198
        s = Stanza(q=qval)
 
199
        t = s.to_string()
 
200
        self.log(t)
 
201
        s2 = read_stanza(s.to_lines())
 
202
        self.assertEquals(s2['q'], qval)
 
203
        
167
204
    def test_quoted(self):
168
205
        """rio quoted string cases"""
169
206
        s = Stanza(q1='"hello"', 
178
215
                   )
179
216
        s2 = read_stanza(s.to_lines())
180
217
        self.assertEquals(s, s2)
181
 
        # apparent bug in read_stanza
182
 
        # s3 = read_stanza(self.stanzas_to_str([s]))
183
 
        # self.assertEquals(s, s3)
184
218
 
185
219
    def test_read_empty(self):
186
220
        """Detect end of rio file"""
192
226
        """Read several stanzas from file"""
193
227
        tmpf = TemporaryFile()
194
228
        tmpf.write("""\
195
 
version_header: 1
196
 
 
197
 
name: foo
198
 
val: 123
199
 
 
200
 
name: bar
201
 
val: 129319
 
229
version_header 1
 
230
 
 
231
name "foo"
 
232
val 123
 
233
 
 
234
name "bar"
 
235
val 129319
202
236
""")
203
237
        tmpf.seek(0)
204
238
        reader = read_stanzas(tmpf)
205
239
        read_iter = iter(reader)
206
240
        stuff = list(reader)
207
241
        self.assertEqual(stuff, 
208
 
                [ Stanza(version_header='1'),
209
 
                  Stanza(name="foo", val='123'),
210
 
                  Stanza(name="bar", val='129319'), ])
 
242
                [ Stanza(version_header=1),
 
243
                  Stanza(name="foo", val=123),
 
244
                  Stanza(name="bar", val=129319), ])
211
245
 
212
246
    def test_read_several(self):
213
247
        """Read several stanzas from file"""
214
248
        tmpf = TemporaryFile()
215
249
        tmpf.write("""\
216
 
version_header: 1
217
 
 
218
 
name: foo
219
 
val: 123
220
 
 
221
 
name: quoted
222
 
address:   "Willowglen"
223
 
\t  42 Wallaby Way
224
 
\t  Sydney
225
 
 
226
 
name: bar
227
 
val: 129319
 
250
version_header 1
 
251
 
 
252
name "foo"
 
253
val 123
 
254
 
 
255
name "quoted"
 
256
address "  \\"Willowglen\\"
 
257
  42 Wallaby Way
 
258
  Sydney"
 
259
 
 
260
name "bar"
 
261
val 129319
228
262
""")
229
263
        tmpf.seek(0)
230
264
        s = read_stanza(tmpf)
231
 
        self.assertEquals(s, Stanza(version_header='1'))
 
265
        self.assertEquals(s, Stanza(version_header=1))
232
266
        s = read_stanza(tmpf)
233
 
        self.assertEquals(s, Stanza(name="foo", val='123'))
 
267
        self.assertEquals(s, Stanza(name="foo", val=123))
234
268
        s = read_stanza(tmpf)
235
269
        self.assertEqualDiff(s.get('name'), 'quoted')
236
270
        self.assertEqualDiff(s.get('address'), '  "Willowglen"\n  42 Wallaby Way\n  Sydney')
237
271
        s = read_stanza(tmpf)
238
 
        self.assertEquals(s, Stanza(name="bar", val='129319'))
 
272
        self.assertEquals(s, Stanza(name="bar", val=129319))
239
273
        s = read_stanza(tmpf)
240
274
        self.assertEquals(s, None)
241
 
        self.check_rio_file(tmpf)
242
 
 
243
 
    def check_rio_file(self, real_file):
244
 
        real_file.seek(0)
245
 
        read_write = rio_file(RioReader(real_file)).read()
246
 
        real_file.seek(0)
247
 
        self.assertEquals(read_write, real_file.read())
248
 
 
249
 
    @staticmethod
250
 
    def stanzas_to_str(stanzas):
251
 
        return rio_file(stanzas).read()
252
 
 
253
 
    def rio_file_stanzas(self, stanzas):
254
 
        new_stanzas = list(RioReader(rio_file(stanzas)))
255
 
        self.assertEqual(new_stanzas, stanzas)
256
275
 
257
276
    def test_tricky_quoted(self):
258
277
        tmpf = TemporaryFile()
259
 
        tmpf.write('''\
260
 
s: "one"
261
 
 
262
 
s: 
263
 
\t"one"
264
 
\t
265
 
 
266
 
s: "
267
 
 
268
 
s: ""
269
 
 
270
 
s: """
271
 
 
272
 
s: 
273
 
\t
274
 
 
275
 
s: \\
276
 
 
277
 
s: 
278
 
\t\\
279
 
\t\\\\
280
 
\t
281
 
 
282
 
s: word\\
283
 
 
284
 
s: quote"
285
 
 
286
 
s: backslashes\\\\\\
287
 
 
288
 
s: both\\\"
289
 
 
290
 
''')
 
278
        tmpf.write(r"""
 
279
s "\"one\""
 
280
 
 
281
s "
 
282
\"one\"
 
283
"
 
284
 
 
285
s "\""
 
286
 
 
287
s "\"\""
 
288
 
 
289
s "\"\"\""
 
290
 
 
291
s "
 
292
"
 
293
 
 
294
s "\\"
 
295
 
 
296
s "
 
297
\\
 
298
\\\\
 
299
"
 
300
 
 
301
s "word\\"
 
302
 
 
303
s "quote\""
 
304
 
 
305
s "backslashes\\\\\\"
 
306
 
 
307
s "both\\\""
 
308
 
 
309
"""[1:]) # remove initial newline
291
310
        tmpf.seek(0)
292
311
        expected_vals = ['"one"',
293
312
            '\n"one"\n',
304
323
            ]
305
324
        for expected in expected_vals:
306
325
            stanza = read_stanza(tmpf)
307
 
            self.rio_file_stanzas([stanza])
308
326
            self.assertEquals(len(stanza), 1)
309
327
            self.assertEqualDiff(stanza.get('s'), expected)
310
328
 
 
329
    def test_write_bool(self):
 
330
        """Write bool to rio"""
 
331
        l = list(Stanza(my_bool=True).to_lines())
 
332
        self.assertEquals(l, ['my_bool 1\n'])
 
333
 
311
334
    def test_write_empty_stanza(self):
312
335
        """Write empty stanza"""
313
336
        l = list(Stanza().to_lines())
314
337
        self.assertEquals(l, [])
315
 
 
316
 
    def test_rio_raises_type_error(self):
317
 
        """TypeError on adding invalid type to Stanza"""
318
 
        s = Stanza()
319
 
        self.assertRaises(TypeError, s.add, 'foo', {})
320
 
 
321
 
    def test_rio_raises_type_error_key(self):
322
 
        """TypeError on adding invalid type to Stanza"""
323
 
        s = Stanza()
324
 
        self.assertRaises(TypeError, s.add, 10, {})
325
 
 
326
 
    def test_rio_unicode(self):
327
 
        uni_data = u'\N{KATAKANA LETTER O}'
328
 
        s = Stanza(foo=uni_data)
329
 
        self.assertEquals(s.get('foo'), uni_data)
330
 
        raw_lines = s.to_lines()
331
 
        self.assertEquals(raw_lines,
332
 
                ['foo: ' + uni_data.encode('utf-8') + '\n'])
333
 
        new_s = read_stanza(raw_lines)
334
 
        self.assertEquals(new_s.get('foo'), uni_data)
335
 
 
336
 
    def test_rio_to_unicode(self):
337
 
        uni_data = u'\N{KATAKANA LETTER O}'
338
 
        s = Stanza(foo=uni_data)
339
 
        unicode_str = s.to_unicode()
340
 
        self.assertEqual(u'foo: %s\n' % (uni_data,), unicode_str)
341
 
        new_s = rio.read_stanza_unicode(unicode_str.splitlines(True))
342
 
        self.assertEqual(uni_data, new_s.get('foo'))
343
 
 
344
 
    def test_nested_rio_unicode(self):
345
 
        uni_data = u'\N{KATAKANA LETTER O}'
346
 
        s = Stanza(foo=uni_data)
347
 
        parent_stanza = Stanza(child=s.to_unicode())
348
 
        raw_lines = parent_stanza.to_lines()
349
 
        self.assertEqual(['child: foo: ' + uni_data.encode('utf-8') + '\n',
350
 
                          '\t\n',
351
 
                         ], raw_lines)
352
 
        new_parent = read_stanza(raw_lines)
353
 
        child_text = new_parent.get('child')
354
 
        self.assertEqual(u'foo: %s\n' % uni_data, child_text)
355
 
        new_child = rio.read_stanza_unicode(child_text.splitlines(True))
356
 
        self.assertEqual(uni_data, new_child.get('foo'))
357
 
 
358
 
    def mail_munge(self, lines, dos_nl=True):
359
 
        new_lines = []
360
 
        for line in lines:
361
 
            line = re.sub(' *\n', '\n', line)
362
 
            if dos_nl:
363
 
                line = re.sub('([^\r])\n', '\\1\r\n', line)
364
 
            new_lines.append(line)
365
 
        return new_lines
366
 
 
367
 
    def test_patch_rio(self):
368
 
        stanza = Stanza(data='#\n\r\\r ', space=' ' * 255, hash='#' * 255)
369
 
        lines = rio.to_patch_lines(stanza)
370
 
        for line in lines:
371
 
            self.assertContainsRe(line, '^# ')
372
 
            self.assertTrue(72 >= len(line))
373
 
        for line in rio.to_patch_lines(stanza, max_width=12):
374
 
            self.assertTrue(12 >= len(line))
375
 
        new_stanza = rio.read_patch_stanza(self.mail_munge(lines,
376
 
                                                           dos_nl=False))
377
 
        lines = self.mail_munge(lines)
378
 
        new_stanza = rio.read_patch_stanza(lines)
379
 
        self.assertEqual('#\n\r\\r ', new_stanza.get('data'))
380
 
        self.assertEqual(' '* 255, new_stanza.get('space'))
381
 
        self.assertEqual('#'* 255, new_stanza.get('hash'))
382
 
 
383
 
    def test_patch_rio_linebreaks(self):
384
 
        stanza = Stanza(breaktest='linebreak -/'*30)
385
 
        self.assertContainsRe(rio.to_patch_lines(stanza, 71)[0],
386
 
                              'linebreak\\\\\n')
387
 
        stanza = Stanza(breaktest='linebreak-/'*30)
388
 
        self.assertContainsRe(rio.to_patch_lines(stanza, 70)[0],
389
 
                              'linebreak-\\\\\n')
390
 
        stanza = Stanza(breaktest='linebreak/'*30)
391
 
        self.assertContainsRe(rio.to_patch_lines(stanza, 70)[0],
392
 
                              'linebreak\\\\\n')