| 1 | #!/usr/bin/env python2
 | 
| 2 | from __future__ import print_function
 | 
| 3 | 
 | 
| 4 | import unittest
 | 
| 5 | 
 | 
| 6 | from _devbuild.gen.syntax_asdl import Id, Id_str
 | 
| 7 | from core import error
 | 
| 8 | from data_lang import j8
 | 
| 9 | from mycpp.mylib import log
 | 
| 10 | 
 | 
| 11 | 
 | 
| 12 | class FunctionsTest(unittest.TestCase):
 | 
| 13 | 
 | 
| 14 |     def testUtf8Encode(self):
 | 
| 15 |         CASES = [
 | 
| 16 |             (u'\u0065'.encode('utf-8'), 0x0065),
 | 
| 17 |             (u'\u0100'.encode('utf-8'), 0x0100),
 | 
| 18 |             (u'\u1234'.encode('utf-8'), 0x1234),
 | 
| 19 |             (u'\U00020000'.encode('utf-8'), 0x00020000),
 | 
| 20 |             # Out of range is checked elsewhere
 | 
| 21 |             #('\xef\xbf\xbd', 0x10020000),
 | 
| 22 |         ]
 | 
| 23 | 
 | 
| 24 |         for expected, code_point in CASES:
 | 
| 25 |             print('')
 | 
| 26 |             print('Utf8Encode case %r %r' % (expected, code_point))
 | 
| 27 |             self.assertEqual(expected, j8.Utf8Encode(code_point))
 | 
| 28 | 
 | 
| 29 | 
 | 
| 30 | def _PrintTokens(lex):
 | 
| 31 |     log('---')
 | 
| 32 |     log('J8 Case %r', lex.s)
 | 
| 33 |     pos = 0
 | 
| 34 |     while True:
 | 
| 35 |         id_, end_pos, decoded = lex.Next()
 | 
| 36 |         val = lex.s[pos:end_pos]
 | 
| 37 |         d = repr(decoded) if decoded is not None else '-'
 | 
| 38 |         log('    %20s %15r %15s', Id_str(id_), val, d)
 | 
| 39 |         if id_ == Id.Eol_Tok:
 | 
| 40 |             break
 | 
| 41 |         pos = end_pos
 | 
| 42 |     log('')
 | 
| 43 | 
 | 
| 44 | 
 | 
| 45 | class Nil8Test(unittest.TestCase):
 | 
| 46 | 
 | 
| 47 |     def testNil8Errors(self):
 | 
| 48 |         cases = [
 | 
| 49 |             #'()',
 | 
| 50 |             #'(42)',
 | 
| 51 |             #'(:)',
 | 
| 52 |             # extra input
 | 
| 53 |             '(command.Simple))',
 | 
| 54 |             '(',
 | 
| 55 |             '(obj.field',
 | 
| 56 |             '(obj.',
 | 
| 57 | 
 | 
| 58 |             # Expected a value afterward
 | 
| 59 |             '(obj.)',
 | 
| 60 |             '(obj.+',
 | 
| 61 |             '(obj.+)',
 | 
| 62 |             '(obj.[)',
 | 
| 63 |         ]
 | 
| 64 |         for s in cases:
 | 
| 65 |             p = j8.Nil8Parser(s, True)
 | 
| 66 |             try:
 | 
| 67 |                 obj = p.ParseNil8()
 | 
| 68 |             except error.Decode as e:
 | 
| 69 |                 print(e)
 | 
| 70 |             else:
 | 
| 71 |                 self.fail('Expected error.Decode when parsing %r' % s)
 | 
| 72 | 
 | 
| 73 |     def testNil8Operator(self):
 | 
| 74 |         # Should be equivalent!
 | 
| 75 | 
 | 
