use std::io::Cursor;
use indoc::indoc;
use insta::assert_debug_snapshot;
use openair::*;
#[test]
fn test_switzerland_fixture() {
let airspace = include_bytes!("../example_data/Switzerland.txt");
let mut cursor = Cursor::new(airspace);
let spaces = parse(&mut cursor).collect::<Result<Vec<_>, _>>().unwrap();
assert_debug_snapshot!(spaces.first().unwrap());
let names = spaces.iter().map(|a| a.to_string()).collect::<Vec<_>>();
assert_debug_snapshot!(names);
}
#[test]
fn test_germany_fixture() {
let airspace = include_bytes!("../example_data/Germany.txt");
let mut cursor = Cursor::new(airspace);
let spaces = parse(&mut cursor).collect::<Result<Vec<_>, _>>().unwrap();
assert_debug_snapshot!(spaces.first().unwrap());
let names = spaces.iter().map(|a| a.to_string()).collect::<Vec<_>>();
assert_debug_snapshot!(names);
}
#[test]
fn test_germany_border_fixture() {
let airspace = include_bytes!("../example_data/Germany_Border.txt");
let mut cursor = Cursor::new(airspace);
let spaces = parse(&mut cursor).collect::<Result<Vec<_>, _>>().unwrap();
assert_debug_snapshot!(spaces.first().unwrap());
let names = spaces.iter().map(|a| a.to_string()).collect::<Vec<_>>();
assert_debug_snapshot!(names);
}
#[test]
fn test_france_fixture() {
let airspace = include_bytes!("../example_data/France.txt");
let mut cursor = Cursor::new(airspace);
let spaces = parse(&mut cursor).collect::<Result<Vec<_>, _>>().unwrap();
assert_debug_snapshot!(spaces.first().unwrap());
assert_debug_snapshot!(spaces.last().unwrap());
let names = spaces.iter().map(|a| a.to_string()).collect::<Vec<_>>();
assert_debug_snapshot!(names);
}
#[test]
fn flyland_buochs() {
let mut airspace = indoc! {"
AC D
AN BUOCHS Be CTR 119.625
AL GND
AH 12959 ft
DP 46:57:13 N 008:27:52 E
DP 46:57:46 N 008:30:41 E
DP 46:57:55 N 008:28:40 E
DP 46:58:28 N 008:27:56 E
DP 46:57:13 N 008:27:52 E
* n-Points: 5
"}
.as_bytes();
let mut spaces = parse(&mut airspace).collect::<Result<Vec<_>, _>>().unwrap();
assert_eq!(spaces.len(), 1);
let space: Airspace = spaces.pop().unwrap();
assert_eq!(space.name.as_deref(), Some("BUOCHS Be CTR 119.625"));
assert_eq!(space.lower_bound, Altitude::Gnd);
assert_eq!(space.upper_bound, Altitude::FeetAmsl(12959));
if let Geometry::Polygon { segments } = space.geom {
assert_eq!(segments.len(), 5);
} else {
panic!("Unexpected enum variant");
}
}
#[test]
fn inverted_bounds() {
let mut a1 = indoc! {"
AC D
AN SOMESPACE
AL GND
AH 12959 ft
DP 46:57:13 N 008:27:52 E
DP 46:57:46 N 008:30:41 E
*
"}
.as_bytes();
let mut a2 = indoc! {"
AC D
AN SOMESPACE
AH 12959 ft
AL GND
DP 46:57:13 N 008:27:52 E
DP 46:57:46 N 008:30:41 E
*
"}
.as_bytes();
let spaces1 = parse(&mut a1).collect::<Result<Vec<_>, _>>().unwrap();
let spaces2 = parse(&mut a2).collect::<Result<Vec<_>, _>>().unwrap();
let space1 = spaces1.last().unwrap();
let space2 = spaces2.last().unwrap();
assert_eq!(space1, space2);
}
#[test]
fn multi_variable() {
let mut a = indoc! {"
AC D
AN SOMESPACE
AL GND
AH FL100
V X=52:00:00N 013:00:00E
V D=+
DA 2,0,30
V X=52:00:00N 013:00:00E
V D=-
DA 4,60,30
*
"}
.as_bytes();
let spaces = parse(&mut a).collect::<Result<Vec<_>, _>>().unwrap();
let airspace = spaces.last().unwrap();
assert_eq!(
airspace.geom,
Geometry::Polygon {
segments: vec![
PolygonSegment::ArcSegment(ArcSegment {
centerpoint: Coord {
lat: 52.0,
lng: 13.0
},
radius: 2.0,
angle_start: 0.0,
angle_end: 30.0,
direction: Direction::Cw,
}),
PolygonSegment::ArcSegment(ArcSegment {
centerpoint: Coord {
lat: 52.0,
lng: 13.0
},
radius: 4.0,
angle_start: 60.0,
angle_end: 30.0,
direction: Direction::Ccw,
}),
],
}
);
}
#[test]
fn extension_records() {
let mut a = indoc! {"
AC D
AN SOMESPACE
AL GND
AH 100 ft AGL
AY AWY
AF 132.350
AG Dutch Mil
AX 1234
A* custom extension
V X=52:00:00 N 013:00:00 E
DC 5
"}
.as_bytes();
let spaces = parse(&mut a).collect::<Result<Vec<_>, _>>().unwrap();
let airspace = spaces.last().unwrap();
assert_eq!(airspace.type_, Some("AWY".to_string()));
assert_eq!(airspace.frequency, Some("132.350".to_string()));
assert_eq!(airspace.call_sign, Some("Dutch Mil".to_string()));
assert_eq!(airspace.transponder_code, Some(1234));
}
#[test]
fn missing_name() {
let mut airspace = indoc! {"
AC D
AL GND
AH 5000 ft
DP 50:00:00 N 010:00:00 E
DP 50:00:00 N 010:01:00 E
DP 50:01:00 N 010:01:00 E
DP 50:01:00 N 010:00:00 E
"}
.as_bytes();
let spaces = parse(&mut airspace).collect::<Result<Vec<_>, _>>().unwrap();
assert_eq!(spaces.len(), 1);
let space = &spaces[0];
assert_eq!(space.name, None);
assert_eq!(space.class, Class::D);
assert_eq!(space.lower_bound, Altitude::Gnd);
assert_eq!(space.upper_bound, Altitude::FeetAmsl(5000));
}
#[test]
fn an_record_as_separator() {
let mut airspace_data = indoc! {"
AN FIRST AIRSPACE
AC D
AL GND
AH 5000 ft
DP 50:00:00 N 010:00:00 E
DP 50:00:00 N 010:01:00 E
DP 50:01:00 N 010:01:00 E
DP 50:01:00 N 010:00:00 E
AN SECOND AIRSPACE
AC R
* Random comment
AL 1000 ft
AH FL100
DP 51:00:00 N 011:00:00 E
DP 51:00:00 N 011:01:00 E
DP 51:01:00 N 011:01:00 E
DP 51:01:00 N 011:00:00 E
"}
.as_bytes();
let spaces = parse(&mut airspace_data)
.collect::<Result<Vec<_>, _>>()
.unwrap();
assert_eq!(
spaces.len(),
2,
"Expected 2 airspaces, got {}",
spaces.len()
);
let first = &spaces[0];
assert_eq!(first.name.as_deref(), Some("FIRST AIRSPACE"));
assert_eq!(first.class, Class::D);
assert_eq!(first.lower_bound, Altitude::Gnd);
assert_eq!(first.upper_bound, Altitude::FeetAmsl(5000));
let second = &spaces[1];
assert_eq!(second.name.as_deref(), Some("SECOND AIRSPACE"));
assert_eq!(second.class, Class::Restricted);
assert_eq!(second.lower_bound, Altitude::FeetAmsl(1000));
assert_eq!(second.upper_bound, Altitude::FlightLevel(100));
}