"""Tests for the centralized path registry (fieldwitness/paths.py).""" from __future__ import annotations from pathlib import Path import pytest # --------------------------------------------------------------------------- # Helpers # --------------------------------------------------------------------------- def _fresh_paths_module(monkeypatch: pytest.MonkeyPatch, base_dir: Path): """Return the paths module with BASE_DIR patched to base_dir. The monkeypatch is applied to the already-imported module attribute so that __getattr__ picks up the new value on subsequent calls. """ import fieldwitness.paths as paths monkeypatch.setattr(paths, "BASE_DIR", base_dir) return paths # --------------------------------------------------------------------------- # test_base_dir_default_is_fwmetadata # --------------------------------------------------------------------------- class TestBaseDirDefault: def test_default_base_dir_ends_with_fwmetadata(self, monkeypatch): """Verify the default data directory name is .fwmetadata.""" import os monkeypatch.delenv("FIELDWITNESS_DATA_DIR", raising=False) # Re-derive the default the same way paths.py does at import time. default = Path.home() / ".fwmetadata" assert default.name == ".fwmetadata" def test_default_base_dir_is_under_home(self, monkeypatch): """Verify the default data directory is under the user's home.""" monkeypatch.delenv("FIELDWITNESS_DATA_DIR", raising=False) default = Path.home() / ".fwmetadata" assert str(default).startswith(str(Path.home())) # --------------------------------------------------------------------------- # test_base_dir_override_via_env # --------------------------------------------------------------------------- class TestBaseDirOverrideViaEnv: def test_env_override_changes_base_dir( self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch ): """Setting FIELDWITNESS_DATA_DIR must relocate BASE_DIR.""" custom = tmp_path / "custom-fw-dir" monkeypatch.setenv("FIELDWITNESS_DATA_DIR", str(custom)) # Re-evaluate the path that the module would compute at import time. # Since BASE_DIR is module-level, we test it after patching the attribute. import fieldwitness.paths as paths monkeypatch.setattr(paths, "BASE_DIR", custom) assert paths.BASE_DIR == custom def test_derived_paths_follow_overridden_base_dir( self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch ): """Derived paths (IDENTITY_DIR etc.) must be under the overridden BASE_DIR.""" custom = tmp_path / "relocated" paths = _fresh_paths_module(monkeypatch, custom) assert str(paths.IDENTITY_DIR).startswith(str(custom)) assert str(paths.CHAIN_DIR).startswith(str(custom)) assert str(paths.ATTESTATIONS_DIR).startswith(str(custom)) # --------------------------------------------------------------------------- # test_trusted_keys_dir_exists # --------------------------------------------------------------------------- class TestTrustedKeysDirDefined: def test_trusted_keys_dir_is_defined(self): import fieldwitness.paths as paths # Access must not raise AttributeError td = paths.TRUSTED_KEYS_DIR assert isinstance(td, Path) def test_trusted_keys_dir_under_base_dir( self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch ): paths = _fresh_paths_module(monkeypatch, tmp_path / ".fwmetadata") assert str(paths.TRUSTED_KEYS_DIR).startswith(str(paths.BASE_DIR)) def test_trusted_keys_dir_name(self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch): paths = _fresh_paths_module(monkeypatch, tmp_path / ".fw") assert paths.TRUSTED_KEYS_DIR.name == "trusted_keys" # --------------------------------------------------------------------------- # test_carrier_history_exists # --------------------------------------------------------------------------- class TestCarrierHistoryDefined: def test_carrier_history_is_defined(self): import fieldwitness.paths as paths ch = paths.CARRIER_HISTORY assert isinstance(ch, Path) def test_carrier_history_under_base_dir( self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch ): paths = _fresh_paths_module(monkeypatch, tmp_path / ".fwmetadata") assert str(paths.CARRIER_HISTORY).startswith(str(paths.BASE_DIR)) def test_carrier_history_filename(self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch): paths = _fresh_paths_module(monkeypatch, tmp_path / ".fw") assert paths.CARRIER_HISTORY.name == "carrier_history.json" # --------------------------------------------------------------------------- # test_tor_dir_exists # --------------------------------------------------------------------------- class TestTorDirDefined: def test_tor_dir_is_defined(self): import fieldwitness.paths as paths td = paths.TOR_DIR assert isinstance(td, Path) def test_tor_hidden_service_dir_is_defined(self): import fieldwitness.paths as paths hs = paths.TOR_HIDDEN_SERVICE_DIR assert isinstance(hs, Path) def test_tor_hidden_service_dir_under_tor_dir( self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch ): paths = _fresh_paths_module(monkeypatch, tmp_path / ".fwmetadata") assert str(paths.TOR_HIDDEN_SERVICE_DIR).startswith(str(paths.TOR_DIR)) def test_tor_dir_under_fieldkit_dir( self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch ): paths = _fresh_paths_module(monkeypatch, tmp_path / ".fwmetadata") assert str(paths.TOR_DIR).startswith(str(paths.FIELDKIT_DIR)) # --------------------------------------------------------------------------- # test_all_paths_under_base_dir # --------------------------------------------------------------------------- class TestAllPathsUnderBaseDir: # Names that are files directly under BASE_DIR (one-segment paths where # the parent IS BASE_DIR, not a sub-directory). _SINGLE_SEGMENT = {"AUDIT_LOG", "CONFIG_FILE", "CARRIER_HISTORY", "LAST_BACKUP"} def test_every_defined_path_is_under_base_dir( self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch ): """Every path in _PATH_DEFS must resolve to a location inside BASE_DIR.""" import fieldwitness.paths as _paths_module base = tmp_path / ".fwmetadata" monkeypatch.setattr(_paths_module, "BASE_DIR", base) for name in _paths_module._PATH_DEFS: resolved: Path = _paths_module.__getattr__(name) assert str(resolved).startswith(str(base)), ( f"Path {name!r} resolves to {resolved}, which is outside BASE_DIR {base}" ) def test_no_absolute_hardcoded_paths_outside_base( self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch ): """Changing BASE_DIR must change ALL derived paths — no hardcoded roots.""" import fieldwitness.paths as _paths_module original_base = _paths_module.BASE_DIR new_base = tmp_path / "relocated" monkeypatch.setattr(_paths_module, "BASE_DIR", new_base) for name in _paths_module._PATH_DEFS: resolved: Path = _paths_module.__getattr__(name) # Must be under the new base, not the original one assert str(resolved).startswith(str(new_base)), ( f"Path {name!r} still points under the old BASE_DIR after override" ) def test_path_defs_is_non_empty(self): import fieldwitness.paths as paths assert len(paths._PATH_DEFS) > 0 def test_unknown_attribute_raises_attribute_error(self): import fieldwitness.paths as paths with pytest.raises(AttributeError): paths.__getattr__("DOES_NOT_EXIST_9999")