| 76 |         cases = [
 | 
| 77 |             # These are equivalent, note that parens like (key: "value") add another layer
 | 
| 78 |             ('(: key "value")', 'key: "value"'),
 | 
| 79 |             ('((: k "v") (: k2 "v2"))', '(k: "v" k2: "v2")'),
 | 
| 80 |             ('(@ "str" x123)', '"str" @ x123'),
 | 
| 81 |             ('((! a b) c)', '( a ! b c)'),
 | 
| 82 |             ('(c (! a b))', '( c a ! b )'),
 | 
| 83 |             ('(. (. obj field1) field2)', 'obj.field1.field2'),
 | 
| 84 |             ('((-> obj method) (. obj field))', '(obj->method obj.field1)'),
 | 
| 85 |         ]
 | 
| 86 |         for prefix, infix in cases:
 | 
| 87 |             print()
 | 
| 88 |             print('PREFIX %s' % prefix)
 | 
| 89 |             p = j8.Nil8Parser(prefix, True)
 | 
| 90 |             obj1 = p.ParseNil8()
 | 
| 91 |             print(obj1)
 | 
| 92 |             log('len %d', len(obj1.items))
 | 
| 93 | 
 | 
| 94 |             print()
 | 
| 95 |             print('INFIX %s' % infix)
 | 
| 96 |             p = j8.Nil8Parser(infix, True)
 | 
| 97 |             obj2 = p.ParseNil8()
 | 
| 98 |             print(obj2)
 | 
| 99 |             log('len %d', len(obj2.items))
 | 
| 100 | 
 | 
| 101 |             self.assertEqual(obj1.tag(), obj2.tag(),
 | 
| 102 |                              '%s != %s' % (obj1.tag(), obj2.tag()))
 | 
| 103 |             self.assertEqual(len(obj1.items), len(obj2.items))
 | 
| 104 | 
 | 
| 105 |     def testNil8(self):
 | 
| 106 |         cases = [
 | 
| 107 |             '(unquoted)',
 | 
| 108 |             '(command.Simple)',
 | 
| 109 |             '(f x)',
 | 
| 110 |             '(f 42 "hi")',
 | 
| 111 |             '((-> obj method) (. obj field))',
 | 
| 112 | 
 | 
| 113 |             # address
 | 
| 114 |             '(@ x123 (Token "foo"))',
 | 
| 115 |             '(: key "value")',
 | 
| 116 |             '(. x123)',  # dereference, could be @
 | 
| 117 | 
 | 
| 118 |             #'(Token "foo") @ x123',
 | 
| 119 | 
 | 
| 120 |             # TODO: parse like infix
 | 
| 121 |             '(Token key:"value" k2:"v2")',
 | 
| 122 | 
 | 
| 123 |             # Should be parsed like infix operator
 | 
| 124 |             '(key !x123)',
 | 
| 125 |             '(<-)',  # symbol
 | 
| 126 |             "(<- 1 b'hi')",  # any kinds of args
 | 
| 127 |             "(<- 1 'hi' (f [1 2 3]))",  # symbol
 | 
| 128 |             '[]',
 | 
| 129 |             '[42]',
 | 
| 130 |             '[42 43]',
 | 
| 131 |             '[42 ["a" "b"]]',
 | 
| 132 |             '42',
 | 
| 133 |             '"hi"',
 | 
| 134 |         ]
 | 
| 135 |         for s in cases:
 | 
| 136 |             p = j8.Nil8Parser(s, True)
 | 
| 137 |             obj = p.ParseNil8()
 | 
| 138 |             print(s)
 | 
| 139 |             print('    %s' % obj)
 | 
| 140 |             print()
 | 
| 141 | 
 | 
| 142 | 
 | 
| 143 | class J8Test(unittest.TestCase):
 | 
| 144 | 
 | 
| 145 |     def testJ8(self):
 | 
| 146 |         s = '{}'
 | 
| 147 |         p = j8.Parser(s, True)
 | 
| 148 |         obj = p.ParseValue()
 | 
| 149 |         print(obj)
 | 
| 150 | 
 | 
| 151 |     def testLexerDecoder(self):
 | 
| 152 |         lex = j8.LexerDecoder(r'{"hi": "bye \n"}', True, 'J8')
 | 
