Implement Array.splice method
[vadmium-streams.git] / javascript / test.py
blob770bf0cdeddd671703c09a29efed500c1e0f2e69
1 from unittest import TestCase
2 import javascript
3 from io import StringIO
4 from unittest.mock import patch
5 from math import inf, ldexp, copysign
6 from itertools import product, combinations, chain
8 class Test(TestCase):
9 def test_identifier_escaped(self):
10 for [code, name] in (
11 (r'ab\u0063de', 'abcde'),
12 (r'\u005Cu123\u0034', '\\u1234'),
14 with self.subTest(code):
15 self.assert_statement(code, ('identifier', name))
16 for code in ('ab\\y0033z', 'ab\\', '\\u123\\u0034'):
17 with self.subTest(code):
18 parser = javascript.parse(StringIO(code))
19 self.assertRaises(Exception, next, parser, None)
21 def test_token_buffering(self):
22 with patch.object(javascript.Parser, 'BUFSIZE', 10):
23 self.assert_statement('abcdefg >>>= x',
24 ('>>>=', ('identifier', 'abcdefg'), ('identifier', 'x')),
27 def test_precedence_non_assign(self):
28 pairs = combinations(self.DECREASING_PREC_NON_ASSIGN, 2)
29 for [higher, lower] in pairs:
30 for [higher, lower] in product(higher, lower):
31 with self.subTest(f'{higher} vs {lower}'):
32 self.assert_statement(f'A {lower} B {higher} C',
33 (lower, self.A, (higher, self.B, self.C)))
34 self.assert_statement(f'A {higher} B {lower} C',
35 (lower, (higher, self.A, self.B), self.C))
37 def test_assign_precedence(self):
38 for assign in self.ASSIGNMENTS:
39 for op in chain.from_iterable(self.ASSIGN_RHS_ONLY):
40 with self.subTest(f'{assign} {op}'):
41 self.assert_statement(f'A {assign} B {op} C',
42 (assign, self.A, (op, self.B, self.C)))
43 self.assert_statement(f'A . B {assign} C',
44 (assign, ('property', self.A, 'B'), self.C))
45 self.assert_statement(f'A, B {assign} C',
46 (',', self.A, (assign, self.B, self.C)))
47 self.assert_statement(f'A {assign} B, C',
48 (',', (assign, self.A, self.B), self.C))
50 def test_left_associativity(self):
51 for set in self.DECREASING_PREC_NON_ASSIGN:
52 for [lhs, rhs] in product(set, repeat=2):
53 with self.subTest(f'{lhs} {rhs}'):
54 self.assert_statement(f'A {lhs} B {rhs} C',
55 (rhs, (lhs, self.A, self.B), self.C))
57 def test_right_associativity(self):
58 for [lhs, rhs] in product(self.ASSIGNMENTS, repeat=2):
59 with self.subTest(f'{lhs} {rhs}'):
60 self.assert_statement(f'A {lhs} B {rhs} C',
61 (lhs, self.A, (rhs, self.B, self.C)))
63 def test_conditional_precedence(self):
64 for higher in self.ASSIGN_RHS_ONLY:
65 for higher in higher:
66 with self.subTest(higher):
67 self.assert_statement(f'1 {higher} 2 ? 3 : 4',
68 ('?', (higher, 1, 2), 3, 4))
69 self.assert_statement(f'1 ? 2 {higher} 3 : 4',
70 ('?', 1, (higher, 2, 3), 4))
71 self.assert_statement(f'1 ? 2 : 3 {higher} 4',
72 ('?', 1, 2, (higher, 3, 4)))
74 self.assert_statement('1, 2 ? 3 : 4', (',', 1, ('?', 2, 3, 4)))
75 self.assert_statement('1 ? 2 : 3, 4', (',', ('?', 1, 2, 3), 4))
77 for assign in self.ASSIGNMENTS:
78 with self.subTest(assign):
79 self.assert_statement(f'A {assign} 1 ? 2 : 3',
80 (assign, self.A, ('?', 1, 2, 3)))
81 self.assert_statement(f'1 ? A {assign} 2 : 3',
82 ('?', 1, (assign, self.A, 2), 3))
83 self.assert_statement(f'1 ? 2 : A {assign} 3',
84 ('?', 1, 2, (assign, self.A, 3)))
86 self.assert_statement('1 ? 2 : 3 ? 4 : 5',
87 ('?', 1, 2, ('?', 3, 4, 5)))
88 self.assert_statement('1 ? 2 ? 3 : 4 : 5',
89 ('?', 1, ('?', 2, 3, 4), 5))
91 ASSIGN_RHS_ONLY = (
92 ('*', '/', '%'), ('+', '-'),
93 ('<<', '>>', '>>>'),
94 ('<', '>', '<=', '>=', 'instanceof', 'in'),
95 ('==', '!=', '===', '!=='),
96 ('&',), ('^',), ('|',), ('&&',), ('||',),
98 DECREASING_PREC_NON_ASSIGN = ASSIGN_RHS_ONLY + ((',',),)
100 ASSIGNMENTS \
101 = ('', '*', '/', '%', '+', '-', '<<', '>>', '>>>', '&', '^', '|')
102 ASSIGNMENTS = tuple(f'{op}=' for op in ASSIGNMENTS)
104 A = ('identifier', 'A')
105 B = ('identifier', 'B')
106 C = ('identifier', 'C')
108 def test_comment_greed(self):
109 self.assert_statement('/* Comment */ 83 /* Comment */', 83)
111 def test_rounding(self):
112 for [code, rounded] in (
113 ('0.24703''28229''20623''27208e-323', 0),
114 ('0.24703''28229''20623''27209e-323', ldexp(2**-52, -1022)),
115 ('24703''28229''20623''27208e-343', 0),
116 ('24703''28229''20623''27209e-343', ldexp(2**-52, -1022)),
117 ('0.17976''93134''86231''58079e+309', ldexp(1 - 2**-53, +1024)),
118 ('0.17976''93134''86231''58080e+309', inf),
119 ('17976''93134''86231''58079e+289', ldexp(1 - 2**-53, +1024)),
120 ('17976''93134''86231''58080e+289', inf),
121 (f'{2**52 + 0}.5', 2**52),
122 (f'{2**52 + 1}.5', 2**52 + 2),
123 (hex( 2**1024 - 2**(1024 - 53) + (0b10 << (1024 - 55)) ), inf),
124 (hex( 2**1024 - 2**(1024 - 53) + (0b01 << (1024 - 55)) ),
125 ldexp(1 - 2**-53, +1024)),
126 (hex(2**53 + 0b01), 2**53),
127 (hex(2**53 + 0b11), 2**53 + 0b100),
129 with self.subTest(code):
130 [[labels, code]] = javascript.parse(StringIO(code))
131 self.assertEqual(code, rounded)
132 self.assertEqual(copysign(1, code), copysign(1, rounded))
134 def test_div_vs_regex(self):
135 regex = ('regex', 'a', 'g')
136 def div(x):
137 return ('/', ('/', x, ('identifier', 'a')), ('identifier', 'g'))
139 for [code, ast] in (
140 ('/a/g', regex),
141 ('x /a/g', div( ('identifier', 'x') )),
142 ('{ /a/g }', ('block', (
143 (frozenset(), regex),
144 ))),
145 ('return /a/g', ('return', regex)),
146 ('[] /a/g', div([])),
147 ('++ /a/g', ('prefix ++', regex)),
148 ('\n ++ /a/g', ('prefix ++', regex)),
149 ('x ++ /a/g', div( ('postfix ++', ('identifier', 'x')) )),
150 ('++ ++ /a/g', ('prefix ++', ('prefix ++', regex))),
151 ('{ } /a/g', regex),
152 ('( { } /a/g )', div(('object', []))),
153 ('( x ) /a/g', div( ('identifier', 'x') )),
154 ('if ( x ) /a/g',
155 ('if', ('identifier', 'x'), (frozenset(), regex),
156 (frozenset(), ('block', ())))),
157 ('try {} catch (x) {} /a/g', regex),
158 ('try {} finally {} /a/g', regex),
160 with self.subTest(code):
161 for stmt in javascript.parse(StringIO(code)):
162 pass
163 self.assertEqual(stmt, (frozenset(), ast))
165 def test_array_literal(self):
166 ELISION = ('undefined',)
167 self.assert_statement('[]', [])
168 self.assert_statement('[, ]', [ELISION])
169 self.assert_statement('[, , ]', [ELISION, ELISION])
170 self.assert_statement('[81]', [81])
171 self.assert_statement('[81, ]', [81])
172 self.assert_statement('[81, , ]', [81, ELISION])
173 self.assert_statement('[81, , , ]', [81, ELISION, ELISION])
174 self.assert_statement('[81, 82]', [81, 82])
175 self.assert_statement('[81, , 82]', [81, ELISION, 82])
176 self.assert_statement('[81, , , 82]', [81, ELISION, ELISION, 82])
178 def test_object_literal(self):
179 self.assert_statement('({})', ('object', []))
180 self.assert_statement('({A: 81})', ('object', [('A', 81)]))
181 self.assert_statement('({A: 81, B: 82})',
182 ('object', [('A', 81), ('B', 82)]))
183 self.assert_statement('({"A": 81})', ('object', [('A', 81)]))
184 self.assert_statement('({81: 82})', ('object', [(81, 82)]))
186 def assert_statement(self, code, expected):
187 [code] = javascript.parse(StringIO(code))
188 self.assertEqual(code, (frozenset(), expected))