Skip to main content

No project description provided

Project description

Valgrind testing helper for pytest

This is much of a hack, but it can help you test a C extension module with valgrind. In particular if you are interested in checking for memory leaks.

When might I want to use this?:

  • You have a non-trivial C-extention and should really check it with valgrind.
  • You have a non-trivial C-extention module that does memory allocations and might leak memory.
  • You are interested not only in reference count leaks (for which other tools are probably be better). Or hope valgrind can give you some information on the leak.
  • You are looking for a simple way to get an overview over which tests cause errors detected by valgrind.

Why not just run the test in valgrind?:

  • Memory leak checking on valgrind is normally done only at exit. This will run a leak check after every test allowing you to narrow down where a leak occurs without additional effort.
  • This reports which test fails valgrind and the exact error associated with it. So it may be a bit more convenient

Why should I not use this?:

  • It is a a hack with you passing in the valgrind log file to pytest (if you want a helpful error summary).
  • The error reporting probably has some quirks and hides normal errors.
  • You want to inspect the full valgrind information and this way you are more likely to miss errors that only show up between tests (e.g. module import/teardown).

Testing for memory leaks after every test seems to be a bit flaky and increadibly slow. Also I do not know the details well enough to be sure that there are no other issues.

How to use the plugin

To use this module, you need to first install it using pip install . or pip install . --user. It currently only supports Python 3 and requires a C compiler as well as typical valgrind installation (valgrind/valgrind.h).

To then use it, use a normal pytest invocation giving the --valgrind option, however, you also need to run everything in valgrind itself.

The easiest way to do this is (requires python 3.6 I believe) is the sample invocation below (or similar pytest command). There is an example test in the example subfolder, which includes a similar invocation as documentation:

PYTHONMALLOC=malloc valgrind --show-leak-kinds=definite --log-file=/tmp/valgrind-output \
    python -m pytest -vv --valgrind --valgrind-log=/tmp/valgrind-output

Note that the PYTHONMALLOC=malloc command is crucial (and only works on newer python versions). Alternatively, a python debug build with the --valgrind option can be used. If neither is used, the output will be useless due to false positives by python (suppression could be added, but are less reliable). It is the responsibility of the caller to pass the correct valgrind arguments. you must pass --show-leak-kinds=definite and should use --log-file as above!

You should provide a log file in this invocation and pass it into pytest. Otherwise pytest-valgrind will not be able to provide a nice error report. Any normal failures will be skipped. For example in numpy, typically the floating point errors fail to report, which causes test failures.

The first version effectively ignored the --errors-for-leak-kinds valgrind option. In the current version --errors-for-leak-kinds=definite will work (and ignore "indirect" leaks).

Any valgrind error or memory leak occuring during the test will lead to the test being recorded as FAILURE. You will have to search the valgrind log file for the specific error.

As a further example, one may run an individual NumPy test file with the following commend (some of these options are not necessary):

PYTHONMALLOC=malloc valgrind --show-leak-kinds=definite --log-file=/tmp/valgrind-output python runtests.py -g -t numpy/core/tests/test_dtype.py -- -vv --valgrind --valgrind-log=/tmp/valgrind-output --continue-on-collection-errors

Options

  • --valgrind enables the plugin.
  • --valgrind-log=<log_file> Should be given. This is the same file passed to valgrind as --log-file=<log_file>. If not given, the error reports do not include any valgrind output.
  • --no-memcheck will disable checking for memory leaks after every function call (or actually at all). If you are sure there are no leaks, this might speed up execution.
  • --memcheck-before-func will run a memory check before each test call. This should not be necessary, so maybe should be removed again.

Reported failures and marking tests

This plugin ignores all normal exceptions and replaces them with KNOWNFAIL/xfail right now. It will report failures only for errors/leaks reported by valgrind. It seems that known failures that produce valgrind errors are also reported as known failure.

You can mark tests with pytest.mark.valgrind_known_leak(reason="?!") or pytest.mark.valgrind_known_error(reason="Oooops") (or both) to make the test result an xfail specifically for this plugin and specific to either leaks or other errors reported by valgrind.

