Files
Cerbero-Bite/tests/unit/test_smoke.py
Adriano 411b747e93 Phase 4 hardening: status CLI, lock file, backup job, hash enforce, pooling, real bias
Sei interventi mirati sui rischi operativi rilevati nell'audit
post-Fase 4. 317 test pass, mypy strict pulito, ruff clean.

1. status CLI: legge SQLite reale e mostra kill_switch, posizioni
   aperte, environment, config_version, last_health_check, started_at.
   Sostituisce il placeholder "phase 0 skeleton".

2. Lock file single-instance: runtime/lockfile.py acquisisce
   data/.lockfile via fcntl.flock al boot di run_forever; un secondo
   container fallisce subito con LockError.

3. Backup orario nello scheduler: nuovo job APScheduler 0 * * * *
   chiama scripts.backup.backup_database + prune_backups.

4. config_hash enforce su start: il CLI start verifica l'integrità
   del file (enforce_hash=True). Mismatch → exit 1 prima di toccare
   stato. dry-run resta enforce_hash=False per debug.

5. Connection pooling MCP: RuntimeContext espone un httpx.AsyncClient
   long-lived condiviso da tutti i wrapper (limits 20/10
   connections/keepalive). aclose() chiamato in run_forever finale.

6. Bias direzionale reale: deribit.historical_close +
   deribit.adx_14 popolano TrendContext con spot a 30 giorni e
   ADX(14) effettivi. Sblocca bull_put e bear_call. Quando i dati
   storici mancano l'engine emette alert MEDIUM e cade su no_entry
   in modo deterministico.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 00:15:28 +02:00

97 lines
2.6 KiB
Python

"""Smoke tests: package importable, version exposed, CLI invokable."""
from __future__ import annotations
from pathlib import Path
from click.testing import CliRunner
import cerbero_bite
from cerbero_bite import __version__
from cerbero_bite.cli import main as cli_main
def test_package_version_string() -> None:
assert isinstance(__version__, str)
assert __version__.count(".") == 2
def test_package_module_attribute() -> None:
assert cerbero_bite.__version__ == __version__
def test_cli_help_lists_status_command() -> None:
runner = CliRunner()
result = runner.invoke(cli_main, ["--help"])
assert result.exit_code == 0
assert "status" in result.output
def test_cli_status_when_state_missing(tmp_data_dir: Path) -> None:
runner = CliRunner()
result = runner.invoke(
cli_main,
[
"--log-dir",
str(tmp_data_dir / "log"),
"status",
"--db",
str(tmp_data_dir / "missing.sqlite"),
],
)
assert result.exit_code == 0
assert "Cerbero Bite" in result.output
assert "never started" in result.output
def test_cli_status_after_kill_switch_arm(tmp_data_dir: Path) -> None:
runner = CliRunner()
db_path = tmp_data_dir / "state.sqlite"
audit_path = tmp_data_dir / "audit.log"
runner.invoke(
cli_main,
[
"--log-dir", str(tmp_data_dir / "log"),
"kill-switch", "arm",
"--reason", "smoke",
"--db", str(db_path),
"--audit", str(audit_path),
],
)
result = runner.invoke(cli_main, ["status", "--db", str(db_path)])
assert result.exit_code == 0
assert "ARMED" in result.output
assert "open positions: 0" in result.output
def test_cli_kill_switch_arm_persists_state(tmp_data_dir: Path) -> None:
runner = CliRunner()
db_path = tmp_data_dir / "state.sqlite"
audit_path = tmp_data_dir / "audit.log"
result = runner.invoke(
cli_main,
[
"--log-dir",
str(tmp_data_dir / "log"),
"kill-switch",
"arm",
"--reason",
"smoke",
"--db",
str(db_path),
"--audit",
str(audit_path),
],
)
assert result.exit_code == 0, result.output
assert "ARMED" in result.output
assert db_path.exists()
assert audit_path.exists()
def test_cli_version_flag() -> None:
runner = CliRunner()
result = runner.invoke(cli_main, ["--version"])
assert result.exit_code == 0
assert __version__ in result.output