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")