Files
coinhunter-cli/tests/test_runtime.py
Tacit Lab 62c40a9776 refactor: address high-priority debt and publish to PyPI
- Fix TOCTOU race conditions by wrapping read-modify-write cycles
  under single-file locks in execution_state, portfolio_service,
  precheck_state, state_manager, and precheck_service.
- Add missing test coverage (96 tests total):
  - test_review_service.py (15 tests)
  - test_check_api.py (6 tests)
  - test_external_gate.py main branches (+10 tests)
  - test_trade_execution.py new commands (+8 tests)
- Unify all agent-consumed JSON messages to English.
- Config-ize hardcoded values (volume filter, schema_version) via
  get_user_config with sensible defaults.
- Add 1-hour TTL to exchange cache with force_new override.
- Add ruff and mypy to dev dependencies; fix all type errors.
- Add __all__ declarations to 11 service modules.
- Sync README with new commands, config tuning docs, and PyPI badge.
- Publish package as coinhunter==1.0.0 on PyPI with MIT license.
- Deprecate coinhunter-cli==1.0.1 with runtime warning.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-16 01:21:27 +08:00

64 lines
2.1 KiB
Python

"""Tests for runtime path resolution."""
from pathlib import Path
import pytest
from coinhunter.runtime import RuntimePaths, ensure_runtime_dirs, get_runtime_paths, mask_secret
class TestGetRuntimePaths:
def test_defaults_point_to_home_dot_coinhunter(self):
paths = get_runtime_paths()
assert paths.root == Path.home() / ".coinhunter"
def test_respects_coinhunter_home_env(self, monkeypatch):
monkeypatch.setenv("COINHUNTER_HOME", "~/custom_ch")
paths = get_runtime_paths()
assert paths.root == Path.home() / "custom_ch"
def test_respects_hermes_home_env(self, monkeypatch):
monkeypatch.setenv("HERMES_HOME", "~/custom_hermes")
paths = get_runtime_paths()
assert paths.hermes_home == Path.home() / "custom_hermes"
assert paths.env_file == Path.home() / "custom_hermes" / ".env"
def test_returns_frozen_dataclass(self):
paths = get_runtime_paths()
assert isinstance(paths, RuntimePaths)
with pytest.raises(AttributeError):
paths.root = Path("/tmp")
def test_as_dict_returns_strings(self):
paths = get_runtime_paths()
d = paths.as_dict()
assert isinstance(d, dict)
assert all(isinstance(v, str) for v in d.values())
assert "root" in d
class TestEnsureRuntimeDirs:
def test_creates_directories(self, tmp_path, monkeypatch):
monkeypatch.setenv("COINHUNTER_HOME", str(tmp_path))
paths = get_runtime_paths()
returned = ensure_runtime_dirs(paths)
assert returned.root.exists()
assert returned.state_dir.exists()
assert returned.logs_dir.exists()
assert returned.cache_dir.exists()
assert returned.reviews_dir.exists()
class TestMaskSecret:
def test_empty_string(self):
assert mask_secret("") == ""
def test_short_value(self):
assert mask_secret("ab") == "**"
def test_masks_all_but_tail(self):
assert mask_secret("supersecret", tail=4) == "*******cret"
def test_none_returns_empty(self):
assert mask_secret(None) == ""