65 lines
2.4 KiB
Python
65 lines
2.4 KiB
Python
"""US-002 integration test: two-node shard pipeline with activation tensors flowing A → B."""
|
|
|
|
import json
|
|
import urllib.request
|
|
|
|
from meshnet_node.server import StubNodeServer
|
|
from meshnet_gateway.server import GatewayServer
|
|
|
|
|
|
def test_two_node_activation_pipeline():
|
|
# Node A owns layers 0-15 (first shard, not last — returns activations).
|
|
node_a = StubNodeServer(shard_start=0, shard_end=15, is_last_shard=False)
|
|
port_a = node_a.start()
|
|
|
|
# Node B owns layers 16-31 (last shard — returns text after receiving activations).
|
|
node_b = StubNodeServer(shard_start=16, shard_end=31, is_last_shard=True)
|
|
port_b = node_b.start()
|
|
|
|
# Gateway hardcodes the two-node inference route for this story.
|
|
gateway = GatewayServer(
|
|
inference_route=[
|
|
f"http://127.0.0.1:{port_a}",
|
|
f"http://127.0.0.1:{port_b}",
|
|
]
|
|
)
|
|
gateway_port = gateway.start()
|
|
|
|
try:
|
|
payload = json.dumps({
|
|
"model": "stub-model",
|
|
"messages": [{"role": "user", "content": "hello"}],
|
|
}).encode()
|
|
|
|
req = urllib.request.Request(
|
|
f"http://127.0.0.1:{gateway_port}/v1/chat/completions",
|
|
data=payload,
|
|
headers={"Content-Type": "application/json"},
|
|
method="POST",
|
|
)
|
|
|
|
with urllib.request.urlopen(req) as resp:
|
|
assert resp.status == 200
|
|
body = json.loads(resp.read())
|
|
|
|
# Gateway must assemble a valid OpenAI-format response.
|
|
assert body["id"] == "chatcmpl-stub"
|
|
assert body["object"] == "chat.completion"
|
|
assert body["model"] == "stub-model"
|
|
assert len(body["choices"]) == 1
|
|
choice = body["choices"][0]
|
|
assert choice["message"]["role"] == "assistant"
|
|
assert choice["message"]["content"] == "stub response to: hello"
|
|
assert choice["finish_reason"] == "stop"
|
|
|
|
# Node B must have received an activation tensor from node A — this is
|
|
# the observable proof that the A → B activation hop occurred.
|
|
assert node_b.received_activations, "node B did not receive activation tensors from node A"
|
|
|
|
# Node A must NOT have received activations (it is the first shard).
|
|
assert not node_a.received_activations, "node A should not receive activations — it is first in the route"
|
|
finally:
|
|
gateway.stop()
|
|
node_a.stop()
|
|
node_b.stop()
|