8Validate the OI-423 stale Doxyfile sweeper in ``oct.docs.oct_docs``.
12- Confirm old ``oct-doxyfile-*.Doxyfile`` temp files are removed.
13- Confirm recent ``oct-doxyfile-*.Doxyfile`` temp files are preserved.
14- Confirm unrelated temp files are never touched.
15- Confirm the sweeper is resilient to per-file OS errors.
16- Confirm the sweeper returns the count of removed files.
27Inputs: tmp_path, monkeypatch pytest fixtures
28Outputs: pass/fail assertions
34from pathlib
import Path
40 _sweep_stale_doxyfiles,
41 _STALE_DOXYFILE_MAX_AGE_SECONDS,
47 """Redirect ``tempfile.gettempdir()`` to an isolated directory.
49 Prevents tests from touching (or being polluted by) the real system
52 monkeypatch.setattr(tempfile,
"gettempdir",
lambda: str(tmp_path))
55 monkeypatch.setattr(oct_docs.tempfile,
"gettempdir",
lambda: str(tmp_path))
60 path.write_text(
"# fake Doxyfile\n", encoding=
"utf-8")
61 past = time.time() - age_seconds
62 os.utime(path, (past, past))
66 """A 48h-old oct-doxyfile-*.Doxyfile is removed."""
67 stale = isolated_tmp /
"oct-doxyfile-abc123.Doxyfile"
70 removed = _sweep_stale_doxyfiles()
73 assert not stale.exists()
77 """A freshly-created oct-doxyfile-*.Doxyfile is preserved."""
78 recent = isolated_tmp /
"oct-doxyfile-xyz.Doxyfile"
79 recent.write_text(
"# live Doxyfile\n", encoding=
"utf-8")
81 removed = _sweep_stale_doxyfiles()
84 assert recent.exists()
88 """Files without the oct-doxyfile- prefix are never touched."""
89 foreign = isolated_tmp /
"foo.Doxyfile"
92 removed = _sweep_stale_doxyfiles()
95 assert foreign.exists()
99 """The return value equals the number of files actually removed."""
102 isolated_tmp / f
"oct-doxyfile-{i}.Doxyfile", 48 * 3600,
105 (isolated_tmp /
"oct-doxyfile-live.Doxyfile").write_text(
"x", encoding=
"utf-8")
106 _make_stale(isolated_tmp /
"unrelated.Doxyfile", 48 * 3600)
108 removed = _sweep_stale_doxyfiles()
114 isolated_tmp: Path, monkeypatch,
116 """A per-file OSError during unlink must not propagate."""
117 stale = isolated_tmp /
"oct-doxyfile-locked.Doxyfile"
120 real_unlink = Path.unlink
122 def fake_unlink(self, *args, **kwargs):
123 if self.name ==
"oct-doxyfile-locked.Doxyfile":
124 raise OSError(
"simulated permission error")
125 return real_unlink(self, *args, **kwargs)
127 monkeypatch.setattr(Path,
"unlink", fake_unlink)
130 removed = _sweep_stale_doxyfiles()
135 """An explicit max_age_seconds overrides the 24h default."""
137 path = isolated_tmp /
"oct-doxyfile-borderline.Doxyfile"
140 assert _sweep_stale_doxyfiles() == 0
142 assert _sweep_stale_doxyfiles(max_age_seconds=1800) == 1
143 assert not path.exists()
147 """Sanity: the module-level constant matches the documented value."""
148 assert _STALE_DOXYFILE_MAX_AGE_SECONDS == 24 * 60 * 60
None test_sweep_respects_custom_max_age(Path isolated_tmp)
None test_sweep_handles_unlink_failure_gracefully(Path isolated_tmp, monkeypatch)
Path isolated_tmp(Path tmp_path, monkeypatch)
None test_sweep_ignores_unrelated_temp_files(Path isolated_tmp)
None _make_stale(Path path, float age_seconds)
None test_sweep_returns_count(Path isolated_tmp)
None test_sweep_preserves_recent_doxyfile(Path isolated_tmp)
None test_sweep_default_constant_is_one_day()
None test_sweep_removes_old_stale_doxyfile(Path isolated_tmp)