Add some disassemble tests using pytest.

This commit is contained in:
rocky 2015-12-15 17:55:57 -05:00
parent fcfe451547
commit dafca53022
11 changed files with 228 additions and 21 deletions

View File

@ -11,22 +11,22 @@ RM ?= rm
LINT = flake8
#EXTRA_DIST=ipython/ipy_trepan.py trepan
PHONY=check clean dist distclean lint flake8 test test-unit test-functional rmChangeLog clean_pyc nosetests
PHONY=check clean pytest dist distclean lint flake8 test test-unit test-functional rmChangeLog clean_pyc nosetests
#: Default target - same as "check"
all: check
#: Make HTML docs
html:
cd docs && $(MAKE) html
#: Same as "check"
test: check
test check: pytest check-short
#: Run tests
check check-short:
check-short: pytest
$(MAKE) -C test $@
#: Run tests
pytest:
$(MAKE) -C pytest check
#: Clean up temporary files and .pyc files
clean: clean_pyc
$(PYTHON) ./setup.py $@

View File

@ -4,6 +4,9 @@ machine:
environment:
COMPILE: --compile
dependencies:
override:
- pip install -r test-requirements.txt
test:
override:
- python ./setup.py develop && make check

7
pytest/Makefile Normal file
View File

@ -0,0 +1,7 @@
PHONY=check test pytest
PYTHON ?= python
#: Run all tests
test check pytest:
py.test

33
pytest/test_disasm.py Normal file
View File

@ -0,0 +1,33 @@
import os.path
import pytest
from uncompyle6.disas import disassemble_file
def get_srcdir():
filename = os.path.normcase(os.path.dirname(__file__))
return os.path.realpath(filename)
src_dir = get_srcdir()
os.chdir(src_dir)
@pytest.mark.parametrize(("test_tuple", "function_to_test"), [
(
('../test/bytecode_2.5/test_import.pyc', 'testdata/test_import_25.right',),
disassemble_file
),
(
('../test/bytecode_2.7/test1.pyc', 'testdata/test1.right',),
disassemble_file
),
])
def test_funcoutput(capfd, test_tuple, function_to_test):
in_file , filename_expected = test_tuple
function_to_test(in_file)
resout, reserr = capfd.readouterr()
expected = open(filename_expected, "r").read()
if resout != expected:
with open(filename_expected + ".got", "w") as out:
out.write(resout)
assert resout == expected

88
pytest/testdata/test1.right vendored Normal file
View File

@ -0,0 +1,88 @@
# Python 2.7
# Embedded file name: /src/external-vcs/github/rocky/python-uncompyle6/__pkginfo__.py
1 0 LOAD_CONST 'uncompyle6 packaging information'
3 STORE_NAME '__doc__'
13 6 LOAD_CONST '\nCopyright (C) 2015 Rocky Bernstein <rocky@gnu.org>.\n'
9 STORE_NAME 'copyright'
15 12 LOAD_CONST 'Development Status :: 3 - Alpha'
16 15 LOAD_CONST 'Intended Audience :: Developers'
17 18 LOAD_CONST 'Operating System :: OS Independent'
18 21 LOAD_CONST 'Programming Language :: Python'
19 24 LOAD_CONST 'Topic :: Software Development :: Debuggers'
20 27 LOAD_CONST 'Topic :: Software Development :: Libraries :: Python Modules'
30 BUILD_LIST_6 None
33 STORE_NAME 'classifiers'
24 36 LOAD_CONST 'Rocky Bernstein'
39 STORE_NAME 'author'
25 42 LOAD_CONST 'rb@dustyfeet.com'
45 STORE_NAME 'author_email'
26 48 LOAD_CONST None
51 STORE_NAME 'ftp_url'
28 54 LOAD_CONST 'python-debugger@googlegroups.com'
57 STORE_NAME 'mailing_list'
29 60 LOAD_CONST 'uncompyle6'
63 STORE_NAME 'modname'
30 66 LOAD_CONST 'uncompyle6'
69 LOAD_CONST 'uncompyle6.opcodes'
72 BUILD_LIST_2 None
75 STORE_NAME 'packages'
31 78 LOAD_CONST None
81 STORE_NAME 'py_modules'
32 84 LOAD_CONST 'Python byte-code disassembler and source-code converter'
87 STORE_NAME 'short_desc'
33 90 LOAD_CONST 'bin/uncompyle6'
93 LOAD_CONST 'bin/pydisassemble'
96 BUILD_LIST_2 None
99 STORE_NAME 'scripts'
35 102 LOAD_CONST -1
105 LOAD_CONST None
108 IMPORT_NAME 'os.path'
111 STORE_NAME 'os'
38 114 LOAD_CONST '<code_object get_srcdir>'
117 MAKE_FUNCTION_0 None
120 STORE_NAME 'get_srcdir'
43 123 BUILD_MAP None
126 STORE_NAME 'ns'
44 129 LOAD_CONST '2.0'
132 STORE_NAME 'version'
45 135 LOAD_CONST 'https://github.com/rocky/python-uncompyle6/'
138 STORE_NAME 'web'
48 141 LOAD_NAME 'True'
144 STORE_NAME 'zip_safe'
51 147 LOAD_CONST '<code_object read>'
150 MAKE_FUNCTION_0 None
153 STORE_NAME 'read'
54 156 LOAD_NAME 'read'
159 LOAD_CONST 'README.rst'
162 CALL_FUNCTION_1 None
165 LOAD_CONST '\n'
168 BINARY_ADD None
169 STORE_NAME 'long_description'
172 LOAD_CONST None
175 RETURN_VALUE None

75
pytest/testdata/test_import_25.right vendored Normal file
View File

