use libremetaverse::packets::{ AgentMovementCompletePacketDataBlock, AgentThrottlePacketThrottleBlock, Packet, PacketAckPacket, PacketAckPacketPacketsBlock, PacketType, TestMessagePacket, }; use libremetaverse_structured_data::{OSD, OSDMap}; use std::collections::HashMap; fn map(values: impl IntoIterator) -> OSD { OSD::Map( values .into_iter() .map(|(key, value)| (key.to_owned(), value)) .collect::>(), ) } #[test] fn block_osd_matches_unsigned_and_missing_field_reference_semantics() { let mut block = AgentMovementCompletePacketDataBlock::new_with_constructor().unwrap(); block.region_handle = 0x0102_0304_0506_0708; block.timestamp = 0x1122_3344; let encoded = block.to_osd().unwrap(); assert_eq!( encoded.get("RegionHandle"), Some(OSD::Binary(vec![ 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01 ])) ); assert_eq!( encoded.get("Timestamp"), Some(OSD::Binary(vec![0x44, 0x33, 0x22, 0x11])) ); let partial = OSDMap::new_with_constructor().unwrap(); partial .add_with_string_osd("Timestamp".to_owned(), OSD::Binary(vec![1, 2, 3])) .unwrap(); block.from_osd(partial).unwrap(); assert_eq!(block.timestamp, 0); assert_eq!(block.region_handle, 0x0102_0304_0506_0708); } #[test] fn byte_fields_accept_osd_strings_as_utf8_like_the_reference_generator() { let mut block = AgentThrottlePacketThrottleBlock::new_with_constructor().unwrap(); let source = OSDMap::new_with_constructor().unwrap(); source .add_with_string_osd("Throttles".to_owned(), OSD::String("throttle".to_owned())) .unwrap(); block.from_osd(source).unwrap(); assert_eq!(block.throttles, b"throttle"); } #[test] fn packet_osd_replaces_variable_blocks_and_restores_fixed_block_counts() { let mut variable = PacketAckPacket::new_with_constructor().unwrap(); let mut old = PacketAckPacketPacketsBlock::new_with_constructor().unwrap(); old.id = 99; variable.packets.push(old); let variable_body = OSDMap::new_with_constructor().unwrap(); variable_body .add_with_string_osd( "Packets".to_owned(), OSD::Array(vec![ map([("ID", OSD::Binary(7_u32.to_le_bytes().to_vec()))]), OSD::Undefined, ]), ) .unwrap(); variable.packet_from_osd(variable_body).unwrap(); assert_eq!(variable.packets.len(), 2); assert_eq!(variable.packets[0].id, 7); assert_eq!(variable.packets[1].id, 0); let mut fixed = TestMessagePacket::new_with_constructor().unwrap(); fixed.neighbor_block.clear(); let fixed_body = OSDMap::new_with_constructor().unwrap(); fixed_body .add_with_string_osd( "NeighborBlock".to_owned(), OSD::Array(vec![ map([("Test0", OSD::Binary(42_u32.to_le_bytes().to_vec()))]), OSD::String("not a block map".to_owned()), ]), ) .unwrap(); fixed.packet_from_osd(fixed_body).unwrap(); assert_eq!(fixed.neighbor_block.len(), 4); assert_eq!(fixed.neighbor_block[0].test0, 42); assert!( fixed.neighbor_block[1..] .iter() .all(|block| block.test0 == 0) ); } #[test] fn osd_packet_factory_validates_known_bodies_and_rejects_unknown_names() { let body = OSDMap::new_with_constructor().unwrap(); body.add_with_string_osd("Packets".to_owned(), OSD::Array(Vec::new())) .unwrap(); let packet = Packet::build_packet_from_osd("PacketAck".to_owned(), body.clone()) .unwrap() .expect("known packet"); assert_eq!(packet.type_, PacketType::PacketAck); assert!( Packet::build_packet_from_osd("UnknownPacket".to_owned(), body) .unwrap() .is_none() ); }