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", "./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", "./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();
assert!(!protocol.dialects_are_empty(), "no dialects parsed");
assert!(
protocol.get_dialect_by_canonical_name("minimal").is_some(),
"`minimal` dialect should be parsed"
);
assert!(
protocol.get_dialect_by_canonical_name("common").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 enums_are_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();
let mav_autopilot = minimal
.get_enum_by_name("MAV_AUTOPILOT")
.expect("`MAV_AUTOPILOT` enum not found in `minimal` dialect");
assert!(
mav_autopilot.entries().len() > 10,
"incorrect number of entries in `MAV_AUTOPILOT` enum"
);
assert_eq!(
mav_autopilot.entries().first().unwrap().name(),
"MAV_AUTOPILOT_GENERIC"
);
assert_eq!(mav_autopilot.entries().first().unwrap().value(), 0);
assert_eq!(
mav_autopilot.entries().get(8).unwrap().name(),
"MAV_AUTOPILOT_INVALID"
);
assert_eq!(mav_autopilot.entries().get(8).unwrap().value(), 8);
let mav_inspect_test = protocol.get_dialect_by_canonical_name("mav_inspect_test").unwrap();
let large_enum = mav_inspect_test
.get_enum_by_name("LARGE_ENUM")
.expect("`LARGE_ENUM` enum not found in `MAVInspect_test` dialect");
assert_eq!(large_enum.entries().len(), 4, "incorrect number of entries in `LARGE_ENUM` enum");
assert_eq!(
large_enum.entries().first().unwrap().name(),
"LARGE_ENUM_FIRST"
);
assert_eq!(large_enum.entries().first().unwrap().value(), 0);
assert_eq!(
large_enum.entries().get(1).unwrap().name(),
"LARGE_ENUM_SECOND"
);
assert_eq!(large_enum.entries().get(1).unwrap().value(), 256);
}
#[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));
}
#[test]
fn test_default_dialects() {
let inspector = Inspector::builder()
.set_sources(&default_dialect_paths())
.set_include(&["crazy_flight", "common"])
.build()
.unwrap();
let protocol = inspector.parse().unwrap().with_default_dialect("common");
let default_dialect = protocol.default_dialect().unwrap();
assert_eq!(default_dialect.name(), "common");
}
#[test]
fn test_dialect_names_discovery() {
let dialect_names = Inspector::discover_dialect_names(&default_dialect_paths()).unwrap();
assert!(dialect_names.contains(&"common".to_string()));
assert!(dialect_names.contains(&"ASLUAV".to_string()));
assert!(dialect_names.contains(&"MAVInspect_test".to_string()));
}
#[test]
fn test_dialect_canonical_names_discovery() {
let dialect_names =
Inspector::discover_dialect_canonical_names(&default_dialect_paths()).unwrap();
assert!(dialect_names.contains(&"common".to_string()));
assert!(dialect_names.contains(&"asluav".to_string()));
assert!(dialect_names.contains(&"mav_inspect_test".to_string()));
}