OLD | NEW |
| (Empty) |
1 #!/usr/bin/env python | |
2 # Copyright (C) 2013 Google Inc. All rights reserved. | |
3 # | |
4 # Redistribution and use in source and binary forms, with or without | |
5 # modification, are permitted provided that the following conditions are | |
6 # met: | |
7 # | |
8 # * Redistributions of source code must retain the above copyright | |
9 # notice, this list of conditions and the following disclaimer. | |
10 # * Redistributions in binary form must reproduce the above | |
11 # copyright notice, this list of conditions and the following disclaimer | |
12 # in the documentation and/or other materials provided with the | |
13 # distribution. | |
14 # * Neither the name of Google Inc. nor the names of its | |
15 # contributors may be used to endorse or promote products derived from | |
16 # this software without specific prior written permission. | |
17 # | |
18 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
19 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
20 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
21 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
22 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
23 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
24 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
25 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
26 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
27 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
28 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
29 | |
30 import tempfile | |
31 import unittest | |
32 | |
33 from make_token_matcher import BadInput, CaseLineProcessor, MainLineProcessor, O
ptimizer, process_file, SwitchCase, SwitchLineProcessor | |
34 | |
35 | |
36 class OptimizerTest(unittest.TestCase): | |
37 def test_nonalphabetic(self): | |
38 optimizer = Optimizer(None, None, None) | |
39 self.assertRaises( | |
40 BadInput, | |
41 optimizer.inspect_array, | |
42 [SwitchCase('-', None), SwitchCase('x', None)], | |
43 [0]) | |
44 | |
45 | |
46 class MainLineProcessorTest(unittest.TestCase): | |
47 def test_switch(self): | |
48 processor = MainLineProcessor(None) | |
49 switchLineProcessor = processor.process_line('SWITCH(array, length) {') | |
50 self.assertIsInstance(switchLineProcessor, SwitchLineProcessor) | |
51 self.assertEquals('array', switchLineProcessor.array_variable) | |
52 self.assertEquals('length', switchLineProcessor.length_variable) | |
53 | |
54 | |
55 class SwitchLineProcessorTest(unittest.TestCase): | |
56 def test_case(self): | |
57 processor = SwitchLineProcessor(None, None, None, None) | |
58 caseLineProcessor = processor.process_line('CASE("identifier") {') | |
59 self.assertIsInstance(caseLineProcessor, CaseLineProcessor) | |
60 self.assertEquals('identifier', caseLineProcessor.identifier) | |
61 | |
62 def test_unexpected(self): | |
63 processor = SwitchLineProcessor(None, None, None, None) | |
64 self.assertRaises( | |
65 BadInput, | |
66 processor.process_line, | |
67 'unexpected') | |
68 | |
69 def test_repeated(self): | |
70 processor = SwitchLineProcessor(None, None, None, None) | |
71 processor.process_line('CASE("x") {').process_line('}') | |
72 caseLineProcessor = processor.process_line('CASE("x") {') | |
73 self.assertRaises( | |
74 BadInput, | |
75 caseLineProcessor.process_line, | |
76 '}') | |
77 | |
78 | |
79 class CaseLineProcessorTest(unittest.TestCase): | |
80 def test_break(self): | |
81 processor = CaseLineProcessor(None, None, None) | |
82 self.assertRaises( | |
83 BadInput, | |
84 processor.process_line, | |
85 'break;') | |
86 | |
87 | |
88 class ProcessFileTest(unittest.TestCase): | |
89 SOURCE_SMALL = """ | |
90 SWITCH(p, q) { | |
91 CASE("a(") { | |
92 X; | |
93 } | |
94 CASE("b(") { | |
95 Y; | |
96 } | |
97 } | |
98 """ | |
99 | |
100 EXPECTED_SMALL = """ | |
101 if (LIKELY(q == 2)) { | |
102 if (LIKELY(p[1] == '(')) { | |
103 if ((p[0] | 0x20) == 'a') { | |
104 X; | |
105 } else if (LIKELY((p[0] | 0x20) == 'b')) { | |
106 Y; | |
107 } | |
108 } | |
109 } | |
110 """ | |
111 | |
112 SOURCE_MEDIUM = """ | |
113 SWITCH (p, q) { | |
114 CASE ("ab") { | |
115 X; | |
116 } | |
117 CASE ("cd") { | |
118 Y; | |
119 } | |
120 CASE ("ed") { | |
121 Z; | |
122 } | |
123 } | |
124 """ | |
125 | |
126 EXPECTED_MEDIUM = """ | |
127 if (LIKELY(q == 2)) { | |
128 if ((p[1] | 0x20) == 'b') { | |
129 if (LIKELY((p[0] | 0x20) == 'a')) { | |
130 X; | |
131 } | |
132 } else if (LIKELY((p[1] | 0x20) == 'd')) { | |
133 if ((p[0] | 0x20) == 'c') { | |
134 Y; | |
135 } else if (LIKELY((p[0] | 0x20) == 'e')) { | |
136 Z; | |
137 } | |
138 } | |
139 } | |
140 """ | |
141 | |
142 SOURCE_LARGE = """ | |
143 prefix; | |
144 SWITCH(p, q) { | |
145 CASE("hij") { | |
146 R; | |
147 } | |
148 CASE("efg") { | |
149 S; | |
150 } | |
151 CASE("c-") { | |
152 T; | |
153 } | |
154 CASE("klm") { | |
155 U; | |
156 } | |
157 | |
158 CASE("d-") { | |
159 V; | |
160 } | |
161 CASE("a") { | |
162 W; | |
163 X; | |
164 } | |
165 CASE("b-") { | |
166 Y; | |
167 Z; | |
168 } | |
169 } | |
170 suffix; | |
171 """ | |
172 | |
173 EXPECTED_LARGE = """ | |
174 prefix; | |
175 switch (q) { | |
176 case 1: { | |
177 if (LIKELY((p[0] | 0x20) == 'a')) { | |
178 W; | |
179 X; | |
180 } | |
181 } break; | |
182 case 2: { | |
183 if (LIKELY(p[1] == '-')) { | |
184 switch ((p[0] | 0x20)) { | |
185 case 'b': { | |
186 Y; | |
187 Z; | |
188 } break; | |
189 case 'c': { | |
190 T; | |
191 } break; | |
192 case 'd': { | |
193 V; | |
194 } break; | |
195 } | |
196 } | |
197 } break; | |
198 case 3: { | |
199 switch ((p[0] | 0x20)) { | |
200 case 'e': { | |
201 if (LIKELY((p[1] | 0x20) == 'f' && (p[2] | 0x20) == 'g')) { | |
202 S; | |
203 } | |
204 } break; | |
205 case 'h': { | |
206 if (LIKELY((p[1] | 0x20) == 'i' && (p[2] | 0x20) == 'j')) { | |
207 R; | |
208 } | |
209 } break; | |
210 case 'k': { | |
211 if (LIKELY((p[1] | 0x20) == 'l' && (p[2] | 0x20) == 'm')) { | |
212 U; | |
213 } | |
214 } break; | |
215 } | |
216 } break; | |
217 } | |
218 suffix; | |
219 """ | |
220 | |
221 def validate(self, source, expected): | |
222 with tempfile.NamedTemporaryFile() as input_file: | |
223 with tempfile.NamedTemporaryFile() as generated_file: | |
224 input_file.write(source) | |
225 input_file.flush() | |
226 process_file(input_file.name, generated_file.name) | |
227 # Our code generation does not yet implement pretty indentation. | |
228 actual = generated_file.read().replace(' ', '') | |
229 expected = expected.replace(' ', '') | |
230 self.assertEquals(actual, expected) | |
231 | |
232 def test_small(self): | |
233 self.validate(ProcessFileTest.SOURCE_SMALL, ProcessFileTest.EXPECTED_SMA
LL) | |
234 | |
235 def test_medium(self): | |
236 self.validate(ProcessFileTest.SOURCE_MEDIUM, ProcessFileTest.EXPECTED_ME
DIUM) | |
237 | |
238 def test_large(self): | |
239 self.validate(ProcessFileTest.SOURCE_LARGE, ProcessFileTest.EXPECTED_LAR
GE) | |
240 | |
241 | |
242 if __name__ == "__main__": | |
243 unittest.main() | |
OLD | NEW |