Not all errors are necessarily due to your own code, sometimes false positives can be reported from known good functions. For example strcmp can do this if the valgrind suppressions are not up to date. Such failures should be fixed with a valgrind suppression file and not using pytest markers.

Notes, Caveats, and Solutions

Please check the valgrind documentation if you wish to modify your output. Valgrind starts hiding duplicate errors, so if is highlighted as an error but there is no error in the valgrind output, it might be that the error is a repetition of a previous one and thus hidden.

Furter notes:

  • If valgrind has bad interaction causing errors during test gathering this may hang pytest. In that case, you may use --continue-on-collection-errors as a quick workaround.
  • CPython always causes "possible" leaks to implement the garbage collector/circular reference counting. Due to this, we perform a sanity check: if obj = object() reports a "leak" valgrinds --errors-for-leak-kinds is ignored (the default includes "possible"). --errors-for-leak-kinds=definite will not be ignored, and possibly there are other ways to make the above check pass.
  • Testing leaks this often slows down testing even more compared to a simple run with valgrind.
  • It does not seem too elegant, since a valgrind output file is passed to the pytest as an argument (I doubt there is a solution for this).
  • If you do not have useful function names in your output maybe you did not build a debug build?
  • Valgrind has lots of options, please check them!
  • No, I did not check this on different systems/compilers. So if it breaks, you may have to modify the code or setup.py.
  • By default checks for leaks once before the first test and once after every test. This means:
    • Leaks occuring before any test is run are not reported!
    • Leaks should not really occur between tests, but if they do they are reported for the next test.
  • If your program has caches (e.g. numpy has a small array cache) this might cause leaks to behave non-deterministic, or the object that is being leaked not correspond to the actual leaked object (since the allocation occured originally for another object).
  • The tool runs the garbage collector repeatedly after every single test, this may be very slow.
  • I do not know pytest plugins well (and the documentation is not super easy at the time), so a lot of how the pytest things are done can and should probably be much done better.

I do not like this or have a better version!

Sure, feel free to create pull requests, if you have something better I will be happy to remove/rename this.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pytest-valgrind-0.2.0.tar.gz (10.9 kB view details)

Uploaded Source

Built Distributions

pytest_valgrind-0.2.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl (25.9 kB view details)

Uploaded CPython 3.8 manylinux: glibc 2.17+ x86-64 manylinux: glibc 2.5+ x86-64

pytest_valgrind-0.2.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl (26.9 kB view details)

Uploaded CPython 3.7m manylinux: glibc 2.17+ x86-64 manylinux: glibc 2.5+ x86-64

File details

Details for the file pytest-valgrind-0.2.0.tar.gz.

File metadata

  • Download URL: pytest-valgrind-0.2.0.tar.gz
  • Upload date:
  • Size: 10.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.1.1 pkginfo/1.5.0.1 requests/2.25.1 setuptools/47.3.1 requests-toolbelt/0.9.1 tqdm/4.43.0 CPython/3.7.6

File hashes

Hashes for pytest-valgrind-0.2.0.tar.gz
Algorithm Hash digest
SHA256 5e74de60d1c9e5c5e5bcdcd9d5b000467a480ff1ac5365582a2e61a52f056517
MD5 de7954db033444acdfea20eb83bfc5c4
BLAKE2b-256 8d343811e7ca6cd805423360a6a81a15dd1ad8fec7aba22273faac3983c2618c

See more details on using hashes here.

File details

Details for the file pytest_valgrind-0.2.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for pytest_valgrind-0.2.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 59c2ea9437e341623bd623117a01b4eb18adc82078d267c55ca4dfa742bd64c4
MD5 528a7cff02ab22f5033a56d0c7a9d90d
BLAKE2b-256 fafe81dea7c2497ecc736b64e1a6ac5de43b314a3165479cda87e320cccc9d25

See more details on using hashes here.

File details

Details for the file pytest_valgrind-0.2.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for pytest_valgrind-0.2.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 fb9c172858d97cbcb8e4409345a9064a664c11811edea6ba4f6c9ad8109747f9
MD5 3e6af1bb68dcade8d599f6c1defb6c74
BLAKE2b-256 ffd42539af41ff5c0f1e78e20906b770c9c38338375e62f0bdb7c565ea3aef69

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page