use mavinspect::parser::errors::XmlInspectionError; use mavinspect::parser::Inspector; use mavinspect::protocol::Microservices; fn default_dialect_paths() -> Vec<&'static str> { vec![ "./message_definitions/standard", "./message_definitions/extra", ] } fn extra_dialect_paths() -> Vec<&'static str> { vec!["./message_definitions/extra"] } #[test] fn naming_collisions_are_avoided() { use mavinspect::errors::Error; let inspector = Inspector::builder() .set_sources(&["./message_definitions/colliding"]) .build(); assert!( inspector.is_err(), "XMLInspector should recognize naming collisions" ); assert!(matches!( inspector, Err(Error::Inspection( XmlInspectionError::NamingCollision { .. } )) )) } #[test] fn wrong_paths_do_not_cause_panic() { use mavinspect::errors::Error; let paths = vec![ "./message_definitions/invalid", // Non-existing "./message_definitions/standard", ]; let inspector = Inspector::builder().set_sources(&paths).build(); assert!( inspector.is_err(), "XMLInspector should return error for non-existing paths" ); assert!(matches!(inspector, Err(Error::Io(_)))) } #[test] fn empty_paths_do_not_cause_errors() { let inspector = Inspector::builder() .set_sources(&[ "./tests", // Clearly don't have any definitions "./message_definitions/standard", ]) .build(); assert!( inspector.is_ok(), "XMLInspector should non return error for paths without definitions" ); } #[test] fn xml_definitions_are_loaded() { let inspector = Inspector::builder() .set_sources(&default_dialect_paths()) .build(); assert!(inspector.is_ok(), "failed to instantiate XMLInspector"); let inspector = inspector.unwrap(); assert!(!inspector.definitions().is_empty(), "no definitions loaded"); } #[test] fn default_message_definitions_are_parsed() { let inspector = Inspector::builder() .set_sources(&default_dialect_paths()) .build() .unwrap(); let protocol = inspector.parse(); assert!( protocol.is_ok(), "failed to instantiate XMLInspector: {:?}", protocol ); let protocol = protocol.unwrap(); // Check that some dialects are parsed assert!(!protocol.dialects_are_empty(), "no dialects parsed"); // Check that minimal dialect is parsed assert!( protocol.get_dialect_by_canonical_name("minimal").is_some(), "`minimal` dialect should be parsed" ); } #[test] fn default_minimal_dialect_is_parsed_correctly() { let inspector = Inspector::builder() .set_sources(&default_dialect_paths()) .build() .unwrap(); let protocol = inspector.parse().unwrap(); let minimal = protocol.get_dialect_by_canonical_name("minimal").unwrap(); assert_eq!(minimal.name(), "minimal", "incorrect dialect name"); assert!( minimal.contains_enum_with_name("MAV_AUTOPILOT"), "`minimal` dialect should contain `MAV_AUTOPILOT` enum" ); assert!( minimal.contains_message_with_id(0u32), "`minimal` dialect should contain `HEARTBEAT` message" ); assert_eq!( minimal.get_message_by_id(0u32).unwrap().name(), "HEARTBEAT", "`minimal` dialect should contain `HEARTBEAT` message" ); assert!( minimal.get_message_by_id(300u32).is_some(), "`minimal` dialect should contain `PROTOCOL_VERSION` message" ); assert_eq!( minimal.get_message_by_id(300u32).unwrap().name(), "PROTOCOL_VERSION", "`minimal` dialect should contain `PROTOCOL_VERSION` message" ); } #[test] fn custom_dialect() { let inspector = Inspector::builder() .set_sources(&extra_dialect_paths()) .set_include(&["crazy_flight"]) .build() .unwrap(); let protocol = inspector.parse().unwrap(); let dialect = protocol .get_dialect_by_canonical_name("crazy_flight") .unwrap(); assert!(dialect.version().is_some()); assert!(matches!(dialect.version(), Some(3))); assert!(dialect.contains_enum_with_name("CRAZYFLIGHT_INSANITY_LEVEL")); assert!(dialect.contains_enum_with_name("CRAZYFLIGHT_DEED_FLAGS")); let mav_enum = dialect .get_enum_by_name("CRAZYFLIGHT_INSANITY_LEVEL") .unwrap(); assert_eq!(mav_enum.entries().len(), 3); let mav_bitmask = dialect.get_enum_by_name("CRAZYFLIGHT_DEED_FLAGS").unwrap(); assert_eq!(mav_bitmask.entries().len(), 3); assert!(mav_bitmask.bitmask()); } #[test] fn microservices_flags() { let inspector = Inspector::builder() .set_sources(&default_dialect_paths()) .set_include(&["crazy_flight", "common"]) .build() .unwrap(); let protocol = inspector.parse().unwrap(); let dialect = protocol .get_dialect_by_canonical_name("crazy_flight") .unwrap(); assert!(dialect.microservices().contains(Microservices::HEARTBEAT)); let dialect = protocol.get_dialect_by_canonical_name("common").unwrap(); assert!(dialect.microservices().contains(Microservices::HEARTBEAT)); assert!(dialect.microservices().contains(Microservices::COMMAND)); assert!(dialect.microservices().contains(Microservices::MISSION)); assert!(dialect.microservices().contains(Microservices::PARAMETER)); }