From 746a9273e6ebf38d1a6855fb776dc6891ff0cabd Mon Sep 17 00:00:00 2001 From: "Jan C. Brammer" Date: Thu, 17 Oct 2024 11:04:07 +0000 Subject: [PATCH] Add multithreading test --- .github/workflows/ci.yml | 4 ++ INCHI-1-TEST/tests/test_library/README.md | 8 ++++ .../tests/test_library/test_multithreading.py | 48 +++++++++++++++++++ 3 files changed, 60 insertions(+) create mode 100644 INCHI-1-TEST/tests/test_library/test_multithreading.py diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index df0b209..ea534ba 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -27,6 +27,8 @@ jobs: run: pytest INCHI-1-TEST/tests/test_executable - uses: ./.github/actions/compile_inchi_lib + - name: Run multithreading test + run: python INCHI-1-TEST/tests/test_library/test_multithreading.py - uses: ./.github/actions/regression_tests with: artifact-name: regression-test-results_glibc_gcc @@ -70,6 +72,8 @@ jobs: run: pytest INCHI-1-TEST/tests/test_executable - uses: ./.github/actions/compile_inchi_lib + - name: Run multithreading test + run: python INCHI-1-TEST/tests/test_library/test_multithreading.py - uses: ./.github/actions/regression_tests with: artifact-name: regression-test-results_musl_gcc diff --git a/INCHI-1-TEST/tests/test_library/README.md b/INCHI-1-TEST/tests/test_library/README.md index 12f5803..afbf1ce 100644 --- a/INCHI-1-TEST/tests/test_library/README.md +++ b/INCHI-1-TEST/tests/test_library/README.md @@ -49,6 +49,14 @@ python -m INCHI-1-TEST.tests.test_library.data.pubchem.validate Note that validation isn't available for `compound3d` (PubChem doesn't provide file hashes). +## Multithreading tests + +Test the thread safety of the InChI library by running + +`python INCHI-1-TEST/tests/test_library/test_multithreading.py` + +The script triggers a segfault should the thread safety of the library be compromised. + ## Invariance tests Invariance tests are meant to detect problems with InChI's canonicalization algorithm. diff --git a/INCHI-1-TEST/tests/test_library/test_multithreading.py b/INCHI-1-TEST/tests/test_library/test_multithreading.py new file mode 100644 index 0000000..6a3951c --- /dev/null +++ b/INCHI-1-TEST/tests/test_library/test_multithreading.py @@ -0,0 +1,48 @@ +""" +This script is meant to trigger segfaults. +Unix systems return exit code 139 when a process terminates due to a segfault. +139 = 128 + 11, +where 128+n means "Fatal error signal 'n'", see https://tldp.org/LDP/abs/html/exitcodes.html, +and 11 means "SIGSEGV", i.e., segfault, see wikipedia.org/wiki/Signal_(IPC)#POSIX_signals. +""" + +import threading +import ctypes +from pathlib import Path +from inchi_tests.inchi_api import make_inchi_from_molfile_text +from sdf_pipeline.utils import read_records_from_gzipped_sdf + + +SDF_PATH = Path("INCHI-1-TEST/tests/test_library/data/ci/inchi.sdf.gz") +INCHI_LIB_PATH = Path("INCHI-1-TEST/libs/libinchi.so.main") +# INCHI_LIB_PATH = Path("INCHI-1-TEST/libs/libinchi.so.v1.06") +INCHI_LIB = ctypes.CDLL(str(INCHI_LIB_PATH)) + + +class ConsumerThread(threading.Thread): + def __init__(self, inchi_lib, molfile): + super().__init__() + self.inchi_lib = inchi_lib + self.molfile = molfile + + def run(self): + (_, inchi, _, _, _) = make_inchi_from_molfile_text( + self.inchi_lib, + self.molfile, + "", + ) + print(inchi) + + +if __name__ == "__main__": + + threads = [ + ConsumerThread(INCHI_LIB, molfile) + for molfile in read_records_from_gzipped_sdf(SDF_PATH) + ] + + for thread in threads: + thread.start() + + for thread in threads: + thread.join(timeout=5)