synvael/crates/shared/src/tests/protocol.rs

88 lines
2.8 KiB
Rust

// SPDX-License-Identifier: AGPL-3.0-only
use super::*;
#[test]
fn stream_layout_default_is_canonical() {
let layout = StreamLayout::default();
assert_eq!(layout.control, 0);
assert_eq!(layout.input, 1);
assert_eq!(layout.authority, 2);
assert_eq!(layout.chunk_lod0, 3);
assert_eq!(layout.chunk_lod1, 4);
assert_eq!(layout.chunk_lod2, 5);
assert_eq!(layout.chunk_lod3, 6);
assert_eq!(layout.chunk_lod4, 7);
assert_eq!(layout.asset, 8);
assert_eq!(layout.mod_data, 9);
}
fn roundtrip_test(msg: &ControlMessage) -> Result<(), postcard::Error> {
let bytes = postcard::to_stdvec(msg)?;
let decoded: ControlMessage = postcard::from_bytes(&bytes)?;
assert_eq!(msg, &decoded);
Ok(())
}
#[test]
fn roundtrip_client_hello() -> Result<(), postcard::Error> {
let msg = ControlMessage::ClientHello(ClientHello {
protocol_version: PROTOCOL_VERSION,
client_build: "synvael-client-0.1.0".to_string(),
player_identity: PlayerIdentity {
display_name: "Player1".to_string(),
},
installed_packs: vec![PackRef {
id: "core:base".to_string(),
version: "1.0.0".to_string(),
content_hash: [0; 32],
tier: PackTier::Data,
}],
requested_features: FeatureFlags(0),
});
roundtrip_test(&msg)
}
#[test]
fn roundtrip_handshake_ack() -> Result<(), postcard::Error> {
let msg = ControlMessage::HandshakeAck(HandshakeAck {
protocol_version: PROTOCOL_VERSION,
server_build: "synvael-server-0.1.0".to_string(),
world_packs: vec![],
missing_packs: vec![],
stream_layout: StreamLayout::default(),
tick_rate_hint: 20,
});
roundtrip_test(&msg)
}
#[test]
fn roundtrip_handshake_reject() -> Result<(), postcard::Error> {
let msg = ControlMessage::HandshakeReject(HandshakeReject {
reason: RejectReason::ProtocolMismatch,
detail: "Expected v1, got v2".to_string(),
upgrade_url: Some("https://synvael.example/download".to_string()),
});
roundtrip_test(&msg)
}
#[test]
fn pack_tier_match_rules() {
// Resource packs are client-side overlays: a mismatch is always tolerated.
assert!(!PackTier::Resource.requires_strict_match());
// Data packs affect authoritative content and must match exactly.
assert!(PackTier::Data.requires_strict_match());
// A client-only mod cannot desync server state, so a mismatch is tolerated.
assert!(!PackTier::Mod { client_only: true }.requires_strict_match());
// A server-affecting mod must match exactly.
assert!(PackTier::Mod { client_only: false }.requires_strict_match());
}
#[test]
fn roundtrip_disconnect() -> Result<(), postcard::Error> {
let msg = ControlMessage::Disconnect(Disconnect {
reason: "Server closing".to_string(),
});
roundtrip_test(&msg)
}