source: trunk/tests/test_parser.py @ 23

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

Fix obvious compatibility issues.

Line 
1
2import unittest
3
4import _syck
5
6import StringIO, gc
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
162RECURSIVE = """
163--- &id002
164- &id001 Mark McGwire
165- Sammy Sosa
166- Ken Griffey
167- *id001
168- *id002
169"""
170
171ALIASES = """
172- &alias foo
173- *alias
174"""
175
176class TestAttributes(unittest.TestCase):
177
178    def testAttributes(self):
179        parser = _syck.Parser(EXAMPLE)
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)
193
194class TestGarbage(unittest.TestCase):
195
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)
203
204class TestErrors(unittest.TestCase):
205
206    def testError(self):
207        parser = _syck.Parser(INVALID[0])
208        self.assertRaises(_syck.error, lambda: parser.parse())
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 in range(len(node.value)):
230                item = node.value[i]
231                self.assertEqualStructure(item, structure[i])
232        elif node.kind == 'map':
233            self.assertEqual(type(structure), dict)
234            self.assertEqual(len(node.value), len(structure))
235            for key in node.value:
236                self.assert_(key.value in structure)
237                self.assertEqualStructure(node.value[key], structure[key.value])
238
239class TestValuesAndSources(unittest.TestCase, EqualStructure):
240
241    def testValues1(self):
242        self._testValues(COMPARE1)
243
244    def testValues2(self):
245        self._testValues(COMPARE2)
246
247    def testValues3(self):
248        self._testValues(COMPARE3)
249
250    def testFileValues1(self):
251        self._testFileValues(COMPARE1)
252
253    def testFileValues2(self):
254        self._testFileValues(COMPARE2)
255
256    def testFileValues3(self):
257        self._testFileValues(COMPARE3)
258
259    def testNonsense(self):
260        parser = _syck.Parser(None)
261        self.assertRaises(AttributeError, lambda: parser.parse())
262
263    def testCallMeNot(self):
264        class Source:
265            def __init__(self):
266                self.parser = None
267            def read(self, size=None):
268                if self.parser:
269                    self.parser.parse()
270                    return
271        source = Source()
272        parser = _syck.Parser(source)
273        source.parser = parser
274        self.assertRaises(RuntimeError, lambda: parser.parse())
275
276    def testAbsoluteHorror(self):
277        class Source:
278            def __init__(self):
279                self.parser = None
280            def read(self, size=None):
281                if self.parser:
282                    self.parser = None
283                return ''
284        source = Source()
285        parser = _syck.Parser(source)
286        source.parser = parser
287        del parser
288        self.assertEqual(None, source.parser.parse())
289
290    def _testValues(self, (source, structure)):
291        parser = _syck.Parser(source)
292        document = parser.parse()
293        self.assertEqualStructure(document, structure)
294
295    def _testFileValues(self, (source, structure)):
296        parser = _syck.Parser(StringIO.StringIO(source))
297        document = parser.parse()
298        self.assertEqualStructure(document, structure)
299
300class TestDocuments(unittest.TestCase):
301
302    def testDocuments0(self):
303        self._testDocuments(DOCUMENTS0, 0)
304
305    def testDocuments1(self):
306        self._testDocuments(DOCUMENTS1, 1)
307
308    def testDocuments2(self):
309        self._testDocuments(DOCUMENTS2, 2)
310
311    def testDocuments3(self):
312        self._testDocuments(DOCUMENTS3, 3)
313
314    def _testDocuments(self, source, length):
315        parser = _syck.Parser(source)
316        actual_length = 0
317        while True:
318            document = parser.parse()
319            if parser.eof:
320                self.assertEqual(document, None)
321                break
322            actual_length += 1
323        self.assertEqual(actual_length, length)
324        self.assertEqual(parser.parse(), None)
325        self.assert_(parser.eof)
326        self.assertEqual(parser.parse(), None)
327        self.assert_(parser.eof)
328        self.assert_(parser.eof)
329
330class TestImplicitTyping(unittest.TestCase):
331
332    def testImplicitAndExpansionTyping(self):
333        self._testTyping(True, True)
334
335    def testImplicitTyping(self):
336        self._testTyping(True, False)
337
338    def testExpansionTyping(self):
339        self._testTyping(False, True)
340
341    def testNoTyping(self):
342        self._testTyping(False, False)
343
344    def _testTyping(self, implicit_typing, taguri_expansion):
345        parser = _syck.Parser(IMPLICIT_TYPING[0], implicit_typing, taguri_expansion)
346        for node, (tag, explicit) in zip(parser.parse().value, IMPLICIT_TYPING[1]):
347            if tag is not None and taguri_expansion:
348                tag = 'tag:yaml.org,2002:%s' % tag
349            if implicit_typing or explicit:
350                self.assertEqual(node.tag, tag)
351            else:
352                self.assertEqual(node.tag, None)
353
354class TestExplicitTyping(unittest.TestCase):
355
356    def testExplicitTyping(self):
357        parser = _syck.Parser(EXPLICIT_TYPING[0])
358        for node, tag in zip(parser.parse().value, EXPLICIT_TYPING[1]):
359            self.assertEqual(node.tag, tag)
360
361class TestRecursive(unittest.TestCase):
362
363    def testRecursive(self):
364        parser = _syck.Parser(RECURSIVE)
365        self.assertRaises(TypeError, lambda: parser.parse())
366
367class TestParsingAliases(unittest.TestCase):
368
369    def testAliases(self):
370        parser = _syck.Parser(ALIASES)
371        node = parser.parse()
372        self.assert_(node.value[0] is node.value[1])
373
Note: See TracBrowser for help on using the repository browser.