137 lines
4.8 KiB
Python
137 lines
4.8 KiB
Python
"""US-035: tracker web dashboard — served from any tracker, embedded asset."""
|
|
|
|
import json
|
|
import time
|
|
import urllib.request
|
|
|
|
from meshnet_contracts import LocalSolanaContracts
|
|
from meshnet_tracker.accounts import AccountStore
|
|
from meshnet_tracker.billing import BillingLedger
|
|
from meshnet_tracker.server import TrackerServer
|
|
|
|
PANELS = [
|
|
"Tracker hive", "Nodes & coverage", "Client balances",
|
|
"Node pending payouts", "Settlement history",
|
|
"Strikes / bans / forfeitures", "Model usage", "Node throughput",
|
|
"Console output",
|
|
]
|
|
|
|
|
|
def test_dashboard_served_with_all_panels():
|
|
tracker = TrackerServer(billing=BillingLedger())
|
|
port = tracker.start()
|
|
try:
|
|
html = urllib.request.urlopen(
|
|
f"http://127.0.0.1:{port}/dashboard"
|
|
).read().decode()
|
|
for panel in PANELS:
|
|
assert panel in html
|
|
assert "<script>" in html # polling client embedded, no build step
|
|
finally:
|
|
tracker.stop()
|
|
|
|
|
|
def test_dashboard_served_by_follower():
|
|
"""A tracker that is not the leader (unreachable peers → never elected)
|
|
still serves the dashboard from its own replicated state."""
|
|
tracker = TrackerServer(
|
|
billing=BillingLedger(),
|
|
cluster_peers=["http://127.0.0.1:1", "http://127.0.0.1:2"],
|
|
)
|
|
port = tracker.start()
|
|
try:
|
|
response = urllib.request.urlopen(f"http://127.0.0.1:{port}/dashboard")
|
|
assert response.status == 200
|
|
assert "meshnet tracker" in response.read().decode()
|
|
finally:
|
|
tracker.stop()
|
|
|
|
|
|
def test_registry_wallets_endpoint():
|
|
contracts = LocalSolanaContracts()
|
|
contracts.registry.submit_stake("wallet-a", 100)
|
|
contracts.registry.record_strike("wallet-a")
|
|
accounts = AccountStore()
|
|
admin = accounts.register(email="admin@example.com", password="admin-pass-123")
|
|
session = accounts.create_session(admin["account_id"])
|
|
tracker = TrackerServer(contracts=contracts, accounts=accounts)
|
|
port = tracker.start()
|
|
try:
|
|
req = urllib.request.Request(
|
|
f"http://127.0.0.1:{port}/v1/registry/wallets",
|
|
headers={"Authorization": f"Bearer {session}"},
|
|
)
|
|
data = json.loads(urllib.request.urlopen(req).read())
|
|
assert data["wallets"]["wallet-a"]["strike_count"] == 1
|
|
assert data["wallets"]["wallet-a"]["banned"] is False
|
|
finally:
|
|
tracker.stop()
|
|
|
|
|
|
def test_console_endpoint_exposes_tracker_events():
|
|
tracker = TrackerServer()
|
|
port = tracker.start()
|
|
try:
|
|
body = json.dumps({
|
|
"endpoint": "http://127.0.0.1:9001",
|
|
"model": "stub-model",
|
|
"shard_start": 0,
|
|
"shard_end": 3,
|
|
"hardware_profile": {},
|
|
}).encode()
|
|
req = urllib.request.Request(
|
|
f"http://127.0.0.1:{port}/v1/nodes/register",
|
|
data=body,
|
|
headers={"Content-Type": "application/json"},
|
|
method="POST",
|
|
)
|
|
urllib.request.urlopen(req).read()
|
|
|
|
data = json.loads(urllib.request.urlopen(f"http://127.0.0.1:{port}/v1/console").read())
|
|
finally:
|
|
tracker.stop()
|
|
|
|
assert any(event["message"] == "node registered" for event in data["events"])
|
|
|
|
|
|
def test_console_node_lifecycle_events_include_model_health():
|
|
tracker = TrackerServer(heartbeat_timeout=0.05)
|
|
port = tracker.start()
|
|
try:
|
|
body = json.dumps({
|
|
"endpoint": "http://127.0.0.1:9002",
|
|
"model": "console-health-test",
|
|
"hf_repo": "example/console-health-test",
|
|
"num_layers": 4,
|
|
"shard_start": 0,
|
|
"shard_end": 1,
|
|
"hardware_profile": {},
|
|
}).encode()
|
|
req = urllib.request.Request(
|
|
f"http://127.0.0.1:{port}/v1/nodes/register",
|
|
data=body,
|
|
headers={"Content-Type": "application/json"},
|
|
method="POST",
|
|
)
|
|
urllib.request.urlopen(req).read()
|
|
|
|
registered = json.loads(urllib.request.urlopen(f"http://127.0.0.1:{port}/v1/console").read())
|
|
registered_event = next(
|
|
event for event in registered["events"]
|
|
if event["message"] == "node registered"
|
|
)
|
|
assert registered_event["fields"]["model_health"]["served_model_copies"] == 0.5
|
|
assert registered_event["fields"]["model_health"]["coverage_percentage"] == 50.0
|
|
|
|
time.sleep(0.06)
|
|
urllib.request.urlopen(f"http://127.0.0.1:{port}/v1/network/map").read()
|
|
expired = json.loads(urllib.request.urlopen(f"http://127.0.0.1:{port}/v1/console").read())
|
|
expired_event = next(
|
|
event for event in expired["events"]
|
|
if event["message"] == "node expired"
|
|
)
|
|
assert expired_event["fields"]["model_health"]["served_model_copies"] == 0.0
|
|
assert expired_event["fields"]["model_health"]["coverage_percentage"] == 0.0
|
|
finally:
|
|
tracker.stop()
|