use super::helpers::{minimal_hs, raw_connect, recv_ack, send_hs};
use crate::common::origin::OriginServer;
use nodedb_types::sync::wire::HandshakeMsg;
use nodedb_types::wire_version::WIRE_FORMAT_VERSION;
#[tokio::test]
async fn exact_wire_version_1_is_accepted() {
let Some(_server) = OriginServer::try_spawn() else {
eprintln!("SKIP: Origin binary unavailable (set NODEDB_BIN or run via `cargo nextest`)");
return;
};
let mut ws = raw_connect(_server.ws_url).await;
assert_eq!(
WIRE_FORMAT_VERSION, 1,
"Lite WIRE_FORMAT_VERSION drifted from 1; update this test and the protocol doc"
);
let hs = HandshakeMsg {
wire_version: 1,
..minimal_hs()
};
send_hs(&mut ws, &hs).await;
let ack = recv_ack(&mut ws).await;
assert!(
ack.success,
"wire_version=1 must be accepted; error: {:?}",
ack.error
);
assert_eq!(
ack.server_wire_version, 1,
"server_wire_version must be 1; if this fails Origin bumped its constant without updating Lite"
);
}
#[tokio::test]
async fn wire_version_zero_is_rejected() {
let Some(_server) = OriginServer::try_spawn() else {
eprintln!("SKIP: Origin binary unavailable (set NODEDB_BIN or run via `cargo nextest`)");
return;
};
let mut ws = raw_connect(_server.ws_url).await;
let hs = HandshakeMsg {
wire_version: 0,
..minimal_hs()
};
send_hs(&mut ws, &hs).await;
let ack = recv_ack(&mut ws).await;
assert!(
!ack.success,
"wire_version=0 must be rejected; if this passes Origin loosened its version check"
);
let err = ack
.error
.expect("error field must be present on version rejection");
assert!(
err.contains("wire version") || err.contains("incompatible"),
"error must mention wire version incompatibility; got: {err}"
);
}
#[tokio::test]
async fn wire_version_6_is_rejected() {
let Some(_server) = OriginServer::try_spawn() else {
eprintln!("SKIP: Origin binary unavailable (set NODEDB_BIN or run via `cargo nextest`)");
return;
};
let mut ws = raw_connect(_server.ws_url).await;
let hs = HandshakeMsg {
wire_version: 6,
..minimal_hs()
};
send_hs(&mut ws, &hs).await;
let ack = recv_ack(&mut ws).await;
assert!(
!ack.success,
"wire_version=6 must be rejected (only 1 is accepted); if this passes Origin widened its version check"
);
}
#[tokio::test]
async fn ack_shape_on_success() {
let Some(_server) = OriginServer::try_spawn() else {
eprintln!("SKIP: Origin binary unavailable (set NODEDB_BIN or run via `cargo nextest`)");
return;
};
let mut ws = raw_connect(_server.ws_url).await;
send_hs(&mut ws, &minimal_hs()).await;
let ack = recv_ack(&mut ws).await;
assert!(ack.success, "handshake should succeed");
assert!(
!ack.session_id.is_empty(),
"session_id must be non-empty on success"
);
assert!(
ack.error.is_none(),
"error must be None on success, got: {:?}",
ack.error
);
assert!(
!ack.fork_detected,
"fork_detected must be false for empty lite_id"
);
assert!(
ack.server_wire_version >= 1,
"server_wire_version must be >= 1"
);
}
#[tokio::test]
async fn ack_shape_on_rejection() {
let Some(_server) = OriginServer::try_spawn() else {
eprintln!("SKIP: Origin binary unavailable (set NODEDB_BIN or run via `cargo nextest`)");
return;
};
let mut ws = raw_connect(_server.ws_url).await;
let hs = HandshakeMsg {
wire_version: 0,
..minimal_hs()
};
send_hs(&mut ws, &hs).await;
let ack = recv_ack(&mut ws).await;
assert!(!ack.success);
assert!(ack.error.is_some(), "error field must be Some on rejection");
assert!(
!ack.session_id.is_empty(),
"session_id is echoed by Origin even on rejection"
);
}