git / moonbite-network / tests/test_forum_bot.py · raw
"""Automated network reports: numbers come from the node, posts are labelled,each report posts once, and a node outage posts nothing."""import ioimport pytestimport forumimport forum_botDAY = 86_400NOW = 1_800_000_000 - 1_800_000_000 % DAY + 82_800 # 23:00 UTC, after every posting slotclass FakeNode: """Chain of `n` blocks, one every `spacing` seconds, tip at NOW - 60.""" def __init__(self, n=3000, spacing=120, hashps=404.0): self.tip = n - 1 self.times = {h: NOW - 60 - (self.tip - h) * spacing for h in range(n)} self.hashps = hashps def getblockcount(self): return self.tip def getblockhash(self, h): return f"h{h}" def call(self, method, *params): if method == "getblockheader": return {"time": self.times[int(params[0][1:])]} if method == "getnetworkhashps": return self.hashps if method == "getblockhash": return self.getblockhash(params[0]) raise AssertionError(method)class DeadNode(FakeNode): def getblockcount(self): raise forum_bot.NodeUnavailable("down")@pytest.fixture(autouse=True)def board(tmp_path, monkeypatch): monkeypatch.setattr(forum, "_DB_PATH", str(tmp_path / "forum.db"))def run(node, now=NOW): return forum_bot.run(node, now, max_supply=33_000_000, out=io.StringIO())def test_daily_report_posts_once_as_verified_automated(): assert run(FakeNode()) == ["daily:" + forum_bot.time.strftime("%Y-%m-%d", forum_bot.time.gmtime(NOW))] assert run(FakeNode()) == [] # same day: nothing new t = forum.list_threads(category="network")["threads"][0] assert t["author"] == forum.OFFICIAL_NAME and t["is_official"] and t["automated"] body = forum.get_thread(t["id"])["body"] # 24 hours before 00:00 UTC at one block per 2 minutes = 720 blocks assert "Blocks found: 720" in body assert "Average time between blocks: 2 minutes" in body assert "404 H/s" in bodydef test_expected_wait_is_computed_not_claimed(): # 1 kH/s joining a 404 H/s network that makes a block every 120 s assert forum_bot.expected_wait(120, 404, 1000) == pytest.approx(168.48) run(FakeNode()) body = forum.get_thread(forum.list_threads()["threads"][0]["id"])["body"] assert "`1.00 kH/s` about 3 minutes per block" in body # 120 * 1404 / 1000 = 168 s assert "Mining is luck" in bodydef test_milestone_posts_only_when_recent(): # tip 2999 doesn't reach 10,000; a chain whose tip is 10,030 does (60 min ago) run(FakeNode()) assert not any(t["title"].startswith("Block ") for t in forum.list_threads()["threads"]) run(FakeNode(n=10_031), now=NOW + DAY) titles = [t["title"] for t in forum.list_threads(category="network")["threads"]] assert "Block 10,000 reached" in titlesdef test_node_outage_posts_nothing(): with pytest.raises(forum_bot.NodeUnavailable): run(DeadNode()) assert forum.list_threads()["total"] == 0def test_humans_cannot_impersonate_or_use_network_category(): for name in ("MoonBite", "moonbite team", "Moon-Bite", "Admin", "Verified"): with pytest.raises(ValueError): forum.create_thread("t", name, "b") with pytest.raises(ValueError): forum.create_thread("t", "someone", "b", "network") t = forum.create_thread("t", "someone", "b") with pytest.raises(ValueError): forum.add_reply(t["id"], "MoonBite", "fake official reply")