90 lines
2.4 KiB
Python
90 lines
2.4 KiB
Python
|
|
#!/usr/bin/env python3
|
||
|
|
"""Forge smoke tests — fast checks that core imports resolve and entrypoints load.
|
||
|
|
|
||
|
|
Total runtime target: < 30 seconds.
|
||
|
|
"""
|
||
|
|
|
||
|
|
from __future__ import annotations
|
||
|
|
|
||
|
|
import importlib
|
||
|
|
import subprocess
|
||
|
|
import sys
|
||
|
|
from pathlib import Path
|
||
|
|
|
||
|
|
# Allow running smoke test directly from repo root before pip install
|
||
|
|
REPO_ROOT = Path(__file__).parent.parent
|
||
|
|
sys.path.insert(0, str(REPO_ROOT))
|
||
|
|
|
||
|
|
CORE_MODULES = [
|
||
|
|
"hermes_cli.config",
|
||
|
|
"hermes_state",
|
||
|
|
"model_tools",
|
||
|
|
"toolsets",
|
||
|
|
"utils",
|
||
|
|
]
|
||
|
|
|
||
|
|
CLI_ENTRYPOINTS = [
|
||
|
|
[sys.executable, "cli.py", "--help"],
|
||
|
|
]
|
||
|
|
|
||
|
|
|
||
|
|
def test_imports() -> None:
|
||
|
|
ok = 0
|
||
|
|
skipped = 0
|
||
|
|
for mod in CORE_MODULES:
|
||
|
|
try:
|
||
|
|
importlib.import_module(mod)
|
||
|
|
ok += 1
|
||
|
|
except ImportError as exc:
|
||
|
|
# If the failure is a missing third-party dependency, skip rather than fail
|
||
|
|
# so the smoke test can run before `pip install` in bare environments.
|
||
|
|
msg = str(exc).lower()
|
||
|
|
if "no module named" in msg and mod.replace(".", "/") not in msg:
|
||
|
|
print(f"SKIP: import {mod} -> missing dependency ({exc})")
|
||
|
|
skipped += 1
|
||
|
|
else:
|
||
|
|
print(f"FAIL: import {mod} -> {exc}")
|
||
|
|
sys.exit(1)
|
||
|
|
except Exception as exc:
|
||
|
|
print(f"FAIL: import {mod} -> {exc}")
|
||
|
|
sys.exit(1)
|
||
|
|
print(f"OK: {ok} core imports", end="")
|
||
|
|
if skipped:
|
||
|
|
print(f" ({skipped} skipped due to missing deps)")
|
||
|
|
else:
|
||
|
|
print()
|
||
|
|
|
||
|
|
|
||
|
|
def test_cli_help() -> None:
|
||
|
|
ok = 0
|
||
|
|
skipped = 0
|
||
|
|
for cmd in CLI_ENTRYPOINTS:
|
||
|
|
result = subprocess.run(cmd, capture_output=True, timeout=30)
|
||
|
|
if result.returncode == 0:
|
||
|
|
ok += 1
|
||
|
|
continue
|
||
|
|
stderr = result.stderr.decode().lower()
|
||
|
|
# Gracefully skip if dependencies are missing in bare environments
|
||
|
|
if "modulenotfounderror" in stderr or "no module named" in stderr:
|
||
|
|
print(f"SKIP: {' '.join(cmd)} -> missing dependency")
|
||
|
|
skipped += 1
|
||
|
|
else:
|
||
|
|
print(f"FAIL: {' '.join(cmd)} -> {result.stderr.decode()[:200]}")
|
||
|
|
sys.exit(1)
|
||
|
|
print(f"OK: {ok} CLI entrypoints", end="")
|
||
|
|
if skipped:
|
||
|
|
print(f" ({skipped} skipped due to missing deps)")
|
||
|
|
else:
|
||
|
|
print()
|
||
|
|
|
||
|
|
|
||
|
|
def main() -> int:
|
||
|
|
test_imports()
|
||
|
|
test_cli_help()
|
||
|
|
print("Smoke tests passed.")
|
||
|
|
return 0
|
||
|
|
|
||
|
|
|
||
|
|
if __name__ == "__main__":
|
||
|
|
raise SystemExit(main())
|