From fe8a1348972e80b1f3498ad9e6fbde528913f9d4 Mon Sep 17 00:00:00 2001 From: Valmo Trindade <70849974+valmojr@users.noreply.github.com> Date: Fri, 7 Aug 2026 14:25:37 -0300 Subject: [PATCH] Add comprehensive unit coverage for UAS CoT payloads --- src/cot/uas.rs | 128 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) diff --git a/src/cot/uas.rs b/src/cot/uas.rs index 3ca6e66..d1d2a49 100644 --- a/src/cot/uas.rs +++ b/src/cot/uas.rs @@ -328,3 +328,131 @@ impl UasSensorCoTPayload { xml } } + +#[cfg(test)] +mod tests { + use super::{ + escape_xml, parse_rtsp_url, UasPlatformCoTPayload, UasSensorCoTPayload, + UasVideoCoTPayload, + }; + use arma_rs::FromArma; + + #[test] + fn escapes_uas_xml_values_and_parses_rtsp_components() { + assert_eq!(escape_xml("A&B\"'"), "A&B"<C>'"); + assert_eq!( + parse_rtsp_url("rtsp://video.example.test:8554/live/main"), + Some(( + "video.example.test".to_string(), + "8554".to_string(), + "/live/main".to_string(), + )) + ); + assert!(parse_rtsp_url("https://video.example.test:8554/live").is_none()); + assert!(parse_rtsp_url("rtsp://video.example.test:8554").is_none()); + assert!(parse_rtsp_url("rtsp://video.example.test/live").is_none()); + } + + #[test] + fn parses_and_serializes_uas_platform_with_embedded_video_url() { + let payload = UasPlatformCoTPayload::from_arma( + r#"["uas<&","a-f-A-M-F-Q","Falcon<&",-30.1,-51.2,100,180,12.5,90,-15,60,40,1200,181,2.5,1.5,3.2,"Quad<&|armatak_video_url=rtsp://video.example.test:8554/live",1,"operator<&"]"# + .to_string(), + ) + .expect("UAS platform payload should parse"); + + assert_eq!(payload.uid, "uas<&"); + assert_eq!(payload.vehicle_type_tag, "Quad<&|armatak_video_url=rtsp://video.example.test:8554/live"); + + let xml = payload.to_xml(); + assert!(xml.contains("uid=\"uas<&\"")); + assert!(xml.contains("typeTag=\"Quad<&\"")); + assert!(xml.contains("isFlying=\"true\"")); + assert!(xml.contains("")); + assert!(xml.contains("")); + assert!(xml.contains("<_route sender=\"operator<&\"/>")); + assert!(xml.contains("")); + } + + #[test] + fn parses_and_serializes_standalone_uas_video_event() { + let payload = UasVideoCoTPayload::from_arma( + r#"["video<&","Falcon<&","rtsp://video.example.test:8554/live/main"]"# + .to_string(), + ) + .expect("UAS video payload should parse"); + + let xml = payload.to_xml(); + assert!(xml.contains("type=\"b-i-v\"")); + assert!(xml.contains("uid=\"video<&\"")); + assert!(xml.contains("path=\"/live/main\"")); + assert!(xml.contains("address=\"video.example.test\"")); + assert!(xml.contains("port=\"8554\"")); + assert!(xml.contains("alias=\"Falcon<&\"")); + } + + #[test] + fn rejects_invalid_uas_video_url() { + let payload = UasVideoCoTPayload { + uid: "video-2".to_string(), + callsign: "Raven".to_string(), + video_url: "https://video.example.test/live".to_string(), + }; + + assert_eq!(payload.to_xml(), ""); + } + + #[test] + fn parses_and_serializes_uas_sensor_event() { + let payload = UasSensorCoTPayload::from_arma( + r#"["sensor<&","video<&","Sensor<&",-30.1,-51.2,25,270,45,850]"# + .to_string(), + ) + .expect("UAS sensor payload should parse"); + + let xml = payload.to_xml(); + assert!(xml.contains("type=\"b-m-p-s-p-loc\"")); + assert!(xml.contains("uid=\"sensor<&\"")); + assert!(xml.contains("lat=\"-30.1\" lon=\"-51.2\" hae=\"25\"")); + assert!(xml.contains("fov=\"45\"")); + assert!(xml.contains("range=\"850\"")); + assert!(xml.contains("azimuth=\"270\"")); + assert!(xml.contains("<__video uid=\"video<&\"/>")); + assert!(xml.contains("")); + } +}