source: trunk/tests/test_parser.py @ 20

Revision 20, 8.6 KB checked in by xi, 9 years ago (diff)

syck.dump() is implemented.

RevLine 
[7]1
2import unittest
3
4import _syck
5
[15]6import StringIO, gc
[7]7
8EXAMPLE = """
9-
10  avg: 0.278
11  hr: 65
12  name: Mark McGwire
13-
14  avg: 0.288
15  hr: 63
16  name: Sammy Sosa
17"""
18
19INVALID = """
20 - invalid
21- document
22""", 2, 0
23
24COMPARE1 = """
25one: foo
26two: bar
27three: baz
28""", {
29    'one': 'foo',
30    'two': 'bar',
31    'three': 'baz',
32}
33
34COMPARE2 = """
35- Mark McGwire
36- Sammy Sosa
37- Ken Griffey
38""", [
39    'Mark McGwire',
40    'Sammy Sosa',
41    'Ken Griffey',
42]
43
44COMPARE3 = """
45american:
46  - Boston Red Sox
47  - Detroit Tigers
48  - New York Yankees
49national:
50  - New York Mets
51  - Chicago Cubs
52  - Atlanta Braves
53""", {
54    'american': [
55        'Boston Red Sox',
56        'Detroit Tigers',
57        'New York Yankees',
58    ],
59    'national': [
60        'New York Mets',
61        'Chicago Cubs',
62        'Atlanta Braves',
63    ],
64}
65
66DOCUMENTS0 = ""
67
68DOCUMENTS1 = """
69---
70Time: 2001-11-23 15:01:42 -05:00
71User: ed
72Warning: >
73  This is an error message
74  for the log file
75"""
76
77DOCUMENTS2 = """
78---
79Time: 2001-11-23 15:01:42 -05:00
80User: ed
81Warning: >
82  This is an error message
83  for the log file
84---
85Time: 2001-11-23 15:02:31 -05:00
86User: ed
87Warning: >
88  A slightly different error
89  message.
90"""
91
92DOCUMENTS3 = """
93---
94Time: 2001-11-23 15:01:42 -05:00
95User: ed
96Warning: >
97  This is an error message
98  for the log file
99---
100Time: 2001-11-23 15:02:31 -05:00
101User: ed
102Warning: >
103  A slightly different error
104  message.
105---
106Date: 2001-11-23 15:03:17 -05:00
107User: ed
108Fatal: >
109  Unknown variable "bar"
110Stack:
111  - file: TopClass.py
112    line: 23
113    code: |
114      x = MoreObject("345\\n")
115  - file: MoreClass.py
116    line: 58
117    code: |-
118      foo = bar
119"""
120
121IMPLICIT_TYPING = """
122- 'foo'
123- >-
124  bar
125- baz
126- 123
127- 3.14
128- true
129- false
130- []
131- {}
132""", [
133    ('str', True),
134    ('str', True),
135    ('str', False),
136    ('int', False),
137    ('float#fix', False),
138    ('bool#yes', False),
139    ('bool#no', False),
140    (None, False),
141    (None, False),
142]
143
144EXPLICIT_TYPING = """
145- !int '123'
146- !yamltype 'foo'
147- !python/type 'bar'
148- !domain.tld,2002/type 'baz'
149- !!private 'private'
150- !map {}
151- !seq []
152""", [
153    'tag:yaml.org,2002:int',
154    'tag:yaml.org,2002:yamltype',
155    'tag:python.yaml.org,2002:type',
156    'tag:domain.tld,2002:type',
157    'x-private:private',
158    'tag:yaml.org,2002:map',
159    'tag:yaml.org,2002:seq',
160]
161
[17]162RECURSIVE = """
163--- &id002
164- &id001 Mark McGwire
165- Sammy Sosa
166- Ken Griffey
167- *id001
168- *id002
169"""
170
[20]171ALIASES = """
172- &alias foo
173- *alias
174"""
175
[15]176class TestAttributes(unittest.TestCase):
[7]177
[15]178    def testAttributes(self):
[7]179        parser = _syck.Parser(EXAMPLE)
[15]180        self.assertEqual(type(parser), _syck.Parser)
181        self.assertEqual(parser.source, EXAMPLE)
182        self.assertEqual(parser.implicit_typing, True)
183        self.assertEqual(parser.taguri_expansion, True)
184        self.assertEqual(parser.eof, False)
185        node = parser.parse()
186        self.assert_(isinstance(node, _syck.Node))
187        self.assertEqual(parser.source, EXAMPLE)
188        self.assertEqual(parser.implicit_typing, True)
189        self.assertEqual(parser.taguri_expansion, True)
190        self.assertEqual(parser.eof, False)
191        self.assertEqual(parser.parse(), None)
192        self.assertEqual(parser.eof, True)
[7]193
[15]194class TestGarbage(unittest.TestCase):
[7]195
[15]196    def testGarbage(self):
197        gc.collect()
198        source = []
199        parser = _syck.Parser(source)
200        source.append(parser)
201        del source, parser
202        self.assertEqual(gc.collect(), 2)
[7]203
204class TestErrors(unittest.TestCase):
205
206    def testError(self):
207        parser = _syck.Parser(INVALID[0])
[15]208        self.assertRaises(_syck.error, lambda: parser.parse())
[7]209
210    def testErrorLocation(self):
211        source, line, column = INVALID
212        parser = _syck.Parser(source)
213        try:
214            parser.parse()
215            raise Exception
216        except _syck.error, e:
217            self.assertEqual(e.args[1], line)
218            self.assertEqual(e.args[2], column)
219
220class EqualStructure:
221
222    def assertEqualStructure(self, node, structure):
223        if node.kind == 'scalar':
224            self.assertEqual(type(structure), str)
225            self.assertEqual(node.value, structure)
226        elif node.kind == 'seq':
227            self.assertEqual(type(structure), list)
228            self.assertEqual(len(node.value), len(structure))
229            for i, item in enumerate(node.value):
230                self.assertEqualStructure(item, structure[i])
231        elif node.kind == 'map':
232            self.assertEqual(type(structure), dict)
233            self.assertEqual(len(node.value), len(structure))
234            for key in node.value:
235                self.assert_(key.value in structure)
236                self.assertEqualStructure(node.value[key], structure[key.value])
237
238class TestValuesAndSources(unittest.TestCase, EqualStructure):
239
240    def testValues1(self):
241        self._testValues(COMPARE1)
242
243    def testValues2(self):
244        self._testValues(COMPARE2)
245
246    def testValues3(self):
247        self._testValues(COMPARE3)
248
249    def testFileValues1(self):
250        self._testFileValues(COMPARE1)
251
252    def testFileValues2(self):
253        self._testFileValues(COMPARE2)
254
255    def testFileValues3(self):
256        self._testFileValues(COMPARE3)
257
258    def testNonsense(self):
259        parser = _syck.Parser(None)
[15]260        self.assertRaises(AttributeError, lambda: parser.parse())
[7]261
[15]262    def testCallMeNot(self):
263        class Source:
264            def __init__(self):
265                self.parser = None
266            def read(self, size=None):
267                if self.parser:
268                    self.parser.parse()
269                    return
270        source = Source()
271        parser = _syck.Parser(source)
272        source.parser = parser
273        self.assertRaises(RuntimeError, lambda: parser.parse())
274
275    def testAbsoluteHorror(self):
276        class Source:
277            def __init__(self):
278                self.parser = None
279            def read(self, size=None):
280                if self.parser:
281                    self.parser = None
282                return ''
283        source = Source()
284        parser = _syck.Parser(source)
285        source.parser = parser
286        del parser
287        self.assertEqual(None, source.parser.parse())
288
[7]289    def _testValues(self, (source, structure)):
290        parser = _syck.Parser(source)
291        document = parser.parse()
292        self.assertEqualStructure(document, structure)
293
294    def _testFileValues(self, (source, structure)):
295        parser = _syck.Parser(StringIO.StringIO(source))
296        document = parser.parse()
297        self.assertEqualStructure(document, structure)
298
299class TestDocuments(unittest.TestCase):
300
301    def testDocuments0(self):
302        self._testDocuments(DOCUMENTS0, 0)
303
304    def testDocuments1(self):
305        self._testDocuments(DOCUMENTS1, 1)
306
307    def testDocuments2(self):
308        self._testDocuments(DOCUMENTS2, 2)
309
310    def testDocuments3(self):
311        self._testDocuments(DOCUMENTS3, 3)
312
313    def _testDocuments(self, source, length):
314        parser = _syck.Parser(source)
315        actual_length = 0
316        while True:
317            document = parser.parse()
[15]318            if parser.eof:
[7]319                self.assertEqual(document, None)
320                break
321            actual_length += 1
322        self.assertEqual(actual_length, length)
323        self.assertEqual(parser.parse(), None)
[15]324        self.assert_(parser.eof)
[7]325        self.assertEqual(parser.parse(), None)
[15]326        self.assert_(parser.eof)
327        self.assert_(parser.eof)
[7]328
329class TestImplicitTyping(unittest.TestCase):
330
331    def testImplicitAndExpansionTyping(self):
332        self._testTyping(True, True)
333
334    def testImplicitTyping(self):
335        self._testTyping(True, False)
336
337    def testExpansionTyping(self):
338        self._testTyping(False, True)
339
340    def testNoTyping(self):
341        self._testTyping(False, False)
342
343    def _testTyping(self, implicit_typing, taguri_expansion):
[15]344        parser = _syck.Parser(IMPLICIT_TYPING[0], implicit_typing, taguri_expansion)
345        for node, (tag, explicit) in zip(parser.parse().value, IMPLICIT_TYPING[1]):
346            if tag is not None and taguri_expansion:
347                tag = 'tag:yaml.org,2002:%s' % tag
[7]348            if implicit_typing or explicit:
[15]349                self.assertEqual(node.tag, tag)
[7]350            else:
[15]351                self.assertEqual(node.tag, None)
[7]352
353class TestExplicitTyping(unittest.TestCase):
354
355    def testExplicitTyping(self):
356        parser = _syck.Parser(EXPLICIT_TYPING[0])
[15]357        for node, tag in zip(parser.parse().value, EXPLICIT_TYPING[1]):
358            self.assertEqual(node.tag, tag)
[7]359
[17]360class TestRecursive(unittest.TestCase):
361
362    def testRecursive(self):
363        parser = _syck.Parser(RECURSIVE)
364        self.assertRaises(TypeError, lambda: parser.parse())
365
[20]366class TestParsingAliases(unittest.TestCase):
367
368    def testAliases(self):
369        parser = _syck.Parser(ALIASES)
370        node = parser.parse()
371        self.assert_(node.value[0] is node.value[1])
372
Note: See TracBrowser for help on using the repository browser.