Skip to content
x0ret edited this page May 12, 2019 · 8 revisions

One of the ways that this decompiler is different from most of the others I've seen is in its extensive testing.

After a lot of experimentation, the most effective way to do this is to write a little Python test program for a particular feature you want to test decomplation on. For example, suppose I want to see if the Python 3 format strings of the form f'{xxx}' and f'{xxx!s}' are handled correctly.

First I'll write come code using asserts. Like this:

abc  = 'def'
assert 'defdef' == f'{abc}{abc!s}'

Above it is pretty easy to figure out the assert statement. But in many cases it is too difficult for me to do, so I will let Python do the work for me instead:

abc  = 'def'
print(f'{abc}{abc!s}')

After running this, Python will tell me what the right result is.

Next put the test somwhere under test/simple_source. Let's say you are using Python 3.6 and this is a bug in version 3.6 or later. (Format specifiers were added around Python 3.6). Here, test/simple_source/bug36 might be a good directory to add this under.

The number at the front of the test-case names is just to influence where in the testing the test should be. Simple and fast tests start 01 and very complicated ones start with a high number like 10. That way when testing, we do the easy cases before the difficult one.

Next cd test; ./add-test.py --run simple-source/bug36/01_fstring.py This will compile the test and add it to the corresponding bytecode_N.N_run directory. Here N.N would be 3.6. Add the test into git using git add simple_source/bug36/01_fstring.py and git add -f tests/bytecode-3.6-run/01_fstring.py.

Finally to test run make check-bytecode-3.6.

Here is what this does. Whenever you run make check and you are running a Python 3.6 interpreter,

  • the bytecode in test/bytecode_3.6_run is decompiled
  • the decompiled bytecode is run to make sure not only is the program syntactically correct, but that the code work in the ways that the asserts check.