Index: core/scripts/make_token_matcher_unittest.py |
diff --git a/core/scripts/make_token_matcher_unittest.py b/core/scripts/make_token_matcher_unittest.py |
new file mode 100755 |
index 0000000000000000000000000000000000000000..c0c82863970aa5be5e2e18227ff99ecefe3474c2 |
--- /dev/null |
+++ b/core/scripts/make_token_matcher_unittest.py |
@@ -0,0 +1,243 @@ |
+#!/usr/bin/env python |
+# Copyright (C) 2013 Google Inc. All rights reserved. |
+# |
+# Redistribution and use in source and binary forms, with or without |
+# modification, are permitted provided that the following conditions are |
+# met: |
+# |
+# * Redistributions of source code must retain the above copyright |
+# notice, this list of conditions and the following disclaimer. |
+# * Redistributions in binary form must reproduce the above |
+# copyright notice, this list of conditions and the following disclaimer |
+# in the documentation and/or other materials provided with the |
+# distribution. |
+# * Neither the name of Google Inc. nor the names of its |
+# contributors may be used to endorse or promote products derived from |
+# this software without specific prior written permission. |
+# |
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
+ |
+import tempfile |
+import unittest |
+ |
+from make_token_matcher import BadInput, CaseLineProcessor, MainLineProcessor, Optimizer, process_file, SwitchCase, SwitchLineProcessor |
+ |
+ |
+class OptimizerTest(unittest.TestCase): |
+ def test_nonalphabetic(self): |
+ optimizer = Optimizer(None, None, None) |
+ self.assertRaises( |
+ BadInput, |
+ optimizer.inspect_array, |
+ [SwitchCase('-', None), SwitchCase('x', None)], |
+ [0]) |
+ |
+ |
+class MainLineProcessorTest(unittest.TestCase): |
+ def test_switch(self): |
+ processor = MainLineProcessor(None) |
+ switchLineProcessor = processor.process_line('SWITCH(array, length) {') |
+ self.assertIsInstance(switchLineProcessor, SwitchLineProcessor) |
+ self.assertEquals('array', switchLineProcessor.array_variable) |
+ self.assertEquals('length', switchLineProcessor.length_variable) |
+ |
+ |
+class SwitchLineProcessorTest(unittest.TestCase): |
+ def test_case(self): |
+ processor = SwitchLineProcessor(None, None, None, None) |
+ caseLineProcessor = processor.process_line('CASE("identifier") {') |
+ self.assertIsInstance(caseLineProcessor, CaseLineProcessor) |
+ self.assertEquals('identifier', caseLineProcessor.identifier) |
+ |
+ def test_unexpected(self): |
+ processor = SwitchLineProcessor(None, None, None, None) |
+ self.assertRaises( |
+ BadInput, |
+ processor.process_line, |
+ 'unexpected') |
+ |
+ def test_repeated(self): |
+ processor = SwitchLineProcessor(None, None, None, None) |
+ processor.process_line('CASE("x") {').process_line('}') |
+ caseLineProcessor = processor.process_line('CASE("x") {') |
+ self.assertRaises( |
+ BadInput, |
+ caseLineProcessor.process_line, |
+ '}') |
+ |
+ |
+class CaseLineProcessorTest(unittest.TestCase): |
+ def test_break(self): |
+ processor = CaseLineProcessor(None, None, None) |
+ self.assertRaises( |
+ BadInput, |
+ processor.process_line, |
+ 'break;') |
+ |
+ |
+class ProcessFileTest(unittest.TestCase): |
+ SOURCE_SMALL = """ |
+ SWITCH(p, q) { |
+ CASE("a(") { |
+ X; |
+ } |
+ CASE("b(") { |
+ Y; |
+ } |
+ } |
+ """ |
+ |
+ EXPECTED_SMALL = """ |
+ if (LIKELY(q == 2)) { |
+ if (LIKELY(p[1] == '(')) { |
+ if ((p[0] | 0x20) == 'a') { |
+ X; |
+ } else if (LIKELY((p[0] | 0x20) == 'b')) { |
+ Y; |
+ } |
+ } |
+ } |
+ """ |
+ |
+ SOURCE_MEDIUM = """ |
+ SWITCH (p, q) { |
+ CASE ("ab") { |
+ X; |
+ } |
+ CASE ("cd") { |
+ Y; |
+ } |
+ CASE ("ed") { |
+ Z; |
+ } |
+ } |
+ """ |
+ |
+ EXPECTED_MEDIUM = """ |
+ if (LIKELY(q == 2)) { |
+ if ((p[1] | 0x20) == 'b') { |
+ if (LIKELY((p[0] | 0x20) == 'a')) { |
+ X; |
+ } |
+ } else if (LIKELY((p[1] | 0x20) == 'd')) { |
+ if ((p[0] | 0x20) == 'c') { |
+ Y; |
+ } else if (LIKELY((p[0] | 0x20) == 'e')) { |
+ Z; |
+ } |
+ } |
+ } |
+ """ |
+ |
+ SOURCE_LARGE = """ |
+ prefix; |
+ SWITCH(p, q) { |
+ CASE("hij") { |
+ R; |
+ } |
+ CASE("efg") { |
+ S; |
+ } |
+ CASE("c-") { |
+ T; |
+ } |
+ CASE("klm") { |
+ U; |
+ } |
+ |
+ CASE("d-") { |
+ V; |
+ } |
+ CASE("a") { |
+ W; |
+ X; |
+ } |
+ CASE("b-") { |
+ Y; |
+ Z; |
+ } |
+ } |
+ suffix; |
+ """ |
+ |
+ EXPECTED_LARGE = """ |
+ prefix; |
+ switch (q) { |
+ case 1: { |
+ if (LIKELY((p[0] | 0x20) == 'a')) { |
+ W; |
+ X; |
+ } |
+ } break; |
+ case 2: { |
+ if (LIKELY(p[1] == '-')) { |
+ switch ((p[0] | 0x20)) { |
+ case 'b': { |
+ Y; |
+ Z; |
+ } break; |
+ case 'c': { |
+ T; |
+ } break; |
+ case 'd': { |
+ V; |
+ } break; |
+ } |
+ } |
+ } break; |
+ case 3: { |
+ switch ((p[0] | 0x20)) { |
+ case 'e': { |
+ if (LIKELY((p[1] | 0x20) == 'f' && (p[2] | 0x20) == 'g')) { |
+ S; |
+ } |
+ } break; |
+ case 'h': { |
+ if (LIKELY((p[1] | 0x20) == 'i' && (p[2] | 0x20) == 'j')) { |
+ R; |
+ } |
+ } break; |
+ case 'k': { |
+ if (LIKELY((p[1] | 0x20) == 'l' && (p[2] | 0x20) == 'm')) { |
+ U; |
+ } |
+ } break; |
+ } |
+ } break; |
+ } |
+ suffix; |
+ """ |
+ |
+ def validate(self, source, expected): |
+ with tempfile.NamedTemporaryFile() as input_file: |
+ with tempfile.NamedTemporaryFile() as generated_file: |
+ input_file.write(source) |
+ input_file.flush() |
+ process_file(input_file.name, generated_file.name) |
+ # Our code generation does not yet implement pretty indentation. |
+ actual = generated_file.read().replace(' ', '') |
+ expected = expected.replace(' ', '') |
+ self.assertEquals(actual, expected) |
+ |
+ def test_small(self): |
+ self.validate(ProcessFileTest.SOURCE_SMALL, ProcessFileTest.EXPECTED_SMALL) |
+ |
+ def test_medium(self): |
+ self.validate(ProcessFileTest.SOURCE_MEDIUM, ProcessFileTest.EXPECTED_MEDIUM) |
+ |
+ def test_large(self): |
+ self.validate(ProcessFileTest.SOURCE_LARGE, ProcessFileTest.EXPECTED_LARGE) |
+ |
+ |
+if __name__ == "__main__": |
+ unittest.main() |