| 153 |         _PrintTokens(lex)
 | 
| 154 | 
 | 
| 155 |         lex = j8.LexerDecoder(r"{u'unicode': b'bytes \y1f \yff'}", True, 'J8')
 | 
| 156 |         _PrintTokens(lex)
 | 
| 157 | 
 | 
| 158 |         lex = j8.LexerDecoder(
 | 
| 159 |             r'{"mu \u03BC \u0001":' + r"b'mu \u{03bc} \u{2620}'", True, 'J8')
 | 
| 160 |         _PrintTokens(lex)
 | 
| 161 | 
 | 
| 162 |         lex = j8.LexerDecoder(r'{"x": [1, 2, 3.14, true]}', True, 'J8')
 | 
| 163 |         _PrintTokens(lex)
 | 
| 164 | 
 | 
| 165 |         lex = j8.LexerDecoder(
 | 
| 166 |             r'''
 | 
| 167 |         [
 | 
| 168 |           1e9, 1e-9, -1e9, -1E-9, 42
 | 
| 169 |         ]
 | 
| 170 |         ''', True, 'J8')
 | 
| 171 |         _PrintTokens(lex)
 | 
| 172 | 
 | 
| 173 |         try:
 | 
| 174 |             lex = j8.LexerDecoder('"\x01"', True, 'J8')
 | 
| 175 |             _PrintTokens(lex)
 | 
| 176 |         except error.Decode as e:
 | 
| 177 |             print(e)
 | 
| 178 |         else:
 | 
| 179 |             self.fail('Expected failure')
 | 
| 180 | 
 | 
| 181 |         try:
 | 
| 182 |             lex = j8.LexerDecoder('"\x1f"', True, 'J8')
 | 
| 183 |             _PrintTokens(lex)
 | 
| 184 |         except error.Decode as e:
 | 
| 185 |             print(e)
 | 
| 186 |         else:
 | 
| 187 |             self.fail('Expected failure')
 | 
| 188 | 
 | 
| 189 |     def testMoreTokens(self):
 | 
| 190 |         cases = [
 | 
| 191 |             'true # comment',
 | 
| 192 |             'truez8 # identifier',
 | 
| 193 |             'truez8>  # symbol',
 | 
| 194 |             '(<= 1 3)  # less than',
 | 
| 195 |             # Can allow hex identifiers here like 123
 | 
| 196 |             '(<- 123 (Token))',
 | 
| 197 |             '(Node left:(-> 123))',
 | 
| 198 |         ]
 | 
| 199 |         for s in cases:
 | 
| 200 |             lex = j8.LexerDecoder(s, True, 'J8')
 | 
| 201 |             _PrintTokens(lex)
 | 
| 202 | 
 | 
| 203 |     def testErrorMessagePosition(self):
 | 
| 204 |         lex = j8.LexerDecoder("[ u'hi']", False, 'J8')
 | 
| 205 |         try:
 | 
| 206 |             _PrintTokens(lex)
 | 
| 207 |         except error.Decode as e:
 | 
| 208 |             print(e)
 | 
| 209 |             self.assertEquals(2, e.start_pos)
 | 
| 210 |             self.assertEquals(4, e.end_pos)
 | 
| 211 |         else:
 | 
| 212 |             self.fail('Expected failure')
 | 
| 213 | 
 | 
| 214 | 
 | 
| 215 | class YajlTest(unittest.TestCase):
 | 
| 216 |     """
 | 
| 217 |     Note on old tests for YAJL.  Differences
 | 
| 218 | 
 | 
| 219 |     - It decoded to Python 2 str() type, not unicode()
 | 
| 220 |     - Bug in emitting \\xff literally, which is not valid JSON
 | 
| 221 |       - turns out there is a C level option for this
 | 
| 222 |     """
 | 
| 223 |     pass
 | 
| 224 | 
 | 
| 225 | 
 | 
| 226 | if __name__ == '__main__':
 | 
| 227 |     unittest.main()
 | 
| 228 | 
 | 
| 229 | # vim: sw=4
 |