source: trunk/tests/test_emitter.py @ 23

Revision 23, 10.5 KB checked in by xi, 9 years ago (diff)

Fix obvious compatibility issues.

RevLine 
[17]1
2import unittest
3
4import _syck
5
6import StringIO, gc
7
8EXAMPLE = _syck.Seq([
9        _syck.Scalar('Mark McGwire'),
10        _syck.Scalar('Sammy Sosa'),
11        _syck.Scalar('Ken Griffey'),
12])
13
14COMPLEX_EXAMPLE = _syck.Map({
15    _syck.Scalar('scalars') : _syck.Seq([
16            _syck.Scalar(),
17            _syck.Scalar('on'),
18            _syck.Scalar('12345', tag="tag:yaml.org,2002:int"),
19# Syck bug with trailing spaces.
20#            _syck.Scalar('long '*100, width=20, indent=5),
21            _syck.Scalar('long long long long long\n'*100, width=20, indent=5),
22            _syck.Scalar('"1quote"', style='1quote'),
23            _syck.Scalar("'2quote'", style='2quote'),
24            _syck.Scalar("folding\n"*10, style='fold'),
25            _syck.Scalar("literal\n"*10, style='literal'),
26            _syck.Scalar("plain text", style='plain'),
27        ]),
28    _syck.Scalar('sequences') : _syck.Seq([
29            _syck.Seq([
30                    _syck.Seq([_syck.Scalar('foo'), _syck.Scalar('bar', style='literal')]),
31            ], inline=True),
32            _syck.Seq([
33                _syck.Scalar('foo'),
34                _syck.Scalar('bar'),
35            ], tag="x-private:myprivatesequence")
36        ]),
37    _syck.Scalar('mappings') : _syck.Seq([
38            _syck.Map({
39                _syck.Seq([_syck.Scalar('1'), _syck.Scalar('2')]) :
40                    _syck.Seq([_syck.Scalar('3'), _syck.Scalar('4')]),
41                _syck.Scalar('5') : _syck.Scalar('6'),
42            }),
43            _syck.Map({
44                _syck.Scalar('foo') :
45                    _syck.Seq([_syck.Scalar('bar')])
46            }, inline=True, tag="x-private:myprivatemapping"),
47        ]),
48    _syck.Scalar('empty'): _syck.Seq([
49            _syck.Scalar(),
50            _syck.Seq(),
51            _syck.Map(),
52            _syck.Map({_syck.Scalar(tag='tag:yaml.org,2002:str') : _syck.Scalar(tag='tag:yaml.org,2002:str')}),
53            _syck.Map({_syck.Scalar('foo') : _syck.Scalar()}),
54            _syck.Map({_syck.Scalar(tag='tag:yaml.org,2002:str') : _syck.Scalar('bar')}),
55        ]),
56})
57
58PAIRS = _syck.Map([
59    (_syck.Scalar('foo'), _syck.Scalar('bar')),
60    (_syck.Scalar('bar'), _syck.Scalar('baz')),
61])
62
63CYCLE = _syck.Seq()
64CYCLE.value.append(CYCLE)
65
66ALIASED_OBJECT = _syck.Map({
67        _syck.Scalar('key1'): _syck.Scalar('value1'),
68        _syck.Scalar('key2'): _syck.Scalar('value2'),
69        _syck.Scalar('key3'): _syck.Seq([_syck.Scalar('value3')]),
70})
71
72ALIASES = _syck.Seq([ALIASED_OBJECT, ALIASED_OBJECT])
73
74TAGS = [
75    'tag:yaml.org,2002:str',
76    'tag:yaml.org,2002:int',
77    'tag:python.yaml.org,2002:object',
78    'tag:domain.tld,2002:my/own/type#variant',
79    'x-private:private',
80]
81
82INVALID_ROOT = 'break me'
83
84INVALID_SEQ = [
85    _syck.Seq([1,2,3]),
86    _syck.Map({
87        _syck.Scalar('valid'): _syck.Seq([_syck.Scalar('valid'), _syck.Scalar('valid')]),
88        _syck.Scalar('invalid'): _syck.Seq([_syck.Scalar('valid'), 'invalid', _syck.Scalar('valid')]),
89    }),       
90]
91
92INVALID_MAP = [
93    _syck.Map({'foo': 'bar'}),
94    _syck.Map({'foo': _syck.Scalar('valid')}),
95    _syck.Map({_syck.Scalar('valid'): 'bar'}),
96    _syck.Seq([
97        _syck.Map({}),
98        _syck.Map({_syck.Scalar('valid'): 'invalid'}),
99    ]),
100]
101
102
103def strip(node, node_to_object=None):
104    if node_to_object is None:
105        node_to_object = {}
106    if node in node_to_object:
107        return node_to_object[node]
108    object = None
109    if node.kind == 'scalar':
110        object = node.value
111    elif node.kind == 'seq':
112        object = []
113        for item in node.value:
114            object.append(strip(item, node_to_object))
115        object = tuple(object)
116    elif node.kind == 'map':
117        object = {}
118        dict_value = dict(node.value)
119        for key in dict_value:
120            object[strip(key, node_to_object)] = strip(dict_value[key], node_to_object)
121    node_to_object[node] = object
122    return object
123
124class TestAttributes(unittest.TestCase):
125
126    def testAttributes(self):
127        output = StringIO.StringIO()
128        emitter = _syck.Emitter(output)
129        self.assertEqual(type(emitter), _syck.Emitter)
130        self.assertEqual(emitter.output, output)
131        self.assertEqual(emitter.headless, False)
132        self.assertEqual(emitter.use_header, False)
133        self.assertEqual(emitter.use_version, False)
134        self.assertEqual(emitter.explicit_typing, False)
135        self.assertEqual(emitter.style, None)
136        self.assertEqual(emitter.best_width, 80)
137        self.assertEqual(emitter.indent, 2)
138        emitter = _syck.Emitter(output, headless=True, use_header=True,
139                use_version=True, explicit_typing=True, style='fold',
140                best_width=100, indent=4)
141        self.assertEqual(emitter.headless, True)
142        self.assertEqual(emitter.use_header, True)
143        self.assertEqual(emitter.use_version, True)
144        self.assertEqual(emitter.explicit_typing, True)
145        self.assertEqual(emitter.style, 'fold')
146        self.assertEqual(emitter.best_width, 100)
147        self.assertEqual(emitter.indent, 4)
148
149    def testInvalidTypesAndValues(self):
150        self.assertRaises(TypeError, lambda: _syck.Emitter(None, headless='on'))
151        self.assertRaises(TypeError, lambda: _syck.Emitter(None, use_header='on'))
152        self.assertRaises(TypeError, lambda: _syck.Emitter(None, use_version='on'))
153        self.assertRaises(TypeError, lambda: _syck.Emitter(None, explicit_typing='on'))
154        self.assertRaises(ValueError, lambda: _syck.Emitter(None, style='no_quote'))
155        self.assertRaises(TypeError, lambda: _syck.Emitter(None, best_width='100'))
156        self.assertRaises(ValueError, lambda: _syck.Emitter(None, best_width=0))
157        self.assertRaises(ValueError, lambda: _syck.Emitter(None, best_width=-100))
158        self.assertRaises(TypeError, lambda: _syck.Emitter(None, indent='2'))
159        self.assertRaises(ValueError, lambda: _syck.Emitter(None, indent=0))
160        self.assertRaises(ValueError, lambda: _syck.Emitter(None, indent=-2))
161
162    def testHeadless(self):
163        emitter = _syck.Emitter(StringIO.StringIO(), headless=False)
164        emitter.emit(CYCLE)
[23]165        self.assert_(emitter.output.getvalue().find('---') != -1)
[17]166        emitter = _syck.Emitter(StringIO.StringIO(), headless=True)
167        emitter.emit(CYCLE)
[23]168        self.assert_(emitter.output.getvalue().find('---') == -1)
[17]169
170    def testUseHeader(self):
171        emitter = _syck.Emitter(StringIO.StringIO(), headless=True)
172        emitter.emit(EXAMPLE)
[23]173        self.assert_(emitter.output.getvalue().find('---') == -1)
[17]174        emitter = _syck.Emitter(StringIO.StringIO(), use_header=True)
175        emitter.emit(EXAMPLE)
[23]176        self.assert_(emitter.output.getvalue().find('---') != -1)
[17]177
178    def testExplicitTyping(self):
179        pass    # anyway it's Syck's responsibility to interpret correctly the parameters.
180
181class TestExample(unittest.TestCase):
182
183    def testExample(self):
184        emitter = _syck.Emitter(StringIO.StringIO())
185        emitter.emit(EXAMPLE)
186        parser = _syck.Parser(emitter.output.getvalue())
187        node = parser.parse()
188        self.assertEqual(strip(EXAMPLE), strip(node))
189
190    def testPairs(self):
191        emitter = _syck.Emitter(StringIO.StringIO())
192        emitter.emit(PAIRS)
193        parser = _syck.Parser(emitter.output.getvalue())
194        node = parser.parse()
195        self.assertEqual(strip(PAIRS), strip(node))
196
197    def testComplexExample(self):
198        emitter = _syck.Emitter(StringIO.StringIO())
199        emitter.emit(COMPLEX_EXAMPLE)
200        parser = _syck.Parser(emitter.output.getvalue())
201        node = parser.parse()
202        self.assertEqual(strip(COMPLEX_EXAMPLE), strip(node))
203
204    def testDocuments(self):
205        emitter = _syck.Emitter(StringIO.StringIO())
206        emitter.emit(EXAMPLE)
207        emitter.emit(EXAMPLE)
208        emitter.emit(EXAMPLE)
209        parser = _syck.Parser(emitter.output.getvalue())
210        self.assertEqual(strip(EXAMPLE), strip(parser.parse()))
211        self.assertEqual(strip(EXAMPLE), strip(parser.parse()))
212        self.assertEqual(strip(EXAMPLE), strip(parser.parse()))
213        self.assert_(not parser.eof)
214        parser.parse()
215        self.assert_(parser.eof)
216
217class TestAliases(unittest.TestCase):
218
219    def testAliases(self):
220        emitter = _syck.Emitter(StringIO.StringIO())
221        emitter.emit(ALIASES)
222        parser = _syck.Parser(emitter.output.getvalue())
223        node = parser.parse()
224        self.assert_(node.value[0] is node.value[1])
225
226class TestTags(unittest.TestCase):
227
228    def testTags(self):
229        document = _syck.Seq()
230        for tag in TAGS:
231            document.value.append(_syck.Scalar('foo', tag=tag))
232        emitter = _syck.Emitter(StringIO.StringIO())
233        emitter.emit(document)
234        parser = _syck.Parser(emitter.output.getvalue())
235        document = parser.parse()
236        self.assertEqual(len(document.value), len(TAGS))
[23]237        for index in range(len(document.value)):
238            node = document.value[index]
[17]239            self.assertEqual(node.tag, TAGS[index])
240
241class TestInvalidNodes(unittest.TestCase):
242
243    def testRoot(self):
244        emitter = _syck.Emitter(StringIO.StringIO())
245        self.assertRaises(TypeError, lambda: emitter.emit(INVALID_ROOT))
246
247    def testSeq(self):
248        for invalid in INVALID_SEQ:
249            emitter = _syck.Emitter(StringIO.StringIO())
250            self.assertRaises(TypeError, lambda: emitter.emit(invalid))
251
252    def testMap(self):
253        for invalid in INVALID_MAP:
254            emitter = _syck.Emitter(StringIO.StringIO())
255            self.assertRaises(TypeError, lambda: emitter.emit(invalid))
256
257class TestOutput(unittest.TestCase):
258
259    def testBadOutput(self):
260        emitter = _syck.Emitter(None)
261        self.assertRaises(AttributeError, lambda: emitter.emit(EXAMPLE))
262
263    def testDouble(self):
264        class Stream:
265            def __init__(self):
266                self.emitter = None
267            def write(self, data):
268                if self.emitter:
269                    self.emitter.emit(EXAMPLE)
270        emitter = _syck.Emitter(Stream())
271        emitter.output.emitter = emitter
272        self.assertRaises(RuntimeError, lambda: emitter.emit(EXAMPLE))
273
274class TestGarbage(unittest.TestCase):
275
276    def testGarbage(self):
277        gc.collect()
278        output = []
279        emitter = _syck.Emitter(output)
280        output.append(emitter)
281        del output, emitter
282        self.assertEqual(gc.collect(), 2)
283
284
[21]285#class TestSyckBugWithTrailingSpace(unittest.TestCase):
286#
287#    def testSyckBugWithTrailingSpace(self):
288#        emitter = _syck.Emitter(StringIO.StringIO())
289#        emitter.emit(_syck.Scalar('foo ', tag="tag:yaml.org,2002:str"))
290#        parser = _syck.Parser(emitter.output.getvalue())
291#        self.assertEqual(parser.parse().value, 'foo ')
[17]292
293
Note: See TracBrowser for help on using the repository browser.