personal memory agent
1# SPDX-License-Identifier: AGPL-3.0-only
2# Copyright (c) 2026 sol pbc
3"""Canary tests for the root conftest TMPDIR fallback prelude."""
4
5from __future__ import annotations
6
7import os
8import subprocess
9import sys
10from pathlib import Path
11
12import pytest
13
14pytest_plugins = ["pytester"]
15
16_ROOT_CONFTEST = Path(__file__).resolve().parent.parent / "conftest.py"
17_NOTICE = (
18 "solstone: pytest invoked without TMPDIR export; routing tmp dirs to "
19 "/var/tmp. Prefer 'make test' to set TMPDIR at the shell level.\n"
20)
21
22
23def _install_root_conftest(pytester: pytest.Pytester) -> None:
24 pytester.makepyfile(conftest=_ROOT_CONFTEST.read_text(encoding="utf-8"))
25
26
27def _run_nested(
28 pytester: pytest.Pytester,
29 env_overrides: dict[str, str | None] | None = None,
30) -> subprocess.CompletedProcess[str]:
31 basetemp = pytester.path / "basetemp"
32 env = os.environ.copy()
33 env.pop("TMPDIR", None)
34 env.pop("_SOLSTONE_TMPDIR_FALLBACK_NOTIFIED", None)
35 env.pop("_SOLSTONE_TMPDIR_FALLBACK_TARGET", None)
36 if env_overrides:
37 for key, value in env_overrides.items():
38 if value is None:
39 env.pop(key, None)
40 else:
41 env[key] = value
42 return subprocess.run(
43 [
44 sys.executable,
45 "-m",
46 "pytest",
47 "-q",
48 "-p",
49 "no:cacheprovider",
50 "--basetemp",
51 str(basetemp),
52 ],
53 cwd=pytester.path,
54 env=env,
55 capture_output=True,
56 text=True,
57 check=False,
58 )
59
60
61def test_prelude_redirects_to_var_tmp(pytester: pytest.Pytester) -> None:
62 _install_root_conftest(pytester)
63 pytester.makepyfile(
64 test_tmpdir="""
65 import os
66 import tempfile
67
68 def test_redirects_to_var_tmp():
69 assert tempfile.gettempdir() == "/var/tmp"
70 assert os.environ["TMPDIR"] == "/var/tmp"
71 """
72 )
73
74 result = _run_nested(pytester)
75
76 assert result.returncode == 0, result.stderr + result.stdout
77 assert "1 passed" in result.stdout
78
79
80def test_notice_present_when_tmpdir_unset(pytester: pytest.Pytester) -> None:
81 _install_root_conftest(pytester)
82 pytester.makepyfile(
83 test_notice="""
84 def test_noop():
85 assert True
86 """
87 )
88
89 result = _run_nested(pytester)
90 combined = result.stderr + result.stdout
91
92 assert result.returncode == 0, combined
93 assert _NOTICE in combined
94
95
96def test_notice_absent_when_tmpdir_already_set(pytester: pytest.Pytester) -> None:
97 _install_root_conftest(pytester)
98 pytester.makepyfile(
99 test_notice="""
100 import os
101 import tempfile
102
103 def test_uses_existing_tmpdir():
104 assert tempfile.gettempdir() == "/tmp"
105 assert os.environ["TMPDIR"] == "/tmp"
106 """
107 )
108
109 result = _run_nested(pytester, {"TMPDIR": "/tmp"})
110 combined = result.stderr + result.stdout
111
112 assert result.returncode == 0, combined
113 assert "solstone: pytest invoked without TMPDIR" not in combined
114
115
116def test_notice_single_fire_across_workers(pytester: pytest.Pytester) -> None:
117 _install_root_conftest(pytester)
118 pytester.makepyfile(
119 test_notice="""
120 def test_noop():
121 assert True
122 """
123 )
124
125 first = _run_nested(pytester)
126 second = _run_nested(pytester, {"_SOLSTONE_TMPDIR_FALLBACK_NOTIFIED": "1"})
127 combined = first.stderr + first.stdout + second.stderr + second.stdout
128
129 assert first.returncode == 0, combined
130 assert second.returncode == 0, combined
131 assert combined.count(_NOTICE) == 1
132
133
134def test_unwritable_target_degrades_visibly(
135 pytester: pytest.Pytester, tmp_path: Path
136) -> None:
137 _install_root_conftest(pytester)
138 pytester.makepyfile(
139 test_notice="""
140 import os
141
142 def test_tmpdir_stays_unset():
143 assert os.environ.get("TMPDIR") is None
144 """
145 )
146 blocked = tmp_path / "blocked"
147 blocked.mkdir()
148 os.chmod(blocked, 0)
149
150 try:
151 result = _run_nested(
152 pytester, {"_SOLSTONE_TMPDIR_FALLBACK_TARGET": str(blocked)}
153 )
154 finally:
155 os.chmod(blocked, 0o700)
156
157 combined = result.stderr + result.stdout
158 notice = (
159 "solstone: pytest invoked without TMPDIR export and fallback target "
160 f"{blocked} is not writable; leaving TMPDIR unset.\n"
161 )
162
163 assert result.returncode == 0, combined
164 assert notice in combined
165 assert "routing tmp dirs to" not in combined
166
167
168def test_subprocess_pytest_lands_in_var_tmp(pytester: pytest.Pytester) -> None:
169 _install_root_conftest(pytester)
170 test_path = pytester.makepyfile(
171 test_subprocess="""
172 import os
173 import tempfile
174
175 def test_redirects_in_fresh_subprocess():
176 assert tempfile.gettempdir() == "/var/tmp"
177 assert os.environ["TMPDIR"] == "/var/tmp"
178 """
179 )
180 env = os.environ.copy()
181 env.pop("TMPDIR", None)
182 env.pop("_SOLSTONE_TMPDIR_FALLBACK_NOTIFIED", None)
183 env.pop("_SOLSTONE_TMPDIR_FALLBACK_TARGET", None)
184
185 result = subprocess.run(
186 [
187 sys.executable,
188 "-m",
189 "pytest",
190 "-q",
191 "-p",
192 "no:cacheprovider",
193 "--basetemp",
194 str(pytester.path / "basetemp"),
195 str(test_path),
196 ],
197 cwd=pytester.path,
198 env=env,
199 capture_output=True,
200 text=True,
201 check=False,
202 )
203
204 assert result.returncode == 0, result.stderr + result.stdout
205 assert "1 passed" in result.stdout