//! End-to-end step-3 test: import the fixtures, then route LFPG→EGLL through the //! hand-made airway network and check the result is sensible. use std::path::PathBuf; use flightplanner_core::routing::graph::RouteGraph; use flightplanner_core::{db, routing}; use rusqlite::Connection; fn fixtures_dir() -> PathBuf { PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("tests/fixtures") } fn fixtures_db() -> Connection { let mut conn = Connection::open_in_memory().unwrap(); db::import_navdata(&mut conn, &fixtures_dir()).unwrap(); conn } #[test] fn routes_lfpg_to_egll_via_airways() { let conn = fixtures_db(); let route = routing::plan_route(&conn, "LFPG", "EGLL", None).unwrap(); assert!(route.via_airways, "expected an airway route, got {route:?}"); assert_eq!(route.legs.first().unwrap().from, "LFPG"); assert_eq!(route.legs.last().unwrap().to, "EGLL"); // The fixture network forces travel over the T100/U200 airways. let airways: Vec<&str> = route.legs.iter().map(|l| l.airway.as_str()).collect(); assert!( airways.iter().any(|a| *a != "DCT"), "route used no airway: {airways:?}" ); // Sanity on total distance (direct LFPG-EGLL ≈ 188 nm; via fixtures a bit more). assert!( route.total_nm > 150.0 && route.total_nm < 400.0, "total = {} nm", route.total_nm ); } #[test] fn unknown_airport_is_reported() { let conn = fixtures_db(); let err = routing::plan_route(&conn, "LFPG", "ZZZZ", None).unwrap_err(); assert!(err.to_string().contains("ZZZZ"), "{err}"); } #[test] fn graph_filters_airways_by_flight_level() { let conn = fixtures_db(); // Fixtures: T100 (low, FL35..245) links ABEAM/BEACN/CROSS, // U200 (high, FL245..460) links CROSS/DOVER/ENTRY. assert_eq!(RouteGraph::build(&conn, None).unwrap().node_count(), 5); assert_eq!(RouteGraph::build(&conn, Some(200)).unwrap().node_count(), 3); // T100 only assert_eq!(RouteGraph::build(&conn, Some(300)).unwrap().node_count(), 3); // U200 only assert_eq!(RouteGraph::build(&conn, Some(500)).unwrap().node_count(), 0); // above both } #[test] fn fra_produces_a_dct_chain() { let conn = fixtures_db(); let route = routing::fra::plan_fra(&conn, "LFPG", "EGLL", &[], &[], 360, None).unwrap(); assert!(!route.via_airways, "FRA is DCT-based: {route:?}"); assert!(route.legs.iter().all(|l| l.airway == "DCT"), "{route:?}"); assert_eq!(route.legs.first().unwrap().from, "LFPG"); assert_eq!(route.legs.last().unwrap().to, "EGLL"); assert!( route.total_nm > 150.0 && route.total_nm < 400.0, "total = {} nm", route.total_nm ); } #[test] fn connects_departure_via_given_fix() { let conn = fixtures_db(); // Force LFPG to join the network at CROSS (a SID exit fix, say) rather than // the nearest airway point. let route = routing::plan_route_conn(&conn, "LFPG", "EGLL", None, &["CROSS".to_string()], &[]).unwrap(); assert!(route.via_airways, "{route:?}"); let first = route.legs.first().unwrap(); assert_eq!(first.from, "LFPG"); assert_eq!(first.to, "CROSS", "should connect via the given fix: {route:?}"); }