use libremetaverse::PacketFrequency; use libremetaverse::packet_catalog::{ BlockRepetition, FieldKind, PACKETS, descriptor_by_name, descriptor_by_type, }; use libremetaverse::packets::{ Packet, PacketAckPacket, PacketType, TestMessagePacket, UseCircuitCodePacket, }; use std::collections::BTreeSet; #[test] fn generated_catalog_matches_the_complete_pinned_protocol() { assert_eq!(PACKETS.len(), 483); assert_eq!( PACKETS .iter() .filter(|packet| packet.frequency == PacketFrequency::Low) .count(), 434 ); assert_eq!( PACKETS .iter() .filter(|packet| packet.frequency == PacketFrequency::Medium) .count(), 17 ); assert_eq!( PACKETS .iter() .filter(|packet| packet.frequency == PacketFrequency::High) .count(), 32 ); let names = PACKETS .iter() .map(|packet| packet.name) .collect::>(); let ids = PACKETS .iter() .map(|packet| (packet.frequency as u8, packet.id)) .collect::>(); assert_eq!(names.len(), PACKETS.len()); assert_eq!(ids.len(), PACKETS.len()); for descriptor in PACKETS { assert_eq!(descriptor_by_name(descriptor.name), Some(descriptor)); assert_eq!(descriptor_by_type(descriptor.packet_type), Some(descriptor)); assert_eq!( Packet::get_type(descriptor.id, descriptor.frequency).unwrap(), descriptor.packet_type ); } } #[test] fn generated_ids_repetition_and_field_widths_match_golden_entries() { assert_eq!(PacketType::TestMessage as i32, 0x1_0001); assert_eq!(PacketType::PacketAck as i32, 0x1_fffb); assert_eq!(PacketType::ObjectUpdate as i32, 0x3_000c); let test = descriptor_by_name("TestMessage").unwrap(); assert_eq!(test.id, 1); assert_eq!(test.blocks.len(), 2); assert_eq!(test.blocks[0].repetition, BlockRepetition::Single); assert_eq!(test.blocks[1].repetition, BlockRepetition::Multiple(4)); assert_eq!(test.blocks[1].fields.len(), 3); assert!( test.blocks[1] .fields .iter() .all(|field| field.kind == FieldKind::U32 && field.fixed_width == 4) ); let ack = descriptor_by_name("PacketAck").unwrap(); assert_eq!(ack.id, 0xfffb); assert_eq!(ack.frequency, PacketFrequency::Low); assert_eq!(ack.blocks[0].repetition, BlockRepetition::Variable); assert_eq!(ack.blocks[0].fields[0].kind, FieldKind::U32); let object_update = descriptor_by_name("ObjectUpdate").unwrap(); assert!(object_update.zerocoded); assert!(object_update.trusted); assert!( object_update .blocks .iter() .flat_map(|block| block.fields) .any(|field| field.kind == FieldKind::Fixed) ); } #[test] fn generated_constructors_initialize_blocks_headers_and_sizing_metadata() { let test = TestMessagePacket::new_with_constructor().unwrap(); assert_eq!(test.base.type_, PacketType::TestMessage); assert_eq!(test.base.header.frequency, PacketFrequency::Low); assert_eq!(test.base.header.id, 1); assert!(test.base.header.reliable); assert!(test.base.header.zerocoded); assert_eq!(test.neighbor_block.len(), 4); assert_eq!(test.length(), 62); assert!(test.uses_buffer_pooling()); let ack = PacketAckPacket::new_with_constructor().unwrap(); assert!(ack.packets.is_empty()); // The low-frequency header contributes ten bytes and the empty variable // block contributes its single count byte. assert_eq!(ack.length(), 11); assert!(!ack.uses_buffer_pooling()); let circuit = UseCircuitCodePacket::new_with_constructor().unwrap(); assert_eq!(circuit.circuit_code.code, 0); assert_eq!(circuit.circuit_code.id, libremetaverse_types::UUID::zero()); assert_eq!( circuit.circuit_code.session_id, libremetaverse_types::UUID::zero() ); assert_eq!(circuit.length(), 46); assert!(circuit.uses_buffer_pooling()); } #[test] fn generated_dispatch_handles_known_and_unknown_packets_without_fallbacks() { let packet = Packet::build_packet_with_packet_type(PacketType::UseCircuitCode).unwrap(); assert_eq!(packet.type_, PacketType::UseCircuitCode); assert_eq!(packet.header.frequency, PacketFrequency::Low); assert_eq!(packet.header.id, 3); assert!(packet.header.reliable); assert!(!packet.header.zerocoded); assert!(!packet.has_variable_blocks); assert_eq!( Packet::get_type(u16::MAX, PacketFrequency::High).unwrap(), PacketType::Default ); assert!(matches!( Packet::build_packet_with_packet_type(PacketType::Default), Err(libremetaverse::Error::InvalidOperation) )); assert_eq!(descriptor_by_name("NotAPacket"), None); assert_eq!(descriptor_by_type(PacketType::Default), None); }