From 09123320bbf9dab9eda094950dfe10866d5b5c23 Mon Sep 17 00:00:00 2001 From: ChuckBuilds Date: Fri, 21 Aug 2026 14:04:08 -0400 Subject: [PATCH] test(install): stop assuming pytest's tmp_path is on disk test_returns_nothing_when_tmpdir_is_already_disk_backed asserted that lm_disk_backed_tmpdir prints nothing when TMPDIR is already disk-backed, and used pytest's tmp_path as the "disk-backed" directory: # tmp_path is on the regular filesystem, so the default must be kept. assert call("lm_disk_backed_tmpdir", env={"TMPDIR": str(tmp_path)}) == "" That premise is false on the platform the helper was written for. Debian 13 mounts /tmp as tmpfs -- which is the entire reason lm_disk_backed_tmpdir exists -- and pytest puts tmp_path under /tmp. So on the target platform TMPDIR is memory-backed, the helper correctly answers /var/tmp, and the test fails: E AssertionError: assert '/var/tmp' == '' The helper is right; the test was wrong. Reproduced on a box where /tmp is tmpfs and / is ext4. The test now looks for a directory whose backing store is actually disk -- tmp_path, else a scratch dir under /var/tmp, else beside the library -- using the same findmnt lookup the helper itself uses, and skips only if no disk-backed directory exists anywhere. An earlier version of this fix skipped whenever tmp_path was tmpfs, which made it skip on every machine with a tmpfs /tmp; that is barely better than asserting the wrong thing, so it now searches instead of giving up. Verified: 31 passed, 0 skipped. Mutation-checked -- deleting the "is the current TMPDIR memory-backed?" guard from lm_disk_backed_tmpdir fails this test, so it still catches the regression it is there for. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01STMbQE4YctTacQXfbYqKuW --- test/test_install_lowmem.py | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/test/test_install_lowmem.py b/test/test_install_lowmem.py index 7143176a..7c9fbbc8 100644 --- a/test/test_install_lowmem.py +++ b/test/test_install_lowmem.py @@ -13,6 +13,7 @@ need root and mutate the system, so they are exercised manually instead. """ import subprocess +import tempfile from pathlib import Path import pytest @@ -31,6 +32,16 @@ def run_lib(snippet: str, env: dict | None = None) -> subprocess.CompletedProces ) +def _fstype_of(path: object) -> str: + """Filesystem type backing ``path``, via the same tool the helper uses.""" + result = subprocess.run( + ["findmnt", "-no", "FSTYPE", "--target", str(path)], + capture_output=True, text=True, + env={"PATH": "/usr/bin:/bin:/usr/sbin:/sbin"}, + ) + return result.stdout.strip() + + def call(fn: str, *args: object, env: dict | None = None) -> str: joined = " ".join(str(a) for a in args) result = run_lib(f"{fn} {joined}", env=env) @@ -195,8 +206,29 @@ class TestOomDetection: class TestDiskBackedTmpdir: def test_returns_nothing_when_tmpdir_is_already_disk_backed(self, tmp_path): - # tmp_path is on the regular filesystem, so the default must be kept. - assert call("lm_disk_backed_tmpdir", env={"TMPDIR": str(tmp_path)}) == "" + # Do not assume tmp_path is disk-backed. Debian 13 -- the platform this + # helper exists for -- mounts /tmp as tmpfs, and pytest puts tmp_path + # under /tmp, so this asserted against a *memory*-backed directory and + # failed on the target platform while the helper behaved exactly as + # designed. Search for a directory whose backing store is really disk. + scratch = None + disk_backed = None + for candidate in (tmp_path, Path("/var/tmp"), LIB.parent): + if _fstype_of(candidate) not in ("tmpfs", "ramfs", ""): + if candidate is tmp_path: + disk_backed = candidate + else: + scratch = Path(tempfile.mkdtemp(dir=str(candidate))) + disk_backed = scratch + break + if disk_backed is None: + pytest.skip("no disk-backed directory available to test against") + try: + assert call("lm_disk_backed_tmpdir", + env={"TMPDIR": str(disk_backed)}) == "" + finally: + if scratch is not None: + scratch.rmdir() def test_redirects_away_from_a_memory_backed_tmpdir(self): # Debian 13 mounts /tmp as tmpfs, which would otherwise hold the whole