| 1 | #!/usr/bin/env python2
 | 
| 2 | """front_end_test.py: Tests for front_end.py."""
 | 
| 3 | from __future__ import print_function
 | 
| 4 | 
 | 
| 5 | import cStringIO
 | 
| 6 | import unittest
 | 
| 7 | 
 | 
| 8 | from asdl import front_end  # module under test
 | 
| 9 | from asdl import ast
 | 
| 10 | from asdl import format as fmt
 | 
| 11 | 
 | 
| 12 | 
 | 
| 13 | class FrontEndTest(unittest.TestCase):
 | 
| 14 | 
 | 
| 15 |     def testLoadSchema(self):
 | 
| 16 |         with open('asdl/examples/typed_demo.asdl') as f:
 | 
| 17 |             schema_ast = front_end.LoadSchema(f, {}, verbose=True)
 | 
| 18 |         print(schema_ast)
 | 
| 19 | 
 | 
| 20 |     def testSharedVariant(self):
 | 
| 21 |         with open('asdl/examples/shared_variant.asdl') as f:
 | 
| 22 |             schema_ast = front_end.LoadSchema(f, {}, verbose=False)
 | 
| 23 |         print(schema_ast)
 | 
| 24 | 
 | 
| 25 |     def testSharedVariantCode(self):
 | 
| 26 |         # generated by build/dev.sh minimal
 | 
| 27 |         from _devbuild.gen.shared_variant_asdl import (DoubleQuoted, expr,
 | 
| 28 |                                                        expr_e, word_part,
 | 
| 29 |                                                        word_part_e)
 | 
| 30 |         print(DoubleQuoted)
 | 
| 31 | 
 | 
| 32 |         print(expr)
 | 
| 33 |         print(expr_e)
 | 
| 34 | 
 | 
| 35 |         print(word_part)
 | 
| 36 |         print(word_part_e)
 | 
| 37 | 
 | 
| 38 |         # These have the same value!
 | 
| 39 |         self.assertEqual(65, expr_e.DoubleQuoted)
 | 
| 40 |         self.assertEqual(expr_e.DoubleQuoted, word_part_e.DoubleQuoted)
 | 
| 41 | 
 | 
| 42 |         d = DoubleQuoted(5, ['foo', 'bar'])
 | 
| 43 |         fmt.PrettyPrint(d)
 | 
| 44 |         print()
 | 
| 45 | 
 | 
| 46 |         b = expr.Binary(d, d)
 | 
| 47 |         b.spids = [42, 43]
 | 
| 48 |         fmt.PrettyPrint(b)
 | 
| 49 | 
 | 
| 50 |     def _assertParse(self, code_str):
 | 
| 51 |         f = cStringIO.StringIO(code_str)
 | 
| 52 |         p = front_end.ASDLParser()
 | 
| 53 |         schema_ast = p.parse(f)
 | 
| 54 |         print(schema_ast)
 | 
| 55 |         # For now just test its type
 | 
| 56 |         self.assert_(isinstance(schema_ast, ast.Module))
 | 
| 57 | 
 | 
| 58 |     def testParse(self):
 | 
| 59 |         self._assertParse("""
 | 
| 60 | module foo {
 | 
| 61 |   -- these are invalid, but checked in name resolution stage
 | 
| 62 |   point = (int? x, int* y)
 | 
| 63 | 
 | 
| 64 |   action = Foo | Bar(point z)
 | 
| 65 | 
 | 
| 66 |   foo = (List[int] span_ids)
 | 
| 67 |   bar = (Dict[string, int] options)
 | 
| 68 | 
 | 
| 69 |   -- this check happens later
 | 
| 70 |   does_not_resolve = (typo zz)
 | 
| 71 | 
 | 
| 72 |   color = Red | Green
 | 
| 73 | 
 | 
| 74 |   color2 = Red | Green generate []
 | 
| 75 | 
 | 
| 76 |   color3 = Red | Green
 | 
| 77 |            generate [integers]
 | 
| 78 | 
 | 
| 79 |   color4 = Blue | Purple
 | 
| 80 |            generate [uint16]
 | 
| 81 | 
 | 
| 82 |   -- New optional lists
 | 
| 83 |   spam = (Optional[List[int]] pipe_status)
 | 
| 84 |   -- Nicer way of writing it
 | 
| 85 |   spam2 = (List[int]? pipe_status)
 | 
| 86 | }
 | 
| 87 | """)
 | 
| 88 | 
 | 
| 89 |     def _assertParseError(self, code_str):
 | 
| 90 |         f = cStringIO.StringIO(code_str)
 | 
| 91 |         p = front_end.ASDLParser()
 | 
| 92 |         try:
 | 
