1
# Copyright (C) 2005 by Canonical Ltd
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.
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.
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
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
"""Tests for rio serialization
19
A simple, reproducible structured IO format.
21
rio itself works in Unicode strings. It is typically encoded to UTF-8,
22
but this depends on the transport.
27
from tempfile import TemporaryFile
29
from bzrlib.tests import TestCaseInTempDir, TestCase
30
from bzrlib.rio import RioWriter, Stanza, read_stanza, read_stanzas
33
class TestRio(TestCase):
35
def test_stanza(self):
36
"""Construct rio stanza in memory"""
37
s = Stanza(number=42, name="fred")
38
self.assertTrue('number' in s)
39
self.assertFalse('color' in s)
40
self.assertFalse(42 in s)
41
self.assertEquals(list(s.iter_pairs()),
42
[('name', 'fred'), ('number', 42)])
43
self.assertEquals(s.get('number'), 42)
44
self.assertEquals(s.get('name'), 'fred')
46
def test_value_checks(self):
47
"""rio checks types on construction"""
48
# these aren't enforced at construction time
49
## self.assertRaises(ValueError,
50
## Stanza, complex=42 + 3j)
51
## self.assertRaises(ValueError,
52
## Stanza, several=range(10))
54
def test_empty_value(self):
55
"""Serialize stanza with empty field"""
57
self.assertEqualDiff(s.to_string(),
60
def test_to_lines(self):
61
"""Write simple rio stanza to string"""
62
s = Stanza(number=42, name='fred')
63
self.assertEquals(list(s.to_lines()),
67
def test_to_file(self):
68
"""Write rio to file"""
69
tmpf = TemporaryFile()
70
s = Stanza(a_thing='something with "quotes like \\"this\\""', number=42, name='fred')
73
self.assertEqualDiff(tmpf.read(), r'''
74
a_thing: something with "quotes like \"this\""
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",
86
self.assertEqualDiff(tmpf.read(), r'''\
95
def test_multiline_string(self):
96
tmpf = TemporaryFile()
97
s = Stanza(motto="war is peace\nfreedom is slavery\nignorance is strength")
100
self.assertEqualDiff(tmpf.read(), '''\
103
\tignorance is strength
106
s2 = read_stanza(tmpf)
107
self.assertEquals(s, s2)
109
def test_read_stanza(self):
110
"""Load stanza from string"""
112
revision: mbp@sourcefrog.net-123-abc
113
timestamp: 1130653962
115
committer: Martin Pool <mbp@test.sourcefrog.net>
117
s = read_stanza(lines)
118
self.assertTrue('revision' in s)
119
self.assertEqualDiff(s.get('revision'), 'mbp@sourcefrog.net-123-abc')
120
self.assertEquals(list(s.iter_pairs()),
121
[('revision', 'mbp@sourcefrog.net-123-abc'),
122
('timestamp', '1130653962'),
123
('timezone', '36000'),
124
('committer', "Martin Pool <mbp@test.sourcefrog.net>")])
125
self.assertEquals(len(s), 4)
127
def test_repeated_field(self):
128
"""Repeated field in rio"""
130
for k, v in [('a', '10'), ('b', '20'), ('a', '100'), ('b', '200'),
131
('a', '1000'), ('b', '2000')]:
133
s2 = read_stanza(s.to_lines())
134
self.assertEquals(s, s2)
135
self.assertEquals(s.get_all('a'), map(str, [10, 100, 1000]))
136
self.assertEquals(s.get_all('b'), map(str, [20, 200, 2000]))
138
def test_longint(self):
139
"""rio packing long integers"""
140
s = Stanza(x=-12345678901234567890,
143
s2 = read_stanza(lines)
144
self.assertEquals(s, s2)
146
def test_quoted_0(self):
147
"""Backslash quoted cases"""
150
self.assertEqualDiff(t, 'q "\\\\"\n')
151
s2 = read_stanza(s.to_lines())
152
self.assertEquals(s, s2)
154
def test_quoted_1(self):
155
"""Backslash quoted cases"""
156
s = Stanza(q=r'\"\"')
157
self.assertEqualDiff(s.to_string(), r'q "\\\"\\\""' + '\n')
159
def test_quoted_4(self):
160
s = Stanza(q=r'""""')
162
self.assertEqualDiff(t, r'q "\"\"\"\""' + '\n')
163
s2 = read_stanza(s.to_lines())
164
self.assertEquals(s, s2)
166
def test_quoted_5(self):
167
s = Stanza(q=r'\\\\\"')
169
s2 = read_stanza(s.to_lines())
170
self.assertEquals(s, s2)
172
def test_quoted_6(self):
180
s2 = read_stanza(s.to_lines())
181
self.assertEquals(s2['q'], qval)
183
def test_quoted_7(self):
192
s2 = read_stanza(s.to_lines())
193
self.assertEquals(s2['q'], qval)
195
def test_quoted_8(self):
201
s2 = read_stanza(s.to_lines())
202
self.assertEquals(s2['q'], qval)
204
def test_quoted(self):
205
"""rio quoted string cases"""
206
s = Stanza(q1='"hello"',
216
s2 = read_stanza(s.to_lines())
217
self.assertEquals(s, s2)
219
def test_read_empty(self):
220
"""Detect end of rio file"""
222
self.assertEqual(s, None)
223
self.assertTrue(s is None)
225
def test_read_iter(self):
226
"""Read several stanzas from file"""
227
tmpf = TemporaryFile()
238
reader = read_stanzas(tmpf)
239
read_iter = iter(reader)
241
self.assertEqual(stuff,
242
[ Stanza(version_header=1),
243
Stanza(name="foo", val=123),
244
Stanza(name="bar", val=129319), ])
246
def test_read_several(self):
247
"""Read several stanzas from file"""
248
tmpf = TemporaryFile()
256
address " \\"Willowglen\\"
264
s = read_stanza(tmpf)
265
self.assertEquals(s, Stanza(version_header=1))
266
s = read_stanza(tmpf)
267
self.assertEquals(s, Stanza(name="foo", val=123))
268
s = read_stanza(tmpf)
269
self.assertEqualDiff(s.get('name'), 'quoted')
270
self.assertEqualDiff(s.get('address'), ' "Willowglen"\n 42 Wallaby Way\n Sydney')
271
s = read_stanza(tmpf)
272
self.assertEquals(s, Stanza(name="bar", val=129319))
273
s = read_stanza(tmpf)
274
self.assertEquals(s, None)
276
def test_tricky_quoted(self):
277
tmpf = TemporaryFile()
305
s "backslashes\\\\\\"
309
"""[1:]) # remove initial newline
311
expected_vals = ['"one"',
324
for expected in expected_vals:
325
stanza = read_stanza(tmpf)
326
self.assertEquals(len(stanza), 1)
327
self.assertEqualDiff(stanza.get('s'), expected)
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'])
334
def test_write_empty_stanza(self):
335
"""Write empty stanza"""
336
l = list(Stanza().to_lines())
337
self.assertEquals(l, [])