1
# Copyright (C) 2005, 2006, 2007, 2009, 2010, 2011 Canonical Ltd
1
# Copyright (C) 2005, 2006, 2007, 2009, 2010, 2011, 2016 Canonical Ltd
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
46
46
self.assertTrue('number' in s)
47
47
self.assertFalse('color' in s)
48
48
self.assertFalse('42' in s)
49
self.assertEquals(list(s.iter_pairs()),
50
[('name', 'fred'), ('number', '42')])
51
self.assertEquals(s.get('number'), '42')
52
self.assertEquals(s.get('name'), 'fred')
54
def test_value_checks(self):
55
"""rio checks types on construction"""
56
# these aren't enforced at construction time
57
## self.assertRaises(ValueError,
58
## Stanza, complex=42 + 3j)
59
## self.assertRaises(ValueError,
60
## Stanza, several=range(10))
49
self.assertEqual(list(s.iter_pairs()),
50
[('name', 'fred'), ('number', '42')])
51
self.assertEqual(s.get('number'), '42')
52
self.assertEqual(s.get('name'), 'fred')
62
54
def test_empty_value(self):
63
55
"""Serialize stanza with empty field"""
64
56
s = Stanza(empty='')
65
self.assertEqualDiff(s.to_string(),
57
self.assertEquals(s.to_string(),
68
60
def test_to_lines(self):
69
61
"""Write simple rio stanza to string"""
70
62
s = Stanza(number='42', name='fred')
71
self.assertEquals(list(s.to_lines()),
63
self.assertEqual(list(s.to_lines()),
75
67
def test_as_dict(self):
76
68
"""Convert rio Stanza to dictionary"""
77
69
s = Stanza(number='42', name='fred')
79
self.assertEquals(sd, dict(number='42', name='fred'))
71
self.assertEqual(sd, dict(number='42', name='fred'))
81
73
def test_to_file(self):
82
74
"""Write rio to file"""
83
75
tmpf = TemporaryFile()
84
s = Stanza(a_thing='something with "quotes like \\"this\\""', number='42', name='fred')
76
s = Stanza(a_thing='something with "quotes like \\"this\\""',
77
number='42', name='fred')
87
self.assertEqualDiff(tmpf.read(), r'''
88
a_thing: something with "quotes like \"this\""
80
self.assertEqual(tmpf.read(), b'''\
81
a_thing: something with "quotes like \\"this\\""
93
86
def test_multiline_string(self):
94
87
tmpf = TemporaryFile()
95
s = Stanza(motto="war is peace\nfreedom is slavery\nignorance is strength")
89
motto="war is peace\nfreedom is slavery\nignorance is strength")
98
self.assertEqualDiff(tmpf.read(), '''\
92
self.assertEqual(tmpf.read(), b'''\
99
93
motto: war is peace
100
94
\tfreedom is slavery
101
95
\tignorance is strength
104
98
s2 = read_stanza(tmpf)
105
self.assertEquals(s, s2)
99
self.assertEqual(s, s2)
107
101
def test_read_stanza(self):
108
102
"""Load stanza from string"""
110
104
revision: mbp@sourcefrog.net-123-abc
111
105
timestamp: 1130653962
114
108
""".splitlines(True)
115
109
s = read_stanza(lines)
116
110
self.assertTrue('revision' in s)
117
self.assertEqualDiff(s.get('revision'), 'mbp@sourcefrog.net-123-abc')
118
self.assertEquals(list(s.iter_pairs()),
119
[('revision', 'mbp@sourcefrog.net-123-abc'),
120
('timestamp', '1130653962'),
121
('timezone', '36000'),
122
('committer', "Martin Pool <mbp@test.sourcefrog.net>")])
123
self.assertEquals(len(s), 4)
111
self.assertEqual(s.get('revision'), 'mbp@sourcefrog.net-123-abc')
112
self.assertEqual(list(s.iter_pairs()),
113
[('revision', 'mbp@sourcefrog.net-123-abc'),
114
('timestamp', '1130653962'),
115
('timezone', '36000'),
116
('committer', "Martin Pool <mbp@test.sourcefrog.net>")])
117
self.assertEqual(len(s), 4)
125
119
def test_repeated_field(self):
126
120
"""Repeated field in rio"""
129
123
('a', '1000'), ('b', '2000')]:
131
125
s2 = read_stanza(s.to_lines())
132
self.assertEquals(s, s2)
133
self.assertEquals(s.get_all('a'), map(str, [10, 100, 1000]))
134
self.assertEquals(s.get_all('b'), map(str, [20, 200, 2000]))
126
self.assertEqual(s, s2)
127
self.assertEqual(s.get_all('a'), ['10', '100', '1000'])
128
self.assertEqual(s.get_all('b'), ['20', '200', '2000'])
136
130
def test_backslash(self):
137
131
s = Stanza(q='\\')
138
132
t = s.to_string()
139
self.assertEqualDiff(t, 'q: \\\n')
133
self.assertEqual(t, b'q: \\\n')
140
134
s2 = read_stanza(s.to_lines())
141
self.assertEquals(s, s2)
135
self.assertEqual(s, s2)
143
137
def test_blank_line(self):
144
138
s = Stanza(none='', one='\n', two='\n\n')
145
self.assertEqualDiff(s.to_string(), """\
139
self.assertEqual(s.to_string(), b"""\
193
187
def test_read_nul_byte(self):
194
188
"""File consisting of a nul byte causes an error."""
195
self.assertRaises(ValueError, read_stanza, ['\0'])
189
self.assertRaises(ValueError, read_stanza, [b'\0'])
197
191
def test_read_nul_bytes(self):
198
192
"""File consisting of many nul bytes causes an error."""
199
self.assertRaises(ValueError, read_stanza, ['\0' * 100])
193
self.assertRaises(ValueError, read_stanza, [b'\0' * 100])
201
195
def test_read_iter(self):
202
196
"""Read several stanzas from file"""
203
197
tmpf = TemporaryFile()
205
199
version_header: 1
215
209
read_iter = iter(reader)
216
210
stuff = list(reader)
217
211
self.assertEqual(stuff,
218
[ Stanza(version_header='1'),
219
Stanza(name="foo", val='123'),
220
Stanza(name="bar", val='129319'), ])
212
[Stanza(version_header='1'),
213
Stanza(name="foo", val='123'),
214
Stanza(name="bar", val='129319'), ])
222
216
def test_read_several(self):
223
217
"""Read several stanzas from file"""
224
218
tmpf = TemporaryFile()
226
220
version_header: 1
240
234
s = read_stanza(tmpf)
241
self.assertEquals(s, Stanza(version_header='1'))
242
s = read_stanza(tmpf)
243
self.assertEquals(s, Stanza(name="foo", val='123'))
244
s = read_stanza(tmpf)
245
self.assertEqualDiff(s.get('name'), 'quoted')
246
self.assertEqualDiff(s.get('address'), ' "Willowglen"\n 42 Wallaby Way\n Sydney')
247
s = read_stanza(tmpf)
248
self.assertEquals(s, Stanza(name="bar", val='129319'))
249
s = read_stanza(tmpf)
250
self.assertEquals(s, None)
235
self.assertEqual(s, Stanza(version_header='1'))
236
s = read_stanza(tmpf)
237
self.assertEqual(s, Stanza(name="foo", val='123'))
238
s = read_stanza(tmpf)
239
self.assertEqual(s.get('name'), 'quoted')
241
s.get('address'), ' "Willowglen"\n 42 Wallaby Way\n Sydney')
242
s = read_stanza(tmpf)
243
self.assertEqual(s, Stanza(name="bar", val='129319'))
244
s = read_stanza(tmpf)
245
self.assertEqual(s, None)
251
246
self.check_rio_file(tmpf)
253
248
def check_rio_file(self, real_file):
254
249
real_file.seek(0)
255
250
read_write = rio_file(RioReader(real_file)).read()
256
251
real_file.seek(0)
257
self.assertEquals(read_write, real_file.read())
252
self.assertEqual(read_write, real_file.read())
260
255
def stanzas_to_str(stanzas):
302
297
expected_vals = ['"one"',
315
310
for expected in expected_vals:
316
311
stanza = read_stanza(tmpf)
317
312
self.rio_file_stanzas([stanza])
318
self.assertEquals(len(stanza), 1)
319
self.assertEqualDiff(stanza.get('s'), expected)
313
self.assertEqual(len(stanza), 1)
314
self.assertEqual(stanza.get('s'), expected)
321
316
def test_write_empty_stanza(self):
322
317
"""Write empty stanza"""
323
318
l = list(Stanza().to_lines())
324
self.assertEquals(l, [])
319
self.assertEqual(l, [])
326
321
def test_rio_raises_type_error(self):
327
322
"""TypeError on adding invalid type to Stanza"""
334
329
self.assertRaises(TypeError, s.add, 10, {})
331
def test_rio_surrogateescape(self):
333
self.assertRaises(UnicodeDecodeError, raw_bytes.decode, 'utf-8')
335
uni_data = raw_bytes.decode('utf-8', 'surrogateescape')
337
self.skipTest('surrogateescape is not available on Python < 3')
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
[b'foo: ' + uni_data.encode('utf-8', 'surrogateescape') + b'\n'])
343
new_s = read_stanza(raw_lines)
344
self.assertEqual(new_s.get('foo'), uni_data)
336
346
def test_rio_unicode(self):
337
347
uni_data = u'\N{KATAKANA LETTER O}'
338
348
s = Stanza(foo=uni_data)
339
self.assertEquals(s.get('foo'), uni_data)
349
self.assertEqual(s.get('foo'), uni_data)
340
350
raw_lines = s.to_lines()
341
self.assertEquals(raw_lines,
342
['foo: ' + uni_data.encode('utf-8') + '\n'])
351
self.assertEqual(raw_lines,
352
[b'foo: ' + uni_data.encode('utf-8') + b'\n'])
343
353
new_s = read_stanza(raw_lines)
344
self.assertEquals(new_s.get('foo'), uni_data)
354
self.assertEqual(new_s.get('foo'), uni_data)
346
356
def test_rio_to_unicode(self):
347
357
uni_data = u'\N{KATAKANA LETTER O}'
356
366
s = Stanza(foo=uni_data)
357
367
parent_stanza = Stanza(child=s.to_unicode())
358
368
raw_lines = parent_stanza.to_lines()
359
self.assertEqual(['child: foo: ' + uni_data.encode('utf-8') + '\n',
369
self.assertEqual([b'child: foo: ' + uni_data.encode('utf-8') + b'\n',
362
372
new_parent = read_stanza(raw_lines)
363
373
child_text = new_parent.get('child')
364
374
self.assertEqual(u'foo: %s\n' % uni_data, child_text)
368
378
def mail_munge(self, lines, dos_nl=True):
370
380
for line in lines:
371
line = re.sub(' *\n', '\n', line)
381
line = re.sub(b' *\n', b'\n', line)
373
line = re.sub('([^\r])\n', '\\1\r\n', line)
383
line = re.sub(b'([^\r])\n', b'\\1\r\n', line)
374
384
new_lines.append(line)
378
388
stanza = Stanza(data='#\n\r\\r ', space=' ' * 255, hash='#' * 255)
379
389
lines = rio.to_patch_lines(stanza)
380
390
for line in lines:
381
self.assertContainsRe(line, '^# ')
391
self.assertContainsRe(line, b'^# ')
382
392
self.assertTrue(72 >= len(line))
383
393
for line in rio.to_patch_lines(stanza, max_width=12):
384
394
self.assertTrue(12 >= len(line))
387
397
lines = self.mail_munge(lines)
388
398
new_stanza = rio.read_patch_stanza(lines)
389
399
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'))
400
self.assertEqual(' ' * 255, new_stanza.get('space'))
401
self.assertEqual('#' * 255, new_stanza.get('hash'))
393
403
def test_patch_rio_linebreaks(self):
394
stanza = Stanza(breaktest='linebreak -/'*30)
404
stanza = Stanza(breaktest='linebreak -/' * 30)
395
405
self.assertContainsRe(rio.to_patch_lines(stanza, 71)[0],
397
stanza = Stanza(breaktest='linebreak-/'*30)
398
self.assertContainsRe(rio.to_patch_lines(stanza, 70)[0],
400
stanza = Stanza(breaktest='linebreak/'*30)
401
self.assertContainsRe(rio.to_patch_lines(stanza, 70)[0],
407
stanza = Stanza(breaktest='linebreak-/' * 30)
408
self.assertContainsRe(rio.to_patch_lines(stanza, 70)[0],
410
stanza = Stanza(breaktest='linebreak/' * 30)
411
self.assertContainsRe(rio.to_patch_lines(stanza, 70)[0],