| 93 |             schema_ast = p.parse(f)
 | 
| 94 |         except front_end.ASDLSyntaxError as e:
 | 
| 95 |             print(e)
 | 
| 96 |         else:
 | 
| 97 |             self.fail("Expected parse failure: %r" % code_str)
 | 
| 98 | 
 | 
| 99 |     def testParseErrors(self):
 | 
| 100 |         # Need field name
 | 
| 101 |         self._assertParseError('module foo { t = (int) }')
 | 
| 102 | 
 | 
| 103 |         # Need []
 | 
| 104 |         self._assertParseError('module foo { t = (List foo) }')
 | 
| 105 | 
 | 
| 106 |         # Shouldn't have []
 | 
| 107 |         self._assertParseError('module foo { t = (string[string] a) }')
 | 
| 108 | 
 | 
| 109 |         # Not enough params
 | 
| 110 |         self._assertParseError('module foo { t = (Dict[] a) }')
 | 
| 111 |         self._assertParseError('module foo { t = (Dict[string] a) }')
 | 
| 112 |         self._assertParseError('module foo { t = (Dict[string, ] a) }')
 | 
| 113 | 
 | 
| 114 |         self._assertParseError('module foo { ( }')
 | 
| 115 | 
 | 
| 116 |         # Abandoned syntax
 | 
| 117 |         self._assertParseError('module foo { simple: integers = A | B }')
 | 
| 118 | 
 | 
| 119 |         self._assertParseError('module foo { integers = A | B generate }')
 | 
| 120 | 
 | 
| 121 |         self._assertParseError(
 | 
| 122 |             'module foo { integers = A | B generate [integers, ,] }')
 | 
| 123 | 
 | 
| 124 |         self._assertParseError(
 | 
| 125 |             'module foo { integers = A | B generate [invalid] }')
 | 
| 126 | 
 | 
| 127 |     def _assertResolve(self, code_str):
 | 
| 128 |         f = cStringIO.StringIO(code_str)
 | 
| 129 |         schema_ast = front_end.LoadSchema(f, {})
 | 
| 130 | 
 | 
| 131 |         print(type(schema_ast))
 | 
| 132 |         print(schema_ast)
 | 
| 133 | 
 | 
| 134 |     def testResolve(self):
 | 
| 135 |         self._assertResolve("""
 | 
| 136 | module foo {
 | 
| 137 |   point = (int x, int y)
 | 
| 138 |   place = None | Two(point a, point b)
 | 
| 139 |   options = (Dict[string, int] names)
 | 
| 140 | }
 | 
| 141 | """)
 | 
| 142 | 
 | 
| 143 |     def _assertResolveError(self, code_str):
 | 
| 144 |         f = cStringIO.StringIO(code_str)
 | 
| 145 |         try:
 | 
| 146 |             schema_ast = front_end.LoadSchema(f, {})
 | 
| 147 |         except front_end.ASDLSyntaxError as e:
 | 
| 148 |             print(e)
 | 
| 149 |         else:
 | 
| 150 |             self.fail("Expected name resolution error: %r" % code_str)
 | 
| 151 | 
 | 
| 152 |     def testResolveErrors(self):
 | 
| 153 |         self._assertResolveError("""
 | 
| 154 | module foo {
 | 
| 155 |   place = None | Two(typo b)
 | 
| 156 | }
 | 
| 157 | """)
 | 
| 158 | 
 | 
| 159 |         # Optional integer isn't allowed, because C++ can't express it
 | 
| 160 |         # Integers are initialized to -1
 | 
| 161 |         self._assertResolveError('module foo { t = (int? status) }')
 | 
| 162 | 
 | 
| 163 |         # Optional simple sum isn't allowed
 | 
| 164 |         self._assertResolveError('''
 | 
| 165 |         module foo { 
 | 
| 166 |           color = Red | Green
 | 
| 167 |           t = (color? status)
 | 
| 168 |         }
 | 
| 169 |         ''')
 | 
| 170 | 
 | 
| 171 |     def testAstNodes(self):
 | 
| 172 |         # maybe[string]
 | 
| 173 |         n1 = ast.NamedType('string')
 | 
| 174 |         print(n1)
 | 
| 175 | 
 | 
| 176 |         n2 = ast.ParameterizedType('Optional', [n1])
 | 
| 177 |         print(n2)
 | 
| 178 | 
 | 
| 179 |         n3 = ast.ParameterizedType('Dict', [n1, ast.NamedType('int')])
 | 
| 180 |         print(n3)
 | 
| 181 | 
 | 
| 182 | 
 | 
| 183 | if __name__ == '__main__':
 | 
| 184 |     unittest.main()
 |