feat: USDT reward system — billing ledger, devnet treasury, settlement loop, forfeiture PoW, tracker dashboard (US-030…US-035, ADR-0015)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
154
tests/test_manual_route_benchmark.py
Normal file
154
tests/test_manual_route_benchmark.py
Normal file
@@ -0,0 +1,154 @@
|
||||
"""US-030: manual route selection + hop-penalty benchmarking.
|
||||
|
||||
Pinned "route" in the chat body overrides auto-selection; the privileged
|
||||
benchmark endpoint fans the same prompt through 1/2/3-node routes and appends
|
||||
per-hop latency records to benchmark_results.json.
|
||||
"""
|
||||
|
||||
import json
|
||||
import urllib.error
|
||||
import urllib.request
|
||||
|
||||
import pytest
|
||||
|
||||
from meshnet_node.server import StubNodeServer
|
||||
from meshnet_tracker.server import TrackerServer
|
||||
|
||||
MODEL = "openai-community/gpt2"
|
||||
|
||||
|
||||
def _post_json(url: str, payload: dict, headers: dict | None = None) -> dict:
|
||||
req = urllib.request.Request(
|
||||
url,
|
||||
data=json.dumps(payload).encode(),
|
||||
headers={"Content-Type": "application/json", **(headers or {})},
|
||||
method="POST",
|
||||
)
|
||||
with urllib.request.urlopen(req) as r:
|
||||
return json.loads(r.read())
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def benchmark_setup(tmp_path):
|
||||
"""Tracker + one full-coverage node and one 0-5/6-11 pair, with node ids."""
|
||||
results_path = str(tmp_path / "benchmark_results.json")
|
||||
tracker = TrackerServer(
|
||||
model_presets={
|
||||
MODEL: {
|
||||
"layers_start": 0,
|
||||
"layers_end": 11,
|
||||
"bytes_per_layer": {"bfloat16": 30 * 1024 * 1024},
|
||||
}
|
||||
},
|
||||
benchmark_results_path=results_path,
|
||||
)
|
||||
port = tracker.start()
|
||||
tracker_url = f"http://127.0.0.1:{port}"
|
||||
|
||||
stubs = []
|
||||
node_ids = {}
|
||||
for name, (start, end, prefix, last) in {
|
||||
"full": (0, 11, "full:", True),
|
||||
"head": (0, 5, "head:", False),
|
||||
"tail": (6, 11, "tail:", True),
|
||||
}.items():
|
||||
stub = StubNodeServer(
|
||||
shard_start=start, shard_end=end, is_last_shard=last,
|
||||
response_prefix=prefix, model=MODEL, tracker_mode=(start == 0),
|
||||
)
|
||||
sport = stub.start()
|
||||
stubs.append(stub)
|
||||
reply = _post_json(f"{tracker_url}/v1/nodes/register", {
|
||||
"endpoint": f"http://127.0.0.1:{sport}",
|
||||
"shard_start": start,
|
||||
"shard_end": end,
|
||||
"model": MODEL,
|
||||
"hardware_profile": {},
|
||||
"score": 1.0,
|
||||
"tracker_mode": start == 0,
|
||||
"node_id": f"node-{name}",
|
||||
})
|
||||
node_ids[name] = reply.get("node_id", f"node-{name}")
|
||||
|
||||
yield tracker_url, node_ids, results_path
|
||||
|
||||
for stub in stubs:
|
||||
stub.stop()
|
||||
tracker.stop()
|
||||
|
||||
|
||||
def _chat(tracker_url: str, route: list[str] | None = None) -> dict:
|
||||
body: dict = {
|
||||
"model": MODEL,
|
||||
"messages": [{"role": "user", "content": "ping"}],
|
||||
}
|
||||
if route is not None:
|
||||
body["route"] = route
|
||||
return _post_json(f"{tracker_url}/v1/chat/completions", body)
|
||||
|
||||
|
||||
def test_pinned_route_uses_named_node(benchmark_setup):
|
||||
tracker_url, node_ids, _ = benchmark_setup
|
||||
reply = _chat(tracker_url, route=[node_ids["full"]])
|
||||
content = reply["choices"][0]["message"]["content"]
|
||||
assert content.startswith("full:")
|
||||
|
||||
|
||||
def test_unknown_route_node_is_400(benchmark_setup):
|
||||
tracker_url, _, _ = benchmark_setup
|
||||
with pytest.raises(urllib.error.HTTPError) as exc_info:
|
||||
_chat(tracker_url, route=["no-such-node"])
|
||||
assert exc_info.value.code == 400
|
||||
detail = json.loads(exc_info.value.read())
|
||||
assert "no-such-node" in detail["error"]["message"]
|
||||
|
||||
|
||||
def test_invalid_route_shape_is_400(benchmark_setup):
|
||||
tracker_url, _, _ = benchmark_setup
|
||||
with pytest.raises(urllib.error.HTTPError) as exc_info:
|
||||
_chat(tracker_url, route=[])
|
||||
assert exc_info.value.code == 400
|
||||
|
||||
|
||||
def test_clients_without_route_are_unaffected(benchmark_setup):
|
||||
tracker_url, _, _ = benchmark_setup
|
||||
reply = _chat(tracker_url)
|
||||
assert reply["choices"][0]["message"]["content"]
|
||||
|
||||
|
||||
def test_benchmark_requires_auth(benchmark_setup):
|
||||
tracker_url, _, _ = benchmark_setup
|
||||
with pytest.raises(urllib.error.HTTPError) as exc_info:
|
||||
_post_json(f"{tracker_url}/v1/benchmark/hop-penalty", {"model": MODEL})
|
||||
assert exc_info.value.code == 401
|
||||
with pytest.raises(urllib.error.HTTPError) as exc_info:
|
||||
urllib.request.urlopen(f"{tracker_url}/v1/benchmark/results")
|
||||
assert exc_info.value.code == 401
|
||||
|
||||
|
||||
def test_benchmark_records_one_and_two_node_routes(benchmark_setup):
|
||||
tracker_url, _, results_path = benchmark_setup
|
||||
record = _post_json(
|
||||
f"{tracker_url}/v1/benchmark/hop-penalty",
|
||||
{"model": MODEL, "prompt": "2+2", "max_new_tokens": 8},
|
||||
headers={"Authorization": "Bearer bench"},
|
||||
)
|
||||
by_hops = {len(r["route"]): r for r in record["routes"] if "total_ms" in r}
|
||||
assert 1 in by_hops and 2 in by_hops # 3-node coverage impossible → skipped
|
||||
assert 3 not in by_hops
|
||||
assert len(by_hops[1]["per_hop_ms"]) == 1
|
||||
assert len(by_hops[2]["per_hop_ms"]) == 2
|
||||
assert by_hops[2]["total_ms"] > 0
|
||||
|
||||
stored = json.loads(open(results_path, encoding="utf-8").read())
|
||||
assert isinstance(stored, list) and len(stored) == 1
|
||||
assert stored[0]["model"] == MODEL
|
||||
assert stored[0]["prompt_hash"]
|
||||
|
||||
fetched = json.loads(
|
||||
urllib.request.urlopen(urllib.request.Request(
|
||||
f"{tracker_url}/v1/benchmark/results",
|
||||
headers={"Authorization": "Bearer bench"},
|
||||
)).read()
|
||||
)
|
||||
assert len(fetched["results"]) == 1
|
||||
Reference in New Issue
Block a user