"""V1: dark-idle behavior — no keys ⇒ idle loop, exec adapter never built.""" from __future__ import annotations import asyncio import sys sys.path.insert(0, "/mnt/dolphinng5_predict") sys.path.insert(0, "/mnt/dolphinng5_predict/nautilus_dolphin") import pytest def _clear_keys(monkeypatch): monkeypatch.delenv("BINGX_VIOLET_API_KEY", raising=False) monkeypatch.delenv("BINGX_VIOLET_SECRET_KEY", raising=False) def test_keys_present_detection(monkeypatch): import prod.launch_dolphin_violet as lv _clear_keys(monkeypatch) assert lv._violet_keys_present() is False monkeypatch.setenv("BINGX_VIOLET_API_KEY", "k") assert lv._violet_keys_present() is False # secret still missing monkeypatch.setenv("BINGX_VIOLET_SECRET_KEY", "s") assert lv._violet_keys_present() is True monkeypatch.setenv("BINGX_VIOLET_API_KEY", " ") assert lv._violet_keys_present() is False # whitespace is absent def test_dark_run_never_builds_exec_adapter(monkeypatch): """Without keys, run() must enter the dark loop and never construct the observe runtime (and therefore never the BingX exec adapter).""" import prod.launch_dolphin_violet as lv _clear_keys(monkeypatch) monkeypatch.setenv("DOLPHIN_VIOLET_DARK_DIVERGENCE", "0") # strict idle monkeypatch.setattr(lv, "_preflight_clickhouse", lambda: []) def boom(): raise AssertionError("observe runtime must not be built while DARK") monkeypatch.setattr(lv, "_build_observe_runtime", boom) warnings: list[str] = [] monkeypatch.setattr( lv.LOGGER, "warning", lambda msg, *a: warnings.append(msg % a if a else str(msg)) ) async def drive(): task = asyncio.ensure_future(lv.run()) await asyncio.sleep(0.3) # boot path reaches the dark loop task.cancel() try: await task except asyncio.CancelledError: pass asyncio.run(drive()) assert any("VIOLET DARK" in w for w in warnings), warnings def test_missing_tables_idles_dark_naming_apply_cmd(monkeypatch): import prod.launch_dolphin_violet as lv _clear_keys(monkeypatch) monkeypatch.setattr(lv, "_preflight_clickhouse", lambda: ["violet_feed_divergence"]) crits: list[str] = [] monkeypatch.setattr( lv.LOGGER, "critical", lambda msg, *a: crits.append(msg % a if a else str(msg)) ) async def drive(): task = asyncio.ensure_future(lv.run()) await asyncio.sleep(0.3) task.cancel() try: await task except asyncio.CancelledError: pass asyncio.run(drive()) assert crits and "apply_violet_ddl.py" in crits[0] assert "violet_feed_divergence" in crits[0] def test_violet_env_hard_sets_namespaces_and_snapshot_path(monkeypatch): import prod.launch_dolphin_violet as lv import prod.clean_arch.runtime.pink_direct as pd monkeypatch.setenv("DOLPHIN_STATE_MAP", "DOLPHIN_STATE_PINK") # poisoned env original = pd._KERNEL_STATE_PATH try: lv._apply_violet_env() import os assert os.environ["DOLPHIN_STATE_MAP"] == "DOLPHIN_STATE_VIOLET" assert os.environ["DITA_V2_PREFIX"] == "violet" assert os.environ["DOLPHIN_BINGX_ALLOW_MAINNET"] == "0" # kernel snapshot file repointed away from PINK's fixed path assert pd._KERNEL_STATE_PATH == lv._KERNEL_STATE_PATH_VIOLET assert "pink" not in str(pd._KERNEL_STATE_PATH) finally: pd._KERNEL_STATE_PATH = original if __name__ == "__main__": raise SystemExit(pytest.main([__file__, "-v"]))