From 31d907118ac436fb5e0db21d6e7cce1362aa6bc1 Mon Sep 17 00:00:00 2001 From: Michael Hansen Date: Thu, 3 Oct 2019 15:33:52 -0700 Subject: [PATCH] Add a new unit test framework that actually checks the output of decompiled sources against an expected result. --- CMakeLists.txt | 15 +- scripts/token_dump | 251 ++++++++++++++++++++++++++++ tests/all_tests.sh | 10 ++ tests/compiled/simple_const.1.0.pyc | Bin 0 -> 232 bytes tests/compiled/simple_const.1.1.pyc | Bin 0 -> 232 bytes tests/compiled/simple_const.1.2.pyc | Bin 0 -> 232 bytes tests/compiled/simple_const.1.3.pyc | Bin 0 -> 243 bytes tests/compiled/simple_const.1.4.pyc | Bin 0 -> 241 bytes tests/compiled/simple_const.1.5.pyc | Bin 0 -> 274 bytes tests/compiled/simple_const.1.6.pyc | Bin 0 -> 274 bytes tests/compiled/simple_const.2.0.pyc | Bin 0 -> 274 bytes tests/compiled/simple_const.2.1.pyc | Bin 0 -> 326 bytes tests/compiled/simple_const.2.2.pyc | Bin 0 -> 337 bytes tests/compiled/simple_const.2.3.pyc | Bin 0 -> 323 bytes tests/compiled/simple_const.2.4.pyc | Bin 0 -> 332 bytes tests/compiled/simple_const.2.5.pyc | Bin 0 -> 293 bytes tests/compiled/simple_const.2.6.pyc | Bin 0 -> 291 bytes tests/compiled/simple_const.2.7.pyc | Bin 0 -> 291 bytes tests/compiled/simple_const.3.0.pyc | Bin 0 -> 295 bytes tests/compiled/simple_const.3.1.pyc | Bin 0 -> 295 bytes tests/compiled/simple_const.3.2.pyc | Bin 0 -> 295 bytes tests/compiled/simple_const.3.3.pyc | Bin 0 -> 299 bytes tests/compiled/simple_const.3.4.pyc | Bin 0 -> 251 bytes tests/compiled/simple_const.3.5.pyc | Bin 0 -> 250 bytes tests/compiled/simple_const.3.6.pyc | Bin 0 -> 232 bytes tests/compiled/simple_const.3.7.pyc | Bin 0 -> 231 bytes tests/decompyle_test.sh | 61 +++++++ tests/input/simple_const.py | 12 ++ tests/tokenized/simple_const.txt | 7 + 29 files changed, 347 insertions(+), 9 deletions(-) create mode 100755 scripts/token_dump create mode 100755 tests/all_tests.sh create mode 100644 tests/compiled/simple_const.1.0.pyc create mode 100644 tests/compiled/simple_const.1.1.pyc create mode 100644 tests/compiled/simple_const.1.2.pyc create mode 100644 tests/compiled/simple_const.1.3.pyc create mode 100644 tests/compiled/simple_const.1.4.pyc create mode 100644 tests/compiled/simple_const.1.5.pyc create mode 100644 tests/compiled/simple_const.1.6.pyc create mode 100644 tests/compiled/simple_const.2.0.pyc create mode 100644 tests/compiled/simple_const.2.1.pyc create mode 100644 tests/compiled/simple_const.2.2.pyc create mode 100644 tests/compiled/simple_const.2.3.pyc create mode 100644 tests/compiled/simple_const.2.4.pyc create mode 100644 tests/compiled/simple_const.2.5.pyc create mode 100644 tests/compiled/simple_const.2.6.pyc create mode 100644 tests/compiled/simple_const.2.7.pyc create mode 100644 tests/compiled/simple_const.3.0.pyc create mode 100644 tests/compiled/simple_const.3.1.pyc create mode 100644 tests/compiled/simple_const.3.2.pyc create mode 100644 tests/compiled/simple_const.3.3.pyc create mode 100644 tests/compiled/simple_const.3.4.pyc create mode 100644 tests/compiled/simple_const.3.5.pyc create mode 100644 tests/compiled/simple_const.3.6.pyc create mode 100644 tests/compiled/simple_const.3.7.pyc create mode 100755 tests/decompyle_test.sh create mode 100644 tests/input/simple_const.py create mode 100644 tests/tokenized/simple_const.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index faf12d4..f32d2de 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -57,18 +57,15 @@ target_link_libraries(pycdc pycxx) install(TARGETS pycdc RUNTIME DESTINATION bin) -# For tests -if(POLICY CMP0037) - # Don't complain about adding a target named "test" - cmake_policy(SET CMP0037 OLD) -endif() - -add_custom_target(test "${CMAKE_CURRENT_SOURCE_DIR}/pycdc_test.sh" +add_custom_target(dc_test "${CMAKE_CURRENT_SOURCE_DIR}/pycdc_test.sh" "${CMAKE_CURRENT_SOURCE_DIR}/tests" WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") -add_dependencies(test pycdc) +add_dependencies(dc_test pycdc) add_custom_target(rt_test "${CMAKE_CURRENT_SOURCE_DIR}/pycdc_rt_test.sh" "${CMAKE_CURRENT_BINARY_DIR}/tests" WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") -add_dependencies(rt_test test) +add_dependencies(rt_test dc_test) + +add_custom_target(check "${CMAKE_CURRENT_SOURCE_DIR}/tests/all_tests.sh" + WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") diff --git a/scripts/token_dump b/scripts/token_dump new file mode 100755 index 0000000..5ed0392 --- /dev/null +++ b/scripts/token_dump @@ -0,0 +1,251 @@ +#!/usr/bin/env python3 + +# Compare two python source files by tokens, ignoring whitespace (other than +# indentation) and comments + +import sys +import re + + +class PyToken: + INDENT = 1 + OUTDENT = 2 + ENDLINE = 3 + WORD = 100 + INT = 101 + FLOAT = 102 + STRING = 103 + + def __init__(self, type, n_line): + self.type = type + self.n_line = n_line + + def __str__(self): + if self.type == PyToken.INDENT: + return '' + if self.type == PyToken.OUTDENT: + return '' + if self.type == PyToken.ENDLINE: + return '' + return str(self.type) + + def __eq__(self, other): + return self.type == other.type + + +class WordToken(PyToken): + # We don't need to distinguish between keywords and other words, so + # we just lump them together in a single token type... + def __init__(self, word, n_line): + super().__init__(PyToken.WORD, n_line) + self.word = word + + def __str__(self): + return self.word + + def __eq__(self, other): + if not super().__eq__(other): + return False + return self.word == other.word + + +class IntToken(PyToken): + def __init__(self, value, n_line): + super().__init__(PyToken.INT, n_line) + try: + self.value = int(value.replace('_', ''), 0) + except ValueError: + # Support Python 2.x octal literals + if value.startswith('0'): + self.value = int(value.replace('_', ''), 8) + else: + raise + + def __str__(self): + return str(self.value) + + def __eq__(self, other): + if not super().__eq__(other): + return False + return self.value == other.value + + +class FloatToken(PyToken): + def __init__(self, value, n_line): + super().__init__(PyToken.FLOAT, n_line) + self.value = float(value.replace('_', '')) + + def __str__(self): + return str(self.value) + + def __eq__(self, other): + if not super().__eq__(other): + return False + # TODO: Might need some fuzz + return self.value == other.value + + +class StringToken(PyToken): + def __init__(self, prefix, quotes, line, n_line): + super().__init__(PyToken.STRING, n_line) + + # Normalize prefix for comparison + if prefix is None: + self.prefix = '' + else: + self.prefix = ''.join(sorted(prefix.lower())) + + # Look for the end of the string + self.endpos = len(self.prefix) + len(quotes) + scan = line[self.endpos:] + while True: + if scan[0] == '\\': + scan = scan[2:] + self.endpos += 2 + continue + if scan.startswith(quotes): + self.endpos += len(quotes) + break + scan = scan[1:] + self.endpos += 1 + + self.content = line[len(self.prefix) + len(quotes):self.endpos - len(quotes)] + + # TODO: Normalize special characters for comparison + self.content.replace("'", "\\'") + + def __str__(self): + return "{}'{}'".format(self.prefix, self.content) + + def __eq__(self, other): + if not super().__eq__(other): + return False + return self.prefix == other.prefix and self.content == other.content + + +RE_WHITESPACE = re.compile(r'\s+') +RE_WORD = re.compile(r'[A-Za-z_][A-Za-z0-9_]*') +RE_INT = re.compile(r'[0-9][0-9_]*|0[Xx][0-9A-Fa-f_]+|0[Bb][0-1_]+|0[Oo][0-7_]+') +RE_FLOAT = re.compile(r'(([0-9][0-9_]*)?\.[0-9][0-9_]*|[0-9][0-9_]*\.)([eE][+-]?[0-9][0-9_]*)?') +RE_START_STRING = re.compile(r'([rR][fFbB]?|[uU]|[fF][rR]?|[bB][rR]+)?(\'\'\'|\'|"""|")') + +# Note, tokens sharing a common prefix should be entered in order from +# longest to shortest, so we don't mismatch a long token as a sequence +# of shorter tokens +SYMBOLIC_TOKENS = ( + '<<=', '>>=', '**=', '//=', '...', '.', + '+=', '-=', '*=', '@=', '/=', '%=', '&=', '|=', '^=', + '<>', '<<', '<=', '<', '>>', '>=', '>', '!=', '==', '=', + ',', ';', ':=', ':', '->', '~', + '+', '-', '**', '*', '@', '//', '/', '%', '&', '|', '^', + '(', ')', '{', '}', '[', ']', +) +def symbolic_token(line, n_line): + for tok in SYMBOLIC_TOKENS: + if line.startswith(tok): + return PyToken(tok, n_line) + return None + + +def read_tokens(pysrc): + indent_stack = [0] + context_stack = [] + n_line = 0 + + while True: + line = pysrc.readline() + n_line += 1 + if not line: + break + + sline = line.strip() + if not sline or sline.startswith('#'): + continue + + # Look for indentation changes + if len(context_stack) == 0: + indent = len(line) - len(line.lstrip()) + if indent > indent_stack[-1]: + indent_stack.append(indent) + yield PyToken(PyToken.INDENT, n_line) + while indent < indent_stack[-1]: + indent_stack.pop() + yield PyToken(PyToken.OUTDENT, n_line) + if indent != indent_stack[-1]: + raise RuntimeError('Incorrect indentation on line {}'.format(n_line)) + + while sline: + idx = 0 + while sline[idx].isspace(): + idx += 1 + sline = sline[idx:] + + token = symbolic_token(sline, n_line) + if token: + if token.type in {'(', '{', '['}: + context_stack.append(token.type) + elif token.type == ')': + if len(context_stack) == 0 or context_stack[-1] != '(': + raise RuntimeError('Mismatched token at {} on line {}'.format(sline, n_line)) + context_stack.pop() + elif token.type == '}': + if len(context_stack) == 0 or context_stack[-1] != '{': + raise RuntimeError('Mismatched token at {} on line {}'.format(sline, n_line)) + context_stack.pop() + elif token.type == ']': + if len(context_stack) == 0 or context_stack[-1] != '[': + raise RuntimeError('Mismatched token at {} on line {}'.format(sline, n_line)) + context_stack.pop() + yield token + sline = sline[len(token.type):] + continue + + match = RE_FLOAT.match(sline) + if match: + yield FloatToken(match.group(), n_line) + sline = sline[match.end():] + continue + + match = RE_INT.match(sline) + if match: + yield IntToken(match.group(), n_line) + sline = sline[match.end():] + continue + + match = RE_START_STRING.match(sline) + if match: + token = StringToken(match.group(1), match.group(2), sline, n_line) + yield token + sline = sline[token.endpos:] + continue + + match = RE_WORD.match(sline) + if match: + yield WordToken(match.group(), n_line) + sline = sline[match.end():] + continue + + print('Error: Unrecognized tokens: "{}" at line {}'.format(sline, n_line)) + sys.exit(1) + + if len(context_stack) == 0: + yield PyToken(PyToken.ENDLINE, n_line) + + +if __name__ == '__main__': + if '--help' in sys.argv: + print('Usage: token_dump .py') + sys.exit(0) + + if len(sys.argv) >= 2: + pysrc = open(sys.argv[1], 'r') + else: + pysrc = sys.stdin + + for tok in read_tokens(pysrc): + if tok.type in {PyToken.ENDLINE, PyToken.INDENT, PyToken.OUTDENT}: + print(tok) + else: + print(tok, end=' ') + + pysrc.close() diff --git a/tests/all_tests.sh b/tests/all_tests.sh new file mode 100755 index 0000000..ae8f057 --- /dev/null +++ b/tests/all_tests.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +srcdir="$(cd "$(dirname "${BASH_SOURCE[0]}")"/.. && pwd)" + +test_files=( "$srcdir"/tests/tokenized/*.txt ) +for tf in "${test_files[@]}"; do + test_name="$(basename "$tf")" + test_name="${test_name%.txt}" + "$srcdir"/tests/decompyle_test.sh $test_name tests +done diff --git a/tests/compiled/simple_const.1.0.pyc b/tests/compiled/simple_const.1.0.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b6997b6057503cbe08b52c4d9cd0367d977750da GIT binary patch literal 232 zcmXZVy$ZrG6b0bZG;Qh+K8Qo5sDmOnxVyNesA!YaB85V_bjnjW^j&;7Z-Nj$ayXZJ z**N06|6EV@2Efrvp#VuA0Tn?;a2XVXWN;Ix7>dJCjNztG2@K6}xY@s|sY>AHcmbRi zF_q#VX{W%Y%;-e3B#c<+#irQqET`0K+c%N#m?tKz=dFixDSYzfBlrwfK^4?N6Rhom SCi7J{wAH=WZI^dLD2_jEJSL<7 literal 0 HcmV?d00001 diff --git a/tests/compiled/simple_const.1.1.pyc b/tests/compiled/simple_const.1.1.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fa93803332aad0e80afc93f06d90d7c9f2129226 GIT binary patch literal 232 zcmXZVy$ZrG6b0bZByH*sK1Xq=6m?Jp2X_~@fQmLvEmA0?OQ$@ALm$bv@+Ju3BZqUj zmyaX9`_J`cZvY&<1R7BEk z#B_p#qMZ_#ETt38k}z_e7n@?cvw~7z*}jQ<$2^>{o_95zGwG8rAHip^4C-JNG{M>~ TXfj`QLtEbas_pV_2*vRSQmiIS literal 0 HcmV?d00001 diff --git a/tests/compiled/simple_const.1.2.pyc b/tests/compiled/simple_const.1.2.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1d91a84fe8991595c1f73d7a92b12603e3f5becd GIT binary patch literal 232 zcmXZVO$x#=5C!1ZCT;2uo};*^6m=m8F5J6u7f{hAsYMEf6tSz^Lg;Os1R;Fn@rD^T zj`+O4m!rJ`aP(3rK+;D*MUW9(1{Fiba1$s7#bGEixG7WuLo*z1_OEKH61X{@0H;N< zO0k!;Q{bFubfQ@jMy!i+Q*L*bQ|h(to5**uhY{BE(!(hiKKb$elPFE4m>RhaW(mCO7~9 literal 0 HcmV?d00001 diff --git a/tests/compiled/simple_const.1.3.pyc b/tests/compiled/simple_const.1.3.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6526c59aa70525d767171fffd070b2edaa68c9d5 GIT binary patch literal 243 zcmXZVO$x#=5C!1ZHf?JCIY)63De6KHyn!2c0TpeMTBJ}&5xUCSwcvT31Vi{H!y6`V zF)u!^@3}@e_Cm$c&7c5D4-OSUMsPV)3>m{spb{tsLu~?AK&3D=!{Da>sG%r@o8bX4 zS`@1cdr3PvPGwGCv`fP9wWv1Lc4rxNgSJB(`7HJ%g!Mf2cr3Z^e0U4qgLO~^bI+^`aj`diVj(X(luP literal 0 HcmV?d00001 diff --git a/tests/compiled/simple_const.1.4.pyc b/tests/compiled/simple_const.1.4.pyc new file mode 100644 index 0000000000000000000000000000000000000000..191a417efe246259a3a674e205a0acc15eaf7015 GIT binary patch literal 241 zcmXZVK?=e!5CzcRHZ`@@wO1%E3PoKAf;VvEE})`KQi~J{DMD8{gy4Cd42JL~!yhJM zwah>7@1+4BcctR#&Y%HB4+$MXMerGP3>CxAp%Z8UOKk$5L#MDbBj6YRsHG@{FYp8e zEsFIF2Sqz2&SgelbZf%OO;vB}-QEf6M&rgV3RxUT2p4#n=~T+lh49Wk*oM`tVJ+L1 TGzeD^!_+so(ey(#Oq?Bm^VTIf literal 0 HcmV?d00001 diff --git a/tests/compiled/simple_const.1.5.pyc b/tests/compiled/simple_const.1.5.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4760828bd5d3828c1d009eb38ce1b3338a545d93 GIT binary patch literal 274 zcmXYqF%E)25Jmq2f*{7$BM=J=Q413jZ(w6bj7C{dq9Vy+VYQWq@RFXvzZ+*~UUu?- z{(LsW==(nG3a~tm+7p`XLjpNJ0i-}Kp!<*xatAtubRj)dTwUl0vWJQu4|?#I&Xju4 zF)oZ{kRyGpa%KkDCVif$Cqxy@(rlhBmdc#&O4ZfEXpVtPD1&SH+9ZM5jCiy>Sr(Sk tvb3x$&k2oCV-)q$-&C~kUK2$_gBtpKSh&Vs^20=f(7Aa$TaNEgyW$<>AKL3U8m<3acT(uqMQ;405E8Rm#i&+qlaU)tD%QSu&kZ7fWSMw}omeVKm3UC6vLXcy8jrY(_j-9xZcA uX<1m7mZz9Ts1cDQld5hW?L<|#=2~R=y;g0~Jgsl-Lq#-2BIFy2i1Pz@4J)hw literal 0 HcmV?d00001 diff --git a/tests/compiled/simple_const.2.1.pyc b/tests/compiled/simple_const.2.1.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0f293b0b4defb6c2c6f29dd2f795fd83b3b1c976 GIT binary patch literal 326 zcmZXN%?iRW5QHafZT+cu^%07Pil_%c@D03pD`L^6)#6_v_24NdpH}c0oCHC^B>SN;0-DU9YAxP&q|=J#b3n8}D+%bjIr zDJ^r$!gBw$e?I<vR^C(JjK znfH>_XE=Djl4D9;Sg2d1*a4g<1{uYSxIwW&+$3&MjvkFoIaXFTEHJd`LS%7AI?Z*A z>e9jQ;i+;0YzBS1kVJ yTBuE0s7-}7`FNKU#28%=gk@Dfn^2VZ`j#c>qY_O}w@SQmpb#G5FnK)IM}7euRWKz0 literal 0 HcmV?d00001 diff --git a/tests/compiled/simple_const.2.4.pyc b/tests/compiled/simple_const.2.4.pyc new file mode 100644 index 0000000000000000000000000000000000000000..74a69b5148fbacb190a09bd1063c6604465d6079 GIT binary patch literal 332 zcmYL?OK!qI42C^P2oJ%gs~%z0MNkAtAc5!!ScKgO3ALGoM!X`;u;2h(mjx%lzbW96 zKYRT6y}$K3*UNg9)4xR=zuDc4VTlY=kx^s=G6C5ZnUHLoOhlHGh&Ehr&>vA`V=RPI z!?8(A-C>35i&1_Il607k#*?>s9P)+pmBLs6geU>q;=IsOdNs9VXzC`$@cj|~3Ui?q z7Q#}vk?{;-8BS)9$YP)Yv;Zh-_6PhYXGzkp4)w|RUA3=w#X3J8oKNbrh|aO^x{O#o HUsv4$Anz?P literal 0 HcmV?d00001 diff --git a/tests/compiled/simple_const.2.5.pyc b/tests/compiled/simple_const.2.5.pyc new file mode 100644 index 0000000000000000000000000000000000000000..64f5dc60f6ac287cf097efef2dbeec59012ab527 GIT binary patch literal 293 zcmYL>O$x#=6oeIGChfg5*05bcY#*w#Yg!UO1qyqAbOcfJIF67pr< z%=M8xO$ z4sXaujI6p2975-24*!laOET zzPpgyv){X4vQ>`HYSEq2(Nls11d%~7NDsn;>_D_2yAVDk2_FT`+t^WongJ#vfDEzZ zJ$he`2}OM!K3=14YJ74=X;U(rc^39NW3gA~1$U!g$epqw4{gobwd2Myca)CGaqC!c tD&h}4AREU?SvMz>=9YAqxVK7c;12u^NZf*%R_#*0Ch47=CwK$MMJ$s5 literal 0 HcmV?d00001 diff --git a/tests/compiled/simple_const.3.0.pyc b/tests/compiled/simple_const.3.0.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6976883ce0f69a993af8d025e045ea774602b4b7 GIT binary patch literal 295 zcmYj~zY4-I7{sr&wkmZOoZNy#-CPv$30&NQAlk%I)LKY0_yGF2;_Bul;Gcy2xclxt zGE4it$8EdG@poF(OFlCr6d=g}GJpypL#Pg93#tnlK~Y2~IB%n5fz23G8AByliyrsO zF;P_a;qx`>E^S2DXw$IFEOc<+S%;&(u7n?bL*bPRMdE7C?mYLNxu^2fo(IoDu!tY* qfHun}WmVf|V#;%U(%bw}nI@~Rw!?6Kz9@Urizo>8oU7#zbo(n literal 0 HcmV?d00001 diff --git a/tests/compiled/simple_const.3.1.pyc b/tests/compiled/simple_const.3.1.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f2dfde6fca10fdd096ccb76fec748b60f5ba62a6 GIT binary patch literal 295 zcmYj~JqyAx7=*92)(`3~IJpIfy16LgFVMj)2%=3aMXiN2gFirjuDH5+3HXtahr9Rg zC99;@ecZO241cFVz2GxbLIIKtAOolnGK6YFHlR9?5fnv)obx6M7TAn2kug*YYtiL? zF(UHvK6t){orR6)YHezknS~DSJL_=N*QM~IZz#NSp=i09vpdhdXXdFqwdcVz7cAlj q+ow&_aZy&b9-HD^o%A-ll%`Irt8Fu!oiECs^gO0E2@waMn*?tu%Pa%{ literal 0 HcmV?d00001 diff --git a/tests/compiled/simple_const.3.2.pyc b/tests/compiled/simple_const.3.2.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b509841321d28103b633bca8a3c36e638352926f GIT binary patch literal 295 zcmYj~JqyAx7=*92)(`3~IJpIfy16LgFK}@Sf@l*MWDM28M)bK~ zOo+U?kDjk_Z)GF8Mw^CZW}$=o&N`g*buIkp8w#&nC_1j@?B4U>nRzNt?RoUf1&jE> q4r$YLT2!@drlvU8rQT(i$~0+xwOxjb^F`TGFJo$x5OMIiN$>_sHY_0k literal 0 HcmV?d00001 diff --git a/tests/compiled/simple_const.3.3.pyc b/tests/compiled/simple_const.3.3.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d8f19bf6c059e46c19b7fc8497e0f16c78fd1a52 GIT binary patch literal 299 zcmYL?zY4-I7{sr&)<4u;aB>R{b#qa~Cvb5Kf@l*^ z?n3TKulu-e)-M1V=XV-Z3yzr*3Xo&~89;@QAygZ(0o8$wpeQ2b+&59Mz-EkzjG!ecCh~7iDGZu_;c~QE#$yY3j7P*fzu2>8$Kg&tqzn5OMImN$>%xi!Dn4 literal 0 HcmV?d00001 diff --git a/tests/compiled/simple_const.3.4.pyc b/tests/compiled/simple_const.3.4.pyc new file mode 100644 index 0000000000000000000000000000000000000000..72e40f9a257dcec79d45fe9aef965b1c53c020ef GIT binary patch literal 251 zcmX|)J&wXa427SQ5PlSTq^&4J5jq+W;si8wqm|IY3{eDxC=&_}0C(X^ZmH5BN|p*w z0k-`4>FLS7N8Qf-y!?FvxXFCW7d4ZyV}S;gke~?KgYuwTP(E}UDu5OdAQiuXOahV& zF;XFP6N|W059C6cUw$6{{q{@+m9bS#;?C+Lt0sbpB AV*mgE literal 0 HcmV?d00001 diff --git a/tests/compiled/simple_const.3.5.pyc b/tests/compiled/simple_const.3.5.pyc new file mode 100644 index 0000000000000000000000000000000000000000..93e2eac1d7a2a358f5a287ba70fd7d62c1ea5951 GIT binary patch literal 250 zcmX|)F>b;@5Jmsk#$beNkW!^Ih20|*`2=a`R!A0MHv(oZl0#bx!M?gxbKZA=8HGgK5j8 znGDk>Q~857c1efZEKRejZcbfht3$Il#r9a+E^W>{S{{!2v^Q^|OHSh^So; zIiBX%-t*mW&9thFt!iMec7?UaAa7^R^GKG?DV-BRsoZH2tO+&*2>}uqf-OOM6J_X< q4xerukFvZtRU?}nioIDS$J|zNai(B$IO1tD3! literal 0 HcmV?d00001 diff --git a/tests/compiled/simple_const.3.7.pyc b/tests/compiled/simple_const.3.7.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7da3ad5899444ceb309b49ddf389e031299cd54c GIT binary patch literal 231 zcmXv`y9&ZU5WKxSjADAh%FbBC9}p2gz{c(ng1To2CNbn<;Rooy_)FVbr4dWDa<6cf zotYhmU4~&#FrL?B^Jab6;}6MZ!E44$D3m}@fKo|xl!LBv(L+C#%EJzd43v+-T14G; z!u7Pg4PT#8ccI)yn&2 + exit 1 +fi +if [[ -z "$outdir" ]]; then + echo "Missing required parameter: outdir" >&2 + exit 1 +fi + +shopt -s nullglob +compfiles=( "$testdir/compiled/$testname".?.?.pyc ) +shopt -u nullglob + +if (( ${#compfiles[@]} == 0 )); then + echo "No compiled modules found for compiled/$testname.*.pyc" + exit 1 +fi + +mkdir -p "$outdir" + +fails=0 +for pyc in "${compfiles[@]}"; do + base="$outdir/$(basename "$pyc")" + + echo -ne "\033[1m*** $(basename "$pyc"):\033[0m " + + ./pycdc "$pyc" 2>"$base.err" 1>"$base.src.py" + if (( $? )) || [[ -s "$base.err" ]] + then + let fails+=1 + echo -e "\033[31mFAIL\033[m" + cat "$base.err" + continue + fi + + "$srcdir"/scripts/token_dump "$base.src.py" 2>"$base.tok.err" 1>"$base.tok.txt" + if (( $? )) || [[ -s "$base.tok.err" ]] + then + let fails+=1 + echo -e "\033[31mFAIL\033[m" + cat "$base.tok.err" + continue + fi + + if ! diff "$base.tok.txt" "$testdir/tokenized/$testname.txt" >/dev/null + then + let fails+=1 + echo -e "\033[31mFAIL\033[m" + echo "$base.tok.txt does not match $testdir/tokenized/$testname.txt" + continue + fi + + echo -e "\033[32mPASS\033[m" +done diff --git a/tests/input/simple_const.py b/tests/input/simple_const.py new file mode 100644 index 0000000..074c67e --- /dev/null +++ b/tests/input/simple_const.py @@ -0,0 +1,12 @@ +# Description: Simple constants applicable to any Python version +# Valid Pythons: all + +# Note: Python 1.0 will insert an implied "print" statement into each line + +a = 42 +b = 3.14159 +c = "test" +d = (1, 2) +e = (3,) +f = [1, 2] +g = {'key': 42} diff --git a/tests/tokenized/simple_const.txt b/tests/tokenized/simple_const.txt new file mode 100644 index 0000000..378d0c2 --- /dev/null +++ b/tests/tokenized/simple_const.txt @@ -0,0 +1,7 @@ +a = 42 +b = 3.14159 +c = 'test' +d = ( 1 , 2 ) +e = ( 3 , ) +f = [ 1 , 2 ] +g = { 'key' : 42 }