@ -0,0 +1,75 @@
# Python 2.5
# Embedded file name: test_import.py
9 0 LOAD_CONST '\ntest_import.py -- source test pattern for import statements\n\nThis source is part of the decompyle test suite.\n\ndecompyle is a Python byte-code decompiler\nSee http://www.goebel-consult.de/decompyle/ for download and\nfor further information\n'
3 STORE_NAME '__doc__'
11 6 LOAD_CONST -1
9 LOAD_CONST None
12 IMPORT_NAME 'sys'
15 STORE_NAME 'sys'
12 18 LOAD_CONST -1
21 LOAD_CONST None
24 IMPORT_NAME 'os'
27 STORE_NAME 'os'
30 LOAD_CONST -1
33 LOAD_CONST None
36 IMPORT_NAME_CONT 'sys'
39 STORE_NAME 'sys'
42 LOAD_CONST -1
45 LOAD_CONST None
48 IMPORT_NAME_CONT 'BaseHTTPServer'
51 STORE_NAME 'BaseHTTPServer'
14 54 LOAD_CONST -1
57 LOAD_CONST None
60 IMPORT_NAME 'test.test_MimeWriter'
63 STORE_NAME 'test'
16 66 LOAD_CONST -1
69 LOAD_CONST ('Message',)
72 IMPORT_NAME 'rfc822'
75 IMPORT_FROM 'Message'
78 STORE_NAME 'Message'
81 POP_TOP None
17 82 LOAD_CONST -1
85 LOAD_CONST ('Message', 'decode', 'choose_boundary')
88 IMPORT_NAME 'mimetools'
91 IMPORT_FROM 'Message'
94 STORE_NAME 'Message'
97 IMPORT_FROM 'decode'
100 STORE_NAME 'decode'
103 IMPORT_FROM 'choose_boundary'
106 STORE_NAME 'choose_boundary'
109 POP_TOP None
18 110 LOAD_CONST -1
113 LOAD_CONST ('*',)
116 IMPORT_NAME 'os'
119 IMPORT_STAR None
20 120 SETUP_LOOP '162'
123 LOAD_NAME 'globals'
126 CALL_FUNCTION_0 None
129 LOAD_ATTR 'items'
132 CALL_FUNCTION_0 None
135 GET_ITER None
136 FOR_ITER '161'
139 UNPACK_SEQUENCE_2 None
142 STORE_NAME 'k'
145 STORE_NAME 'v'
21 148 LOAD_NAME 'k'
151 UNARY_CONVERT None
152 PRINT_ITEM None
153 LOAD_NAME 'v'
156 PRINT_ITEM_CONT None
157 PRINT_NEWLINE_CONT None
158 JUMP_BACK '136'
161 POP_BLOCK None
162_0 COME_FROM '120'
162 LOAD_CONST None
165 RETURN_VALUE None

1
test-requirements.txt Normal file
View File

@ -0,0 +1 @@
pytest

View File

@ -38,4 +38,4 @@ clean-unverified:
#: Clean temporary compile/decompile/verify direcotries in /tmp
clean-py-dis:
rm -fvr /tmp/py-dis-* || true
rm -fr /tmp/py-dis-* || true

View File

@ -138,7 +138,7 @@ def do_tests(src_dir, obj_patterns, target_dir, opts):
if opts['start_with']:
try:
start_with = files.index(start_with)
start_with = files.index(opts['start_with'])
files = files[start_with:]
print('>>> starting with file', files[0])
except ValueError:
@ -203,7 +203,7 @@ if __name__ == '__main__':
print("Can't find directory %s. Skipping" % src_dir,
file=sys.stderr)
continue
if last_compile_version and last_compile_version != compile_version:
if last_compile_version and last_compile_version != compiled_version:
print("Warning: mixed python version decompylation")
else:
last_compile_version = compiled_version

View File

@ -62,16 +62,16 @@ def load_code_internal(fp, magic_int):
# a range here.
if 3000 < magic_int < 20121:
fp.read(4)
co_code = load_code(fp, magic_int)
co_consts = load_code(fp, magic_int)
co_names = load_code(fp, magic_int)
co_varnames = load_code(fp, magic_int)
co_freevars = load_code(fp, magic_int)
co_cellvars = load_code(fp, magic_int)
co_filename = load_code(fp, magic_int)
co_name = load_code(fp, magic_int)
co_code = load_code_internal(fp, magic_int)
co_consts = load_code_internal(fp, magic_int)
co_names = load_code_internal(fp, magic_int)
co_varnames = load_code_internal(fp, magic_int)
co_freevars = load_code_internal(fp, magic_int)
co_cellvars = load_code_internal(fp, magic_int)
co_filename = load_code_internal(fp, magic_int)
co_name = load_code_internal(fp, magic_int)
co_firstlineno = unpack('i', fp.read(4))[0]
co_lnotab = load_code(fp, magic_int)
co_lnotab = load_code_internal(fp, magic_int)
# The Python3 code object is different than Python2's which
# we are reading if we get here.
# Also various parameters which were strings are now
@ -159,7 +159,7 @@ def load_code_internal(fp, magic_int):
tuplesize = unpack('i', fp.read(4))[0]
ret = tuple()
while tuplesize > 0:
ret += load_code(fp, magic_int),
ret += load_code_internal(fp, magic_int),
tuplesize -= 1
return ret
elif marshalType == '[':

View File

@ -181,7 +181,7 @@ def cmp_code_objects(version, code_obj1, code_obj2, name=''):
elif version == 3.4:
import uncompyle6.scanners.scanner34 as scan
scanner = scan.Scanner34()
scanner.setShowAsm( showasm=0 )
scanner.setShowAsm( showasm=False )
global JUMP_OPs
JUMP_OPs = scan.JUMP_OPs + ['JUMP_BACK']