git / moonbite-network / tests/test_explorer_demo_latch.py · raw
"""Regression: an implicit demo-mode fallback must not be permanent.explorer.rpc.RpcClient used to set ``self.demo = True`` forever on the firstRPCConnectionError. web_app caches one client per process and gunicornworkers live for hours, so one timeout while the node was starting left thesite serving demo data / 502s until a restart. The fallback is now a shortcooldown after which the node is retried."""import osimport sysfrom pathlib import Pathimport pytestEXPLORER = Path(__file__).resolve().parent.parent / "explorer"if str(EXPLORER) not in sys.path: sys.path.insert(0, str(EXPLORER))@pytest.fixturedef client(monkeypatch): monkeypatch.delenv("DEMO_MODE", raising=False) import importlib import config as cfg importlib.reload(cfg) import rpc as rpcmod importlib.reload(rpcmod) c = rpcmod.RpcClient() assert c.demo is False return c, rpcmoddef test_fallback_is_a_cooldown_not_a_latch(client, monkeypatch): c, rpcmod = client calls = {"n": 0} def flaky(method, params): calls["n"] += 1 if calls["n"] == 1: raise rpcmod.RPCConnectionError("boom") return 12566 monkeypatch.setattr(c, "_http_call", flaky) now = [1000.0] monkeypatch.setattr(rpcmod.time, "monotonic", lambda: now[0]) # First call: node down -> demo data, demo flag on for the cooldown. assert c.call("getblockcount") != 12566 assert c.demo is True and "unreachable" in c.demo_reason # Inside the cooldown: still demo, node NOT hammered. now[0] += 1.0 c.call("getblockcount") assert calls["n"] == 1 # After the cooldown: node retried, real answer, flag cleared. now[0] += c.IMPLICIT_DEMO_COOLDOWN assert c.call("getblockcount") == 12566 assert c.demo is False and c.demo_reason is Nonedef test_explicit_demo_mode_stays_sticky(monkeypatch): monkeypatch.setenv("DEMO_MODE", "1") import importlib import config as cfg importlib.reload(cfg) import rpc as rpcmod importlib.reload(rpcmod) c = rpcmod.RpcClient() assert c.demo is True monkeypatch.setattr(rpcmod.time, "monotonic", lambda: 1e9) assert c.demo is True # no cooldown can expire an explicit DEMO_MODEdef test_demo_mode_zero_raises_instead_of_faking(monkeypatch): monkeypatch.setenv("DEMO_MODE", "0") import importlib import config as cfg importlib.reload(cfg) import rpc as rpcmod importlib.reload(rpcmod) c = rpcmod.RpcClient() monkeypatch.setattr(c, "_http_call", lambda m, p: (_ for _ in ()).throw(rpcmod.RPCConnectionError("down"))) with pytest.raises(rpcmod.RPCConnectionError): c.call("getblockcount") assert c.demo is False