// 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) }