diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 3c4f056..66a8c85 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -160,6 +160,11 @@ jobs: python3.{5..11} \ python3.10-full python3.10-dev + python3.10 -m venv .venv + source .venv/bin/activate + pip install --upgrade pip + pip install -r test/requirements.txt + - name: Compile Austin run: | autoreconf --install @@ -168,14 +173,10 @@ jobs: - name: Run tests run: | + echo "core.%p" | sudo tee /proc/sys/kernel/core_pattern ulimit -c unlimited - python3.10 -m venv .venv - source .venv/bin/activate - pip install --upgrade pip - pip install -r test/requirements.txt .venv/bin/pytest --pastebin=failed -sr fE -n auto || true sudo -E env PATH="$PATH" .venv/bin/pytest --pastebin=failed -sr fE -n auto || true - deactivate - name: Generate Cobertura report run: gcovr --xml ./cobertura.xml -r src/ diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index bc19181..84087d5 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -96,8 +96,7 @@ jobs: sudo apt-get update sudo apt-get -y install \ valgrind \ - gdb \ - systemd-coredump + gdb - name: Install Python uses: actions/setup-python@v4 @@ -114,37 +113,61 @@ jobs: source .venv/bin/activate pip install --upgrade pip pip install -r test/requirements.txt + + - name: Set core dump file pattern + run: | + echo "core.%p" | sudo tee /proc/sys/kernel/core_pattern + ulimit -c unlimited + python3.10 -c "import ctypes;ctypes.string_at(0)" || true + ls core.* + rm core.* - name: Run unit tests - run: .venv/bin/pytest -sv test/cunit + run: | + ulimit -c unlimited + .venv/bin/pytest -sv test/cunit - name: Run functional Austin tests (with sudo) - run: sudo -E env PATH="$PATH" .venv/bin/pytest --pastebin=failed -svr a test/functional -n auto -k "not austinp" + run: | + ulimit -c unlimited + sudo -E env PATH="$PATH" .venv/bin/pytest --pastebin=failed -svr a test/functional -n auto -k "not austinp" if: always() - name: Run functional Austin tests (without sudo) - run: .venv/bin/pytest --pastebin=failed -svr a test/functional -n auto -k "not austinp" + run: | + ulimit -c unlimited + .venv/bin/pytest --pastebin=failed -svr a test/functional -n auto -k "not austinp" if: always() - name: Run functional austinp tests (with sudo) - run: sudo -E env PATH="$PATH" .venv/bin/pytest --pastebin=failed -svr a test/functional -n auto -k "austinp" + run: | + ulimit -c unlimited + sudo -E env PATH="$PATH" .venv/bin/pytest --pastebin=failed -svr a test/functional -n auto -k "austinp" if: always() - name: Run functional austinp tests (without sudo) - run: .venv/bin/pytest --pastebin=failed -svr a test/functional -n auto -k "austinp" + run: | + ulimit -c unlimited + .venv/bin/pytest --pastebin=failed -svr a test/functional -n auto -k "austinp" if: always() - name: Run integrity tests (with sudo) - run: sudo -E env PATH="$PATH" .venv/bin/pytest --pastebin=failed -svr a test/integrity + run: | + ulimit -c unlimited + sudo -E env PATH="$PATH" .venv/bin/pytest --pastebin=failed -svr a test/integrity if: always() - name: Run integrity tests (without sudo) - run: .venv/bin/pytest --pastebin=failed -svr a test/integrity + run: | + ulimit -c unlimited + .venv/bin/pytest --pastebin=failed -svr a test/integrity if: always() - name: Run support tests - run: .venv/bin/pytest -sv test/support + run: | + ulimit -c unlimited + .venv/bin/pytest -sv test/support if: always() wheels-linux: @@ -484,6 +507,7 @@ jobs: - name: Run data validation run: | ulimit -c unlimited + echo "core.%p" | sudo tee /proc/sys/kernel/core_pattern source .venv/bin/activate python scripts/validation.py --ignore-errors diff --git a/test/cunit/conftest.py b/test/cunit/conftest.py index 7e7d02d..46e6cbc 100644 --- a/test/cunit/conftest.py +++ b/test/cunit/conftest.py @@ -3,9 +3,9 @@ import typing as t from pathlib import Path from subprocess import PIPE -from subprocess import run from test.cunit import SRC from test.utils import bt +from test.utils import run from types import FunctionType import pytest @@ -55,7 +55,9 @@ def _(*_, **__): if result.returncode == -11: binary_name = Path(module).stem.replace("test_", "") - raise SegmentationFault(bt((SRC / binary_name).with_suffix(".so"))) + raise SegmentationFault( + bt((SRC / binary_name).with_suffix(".so"), result.pid) + ) raise CUnitTestFailure( f"\n{result.stdout.decode()}\n" diff --git a/test/utils.py b/test/utils.py index 9388435..195d4fa 100644 --- a/test/utils.py +++ b/test/utils.py @@ -110,9 +110,10 @@ def apport_unpack(report: Path, target_dir: Path): ).decode() -def bt(binary: Path) -> str: - if Path("core").is_file(): - return gdb(["bt full", "q"], str(binary), "core") +def bt(binary: Path, pid: int) -> str: + core_file = f"core.{pid}" + if Path(core_file).is_file(): + return gdb(["bt full", "q"], str(binary), core_file) # On Ubuntu, apport puts crashes in /var/crash crash_dir = Path("/var/crash") @@ -155,7 +156,8 @@ def collect_logs(variant: str, pid: int) -> List[str]: EXEEXT = ".exe" if platform.system() == "Windows" else "" -# Taken from the subprocess module +# Taken from the subprocess module. We make our own version that can also +# propagate the PID. def run( *popenargs, input=None, capture_output=False, timeout=None, check=False, **kwargs ): @@ -248,7 +250,7 @@ def __call__( raise if result.returncode in (-11, 139): # SIGSEGV - print(bt(self.path)) + print(bt(self.path, result.pid)) if mojo and not ({"-o", "-w", "--output", "--where"} & set(args)): # We produce MOJO binary data only if we are not writing to file