Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Automated cross-version testing #159

Open
wants to merge 19 commits into
base: master
Choose a base branch
from

Conversation

2elli
Copy link
Collaborator

@2elli 2elli commented Jan 21, 2025

I wrote this automated cross version tests for checking xdis bytecode accuracy against a dis bytecode using pyenv, pyenv-virtualenv, tox, and pytest. I this this will be very useful for testing accuracy against permutations of all the modern python versions being used for xdis so we can catch some of the cases that we ran into issues with last year, for example, the line table inaccuracies in 3.10 when running xdis from a different version.

There is more work needed to have this be useful but I wanted to create this PR for discussion.

Test Overview

To test cross version accuracy of xdis against dis, I wrote a simple way to "serialize" a bytecode into text. This serialization works the same on an xdis and dis bytecode.

  1. tox_prepare.ini, for each test env,
    • compile test sources ./templates/source/*.py to ./templates/compiled/<version>/*.pyc
    • serialize the compiled pyc with dis to ./templates/serialized/<version>/*.txt.
  2. tox.ini for each test env, for each compiled version,
    • take a pair of corresponding bytecode ./templates/compiled/<version>/<file>.pyc and its dis serialized txt file ./templates/serialized/<version>/<file>.txt
    • Load the pyc into an xdis bytecode and serialize it
    • Compare the xdis serialized bytecode to the dis serialized bytecode created with the same bytecode.

TO-DO

  • Find a better solution than tox-pyenv-redux for venv discovery.
  • Display diffs in an easier to understand way. Currently it's still a very manual process to go through test results to find and confirm differences between dis and xdis.

@2elli
Copy link
Collaborator Author

2elli commented Jan 21, 2025

@rocky responding to your comment in the other PR I made;

  • I have updated the Makefile to be compatible with remake.
  • I have not found any inaccuracies with these tests yet, mostly due to a majority of the differences between xdis and dis are that xdis includes some additional info that dis does not. For example: '155 FORMAT_VALUE : 0 (None, False)' != '155 FORMAT_VALUE : 0 0' where the left is from xdis and dis is on the right.

I will need to work on deciding if its best to "massage" an xdis bytecode to be more like the dis bytecode, or just loosen tests more (I already have excluded argrepr from these tests for example).

@rocky
Copy link
Owner

rocky commented Jan 21, 2025

@2elli Good idea and I am glad to see this done.

When I will get a chance I will try this out!

I have not found any inaccuracies with these tests yet, mostly due to a majority of the differences between xdis and dis are that xdis includes some additional info that dis does not. For example: '155 FORMAT_VALUE : 0 (None, False)' != '155 FORMAT_VALUE : 0 0' where the left is from xdis and dis is on the right.

Farily recently, xdis introduced output formats, e.g., "extended", "extended-bytes", "bytes", or "classic". The latter, "classic" is intended to match the standard dis module output.

But beware, because dis output can change from one Python version to the next. So classic may need to be sensitive to the bytecode version.

@2elli
Copy link
Collaborator Author

2elli commented Jan 21, 2025

Perfect, thanks for the reminders! I'll see if classic mode will work better for this.

The different versions changing output for dis is important to consider so thank you for bringing that up. One of the next steps I think would be best is to make some tests version specific. For example I would like to include 'co_lnotab' as part of the tests but that is specific for some versions of dis, even if present in xdis.

Lastly, let me know if running the tests with pyenv-virtualenv gives you any issues. I wanted tox to be able to use pyenv-virtualenv to discover environments so I used https://github.com/un-def/tox-pyenv-redux to handle that, but I believe there may be a better solution.

Thanks :)

@rocky
Copy link
Owner

rocky commented Jan 23, 2025

I tried running this morning after pip installing tox and running make prepare. When I get run remake -x compile, here is what I see:

remake -x compile
Reading makefiles...
Updating makefiles...
Updating goal targets...
 File 'compile' does not exist.
Must remake target 'compile'.
Makefile:32: target 'compile' does not exist
##>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
tox -c ./tox_prepare.ini
##<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
ROOT: will run in automatically provisioned tox, host /home/rocky/.pyenv/versions/3.12.6/bin/python3.12 is missing [requires (has)]: tox-pyenv-redux
ROOT: provision> .tox/.tox/bin/python -m tox -c ./tox_prepare.ini
3.9: <class 'pyenv_inspect.exceptions.UnsupportedImplementation'>: only CPython is currently supported
3.9: <class 'pyenv_inspect.exceptions.UnsupportedImplementation'>: only CPython is currently supported
3.9: <class 'pyenv_inspect.exceptions.UnsupportedImplementation'>: only CPython is currently supported
3.9: <class 'pyenv_inspect.exceptions.UnsupportedImplementation'>: only CPython is currently supported
3.9: <class 'pyenv_inspect.exceptions.UnsupportedImplementation'>: only CPython is currently supported
3.9: <class 'pyenv_inspect.exceptions.UnsupportedImplementation'>: only CPython is currently supported
3.9: <class 'pyenv_inspect.exceptions.UnsupportedImplementation'>: only CPython is currently supported
3.9: <class 'pyenv_inspect.exceptions.UnsupportedImplementation'>: only CPython is currently supported
3.9: <class 'pyenv_inspect.exceptions.UnsupportedImplementation'>: only CPython is currently supported
3.9: <class 'pyenv_inspect.exceptions.UnsupportedImplementation'>: only CPython is currently supported
3.9: commands[0]> python ./prepare_templates.py
0 files compiled and serialized
3.9: OK ✔ in 0.07 seconds
3.10: <class 'pyenv_inspect.exceptions.UnsupportedImplementation'>: only CPython is currently supported
3.10: <class 'pyenv_inspect.exceptions.UnsupportedImplementation'>: only CPython is currently supported
3.10: <class 'pyenv_inspect.exceptions.UnsupportedImplementation'>: only CPython is currently supported
3.10: <class 'pyenv_inspect.exceptions.UnsupportedImplementation'>: only CPython is currently supported
3.10: <class 'pyenv_inspect.exceptions.UnsupportedImplementation'>: only CPython is currently supported
3.10: <class 'pyenv_inspect.exceptions.UnsupportedImplementation'>: only CPython is currently supported
3.10: <class 'pyenv_inspect.exceptions.UnsupportedImplementation'>: only CPython is currently supported
3.10: <class 'pyenv_inspect.exceptions.UnsupportedImplementation'>: only CPython is currently supported
3.10: <class 'pyenv_inspect.exceptions.UnsupportedImplementation'>: only CPython is currently supported
3.10: <class 'pyenv_inspect.exceptions.UnsupportedImplementation'>: only CPython is currently supported
3.10: commands[0]> python ./prepare_templates.py
0 files compiled and serialized
3.10: OK ✔ in 0.06 seconds
3.11: <class 'pyenv_inspect.exceptions.UnsupportedImplementation'>: only CPython is currently supported
3.11: <class 'pyenv_inspect.exceptions.UnsupportedImplementation'>: only CPython is currently supported
3.11: <class 'pyenv_inspect.exceptions.UnsupportedImplementation'>: only CPython is currently supported
3.11: <class 'pyenv_inspect.exceptions.UnsupportedImplementation'>: only CPython is currently supported
3.11: <class 'pyenv_inspect.exceptions.UnsupportedImplementation'>: only CPython is currently supported
3.11: <class 'pyenv_inspect.exceptions.UnsupportedImplementation'>: only CPython is currently supported
3.11: <class 'pyenv_inspect.exceptions.UnsupportedImplementation'>: only CPython is currently supported
3.11: <class 'pyenv_inspect.exceptions.UnsupportedImplementation'>: only CPython is currently supported
3.11: <class 'pyenv_inspect.exceptions.UnsupportedImplementation'>: only CPython is currently supported
3.11: <class 'pyenv_inspect.exceptions.UnsupportedImplementation'>: only CPython is currently supported
3.11: commands[0]> python ./prepare_templates.py
0 files compiled and serialized
3.11: OK ✔ in 0.05 seconds
3.12: <class 'pyenv_inspect.exceptions.UnsupportedImplementation'>: only CPython is currently supported
3.12: <class 'pyenv_inspect.exceptions.UnsupportedImplementation'>: only CPython is currently supported
3.12: <class 'pyenv_inspect.exceptions.UnsupportedImplementation'>: only CPython is currently supported
3.12: <class 'pyenv_inspect.exceptions.UnsupportedImplementation'>: only CPython is currently supported
3.12: <class 'pyenv_inspect.exceptions.UnsupportedImplementation'>: only CPython is currently supported
3.12: <class 'pyenv_inspect.exceptions.UnsupportedImplementation'>: only CPython is currently supported
3.12: <class 'pyenv_inspect.exceptions.UnsupportedImplementation'>: only CPython is currently supported
3.12: <class 'pyenv_inspect.exceptions.UnsupportedImplementation'>: only CPython is currently supported
3.12: <class 'pyenv_inspect.exceptions.UnsupportedImplementation'>: only CPython is currently supported
3.12: <class 'pyenv_inspect.exceptions.UnsupportedImplementation'>: only CPython is currently supported
3.12: commands[0]> python ./prepare_templates.py
0 files compiled and serialized
3.12: OK ✔ in 0.06 seconds
3.13: <class 'pyenv_inspect.exceptions.UnsupportedImplementation'>: only CPython is currently supported
3.13: <class 'pyenv_inspect.exceptions.UnsupportedImplementation'>: only CPython is currently supported
3.13: <class 'pyenv_inspect.exceptions.UnsupportedImplementation'>: only CPython is currently supported
3.13: <class 'pyenv_inspect.exceptions.UnsupportedImplementation'>: only CPython is currently supported
3.13: <class 'pyenv_inspect.exceptions.UnsupportedImplementation'>: only CPython is currently supported
3.13: <class 'pyenv_inspect.exceptions.UnsupportedImplementation'>: only CPython is currently supported
3.13: <class 'pyenv_inspect.exceptions.UnsupportedImplementation'>: only CPython is currently supported
3.13: <class 'pyenv_inspect.exceptions.UnsupportedImplementation'>: only CPython is currently supported
3.13: <class 'pyenv_inspect.exceptions.UnsupportedImplementation'>: only CPython is currently supported
3.13: <class 'pyenv_inspect.exceptions.UnsupportedImplementation'>: only CPython is currently supported
3.13: commands[0]> python ./prepare_templates.py
0 files compiled and serialized
  3.9: OK (0.07=setup[0.02]+cmd[0.05] seconds)
  3.10: OK (0.06=setup[0.00]+cmd[0.05] seconds)
  3.11: OK (0.05=setup[0.00]+cmd[0.05] seconds)
  3.12: OK (0.06=setup[0.01]+cmd[0.05] seconds)
  3.13: OK (0.06=setup[0.00]+cmd[0.05] seconds)
  congratulations :) (0.32 seconds)
Successfully remade target file 'compile'.

What I am supposed to see? What is going wrong?

@2elli
Copy link
Collaborator Author

2elli commented Jan 23, 2025

@rocky It seems everything ran correctly here. I think my wording and the way these tests are setup may be a bit confusing, sorry. I may refactor to something more clear like "prepare_tests".

The compile target runs tox -c tox_compile.ini, which is a dependency for running the test target. This tox config compiles then serializes each source file in ./templates/source with dis. When the test target is ran, we serialize the compiled pyc's with xdis and compare it to the text file containing the corresponding pyc serialized with dis.

The readability of tests right now is definitely hurting due to tox-pyenv-redux handling discovery of pyenv environments. Ive updated the TODO in this PR to include figuring out a better way to handle that.

@rocky
Copy link
Owner

rocky commented Jan 24, 2025

Ok. Thanks for the information.

@2elli
Copy link
Collaborator Author

2elli commented Jan 31, 2025

@rocky I think these tests should be good for development use now. With these tests, I already have been finding some inaccuracies.

Most are inconsequential differences between argvals, but I found incorrect line numbers in 3.10 again. @jdw170000 found that the python provided in https://github.com/python/cpython/blob/3.10/Objects/lnotab_notes.txt is actually incorrect when compared with the C. @jdw170000 and I worked on a fix for xdis that I will open a new PR for.

@2elli 2elli marked this pull request as ready for review January 31, 2025 00:21
@rocky
Copy link
Owner

rocky commented Jan 31, 2025

@rocky I think these tests should be good for development use now. With these tests, I already have been finding some inaccuracies.

Many thanks. I will look at this when I get a chance.

Most are inconsequential differences between argvals, but I found incorrect line numbers in 3.10 again. @jdw170000 found that the python provided in https://github.com/python/cpython/blob/3.10/Objects/lnotab_notes.txt is actually incorrect when compared with the C. @jdw170000 and I worked on a fix for xdis that I will open a new PR for.

Ok. Good news. Keep up the good work!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants