| from unittest import TestCase, main |
| |
| from multiprocessing import Process, Queue |
| from six.moves.queue import Empty |
| |
| import sys |
| |
| if ".." not in sys.path: |
| sys.path.insert(0, "..") |
| |
| from ply.lex import lex |
| from ply.cpp import * |
| |
| |
| def preprocessing(in_, out_queue): |
| out = None |
| |
| try: |
| p = Preprocessor(lex()) |
| p.parse(in_) |
| tokens = [t.value for t in p.parser] |
| out = "".join(tokens) |
| finally: |
| out_queue.put(out) |
| |
| class CPPTests(TestCase): |
| "Tests related to ANSI-C style lexical preprocessor." |
| |
| def __test_preprocessing(self, in_, expected, time_limit = 1.0): |
| out_queue = Queue() |
| |
| preprocessor = Process( |
| name = "PLY`s C preprocessor", |
| target = preprocessing, |
| args = (in_, out_queue) |
| ) |
| |
| preprocessor.start() |
| |
| try: |
| out = out_queue.get(timeout = time_limit) |
| except Empty: |
| preprocessor.terminate() |
| raise RuntimeError("Time limit exceeded!") |
| else: |
| self.assertMultiLineEqual(out, expected) |
| |
| def test_concatenation(self): |
| self.__test_preprocessing("""\ |
| #define a(x) x##_ |
| #define b(x) _##x |
| #define c(x) _##x##_ |
| #define d(x,y) _##x##y##_ |
| |
| a(i) |
| b(j) |
| c(k) |
| d(q,s)""" |
| , """\ |
| |
| |
| |
| |
| |
| i_ |
| _j |
| _k_ |
| _qs_""" |
| ) |
| |
| def test_deadloop_macro(self): |
| # If there is a word which equals to name of a parametrized macro, then |
| # attempt to expand such word as a macro manages the parser to fall |
| # into an infinite loop. |
| |
| self.__test_preprocessing("""\ |
| #define a(x) x |
| |
| a;""" |
| , """\ |
| |
| |
| a;""" |
| ) |
| |
| def test_index_error(self): |
| # If there are no tokens after a word ("a") which equals to name of |
| # a parameterized macro, then attempt to expand this word leads to |
| # IndexError. |
| |
| self.__test_preprocessing("""\ |
| #define a(x) x |
| |
| a""" |
| , """\ |
| |
| |
| a""" |
| ) |
| |
| main() |