use tp_lib_core::{
GnssPosition, NetRelation, Netelement, ProjectedPosition, ProjectionConfig, ProjectionError,
RailwayNetwork,
};
#[test]
fn test_gnss_position_contract() {
use chrono::{FixedOffset, TimeZone};
use std::collections::HashMap;
let tz = FixedOffset::east_opt(3600).unwrap();
let dt = tz.with_ymd_and_hms(2024, 1, 15, 10, 30, 0).unwrap();
let pos = GnssPosition {
latitude: 50.8503,
longitude: 4.3517,
timestamp: dt,
crs: "EPSG:4326".to_string(),
metadata: HashMap::new(),
heading: None,
distance: None,
};
assert_eq!(pos.latitude, 50.8503);
assert_eq!(pos.longitude, 4.3517);
assert_eq!(pos.crs, "EPSG:4326");
assert!(pos.metadata.is_empty());
}
#[test]
fn test_netelement_contract() {
use geo::{CoordsIter, LineString};
let geom = LineString::from(vec![(4.35, 50.85), (4.36, 50.86)]);
let ne = Netelement {
id: "NE001".to_string(),
geometry: geom.clone(),
crs: "EPSG:4326".to_string(),
};
assert_eq!(ne.id, "NE001");
assert_eq!(ne.crs, "EPSG:4326");
assert_eq!(ne.geometry.coords_count(), 2);
}
#[test]
fn test_projected_position_contract() {
use chrono::{FixedOffset, TimeZone};
use geo::Point;
use std::collections::HashMap;
let tz = FixedOffset::east_opt(3600).unwrap();
let dt = tz.with_ymd_and_hms(2024, 1, 15, 10, 30, 0).unwrap();
let original = GnssPosition {
latitude: 50.8503,
longitude: 4.3517,
timestamp: dt,
crs: "EPSG:4326".to_string(),
metadata: HashMap::new(),
heading: None,
distance: None,
};
let proj = ProjectedPosition {
original,
projected_coords: Point::new(4.3517, 50.8503),
netelement_id: "NE001".to_string(),
measure_meters: 123.45,
projection_distance_meters: 2.5,
crs: "EPSG:4326".to_string(),
intrinsic: None,
};
assert_eq!(proj.netelement_id, "NE001");
assert_eq!(proj.measure_meters, 123.45);
assert_eq!(proj.projection_distance_meters, 2.5);
assert_eq!(proj.crs, "EPSG:4326");
}
#[test]
fn test_projection_config_contract() {
let config = ProjectionConfig::default();
assert_eq!(config.projection_distance_warning_threshold, 50.0);
assert!(!config.suppress_warnings);
let custom = ProjectionConfig {
projection_distance_warning_threshold: 100.0,
suppress_warnings: true,
};
assert_eq!(custom.projection_distance_warning_threshold, 100.0);
assert!(custom.suppress_warnings);
}
#[test]
fn test_projection_error_contract() {
use std::fmt::Write;
let errors = vec![
ProjectionError::InvalidCrs("test".to_string()),
ProjectionError::TransformFailed("test".to_string()),
ProjectionError::InvalidCoordinate("test".to_string()),
ProjectionError::MissingTimezone("test".to_string()),
ProjectionError::InvalidTimestamp("test".to_string()),
ProjectionError::EmptyNetwork,
ProjectionError::InvalidGeometry("test".to_string()),
ProjectionError::GeoJsonError("test".to_string()),
];
for err in errors {
let mut msg = String::new();
write!(&mut msg, "{}", err).unwrap();
assert!(!msg.is_empty(), "Error message should not be empty");
}
}
#[test]
fn test_railway_network_contract() {
use geo::LineString;
let geom = LineString::from(vec![(4.35, 50.85), (4.36, 50.86)]);
let ne = Netelement {
id: "NE001".to_string(),
geometry: geom,
crs: "EPSG:4326".to_string(),
};
let network = RailwayNetwork::new(vec![ne]).unwrap();
use geo::Point;
let point = Point::new(4.355, 50.855);
let nearest = network.find_nearest(&point);
assert!(nearest.is_ok());
}
#[test]
fn test_project_gnss_contract() {
use chrono::{FixedOffset, TimeZone};
use geo::LineString;
use std::collections::HashMap;
let tz = FixedOffset::east_opt(3600).unwrap();
let dt = tz.with_ymd_and_hms(2024, 1, 15, 10, 30, 0).unwrap();
let pos = GnssPosition {
latitude: 50.8503,
longitude: 4.3517,
timestamp: dt,
crs: "EPSG:4326".to_string(),
metadata: HashMap::new(),
heading: None,
distance: None,
};
let geom = LineString::from(vec![(4.35, 50.85), (4.36, 50.86)]);
let ne = Netelement {
id: "NE001".to_string(),
geometry: geom,
crs: "EPSG:4326".to_string(),
};
let network = RailwayNetwork::new(vec![ne]).unwrap();
let config = ProjectionConfig::default();
let result = tp_lib_core::project_gnss(&[pos], &network, &config);
assert!(result.is_ok());
let projected = result.unwrap();
assert_eq!(projected.len(), 1);
}
#[test]
fn test_io_functions_contract() {
fn _check_parse_gnss_csv() -> Result<Vec<GnssPosition>, ProjectionError> {
tp_lib_core::parse_gnss_csv(
"dummy.csv",
"EPSG:4326",
"latitude",
"longitude",
"timestamp",
)
}
fn _check_parse_gnss_geojson() -> Result<Vec<GnssPosition>, ProjectionError> {
tp_lib_core::parse_gnss_geojson("dummy.geojson", "EPSG:4326")
}
fn _check_parse_network_geojson() -> Result<(Vec<Netelement>, Vec<NetRelation>), ProjectionError>
{
tp_lib_core::parse_network_geojson("dummy.geojson")
}
fn _check_write_csv<W: std::io::Write>(
projected: &[ProjectedPosition],
writer: &mut W,
) -> Result<(), ProjectionError> {
tp_lib_core::write_csv(projected, writer)
}
fn _check_write_geojson<W: std::io::Write>(
projected: &[ProjectedPosition],
writer: &mut W,
) -> Result<(), ProjectionError> {
tp_lib_core::write_geojson(projected, writer)
}
}