Implement parsing of data_version in nearest tests

This commit is contained in:
Dennis 2024-06-05 18:26:39 +02:00
parent f1ad997a4b
commit 9003881a77
No known key found for this signature in database
GPG Key ID: 6937EAEA33A3FA5D
3 changed files with 52 additions and 28 deletions

View File

@ -2,6 +2,7 @@ use std::io::{self, Write};
use cucumber::{cli, event, parser, Event}; use cucumber::{cli, event, parser, Event};
// TODO: add colors // TODO: add colors
// TODO: print summary at the end
pub struct DotWriter; pub struct DotWriter;
impl<W: 'static> cucumber::Writer<W> for DotWriter { impl<W: 'static> cucumber::Writer<W> for DotWriter {

View File

@ -8,7 +8,6 @@ pub struct Waypoint {
pub distance: f64, pub distance: f64,
pub name: String, pub name: String,
location: [f64; 2], location: [f64; 2],
pub data_version: Option<String>,
} }
impl Waypoint { impl Waypoint {
@ -21,4 +20,5 @@ impl Waypoint {
pub struct NearestResponse { pub struct NearestResponse {
pub code: String, pub code: String,
pub waypoints: Vec<Waypoint>, pub waypoints: Vec<Waypoint>,
pub data_version: Option<String>,
} }

View File

@ -48,10 +48,14 @@ fn set_node_locations(world: &mut OSRMWorld, step: &Step) {
"first column needs to be 'node' indicating the one-letter name" "first column needs to be 'node' indicating the one-letter name"
); );
// the following lookup allows to define lat lon columns in any order // the following lookup allows to define lat lon columns in any order
let lat_lon_lookup = HashMap::from([(header[1].clone(), 1), (header[2].clone(), 2)]); let header_lookup: HashMap<&str, usize> = header
.into_iter()
.enumerate()
.map(|(index, name)| (name.as_str(), index))
.collect();
["lat", "lon"].iter().for_each(|dim| { ["lat", "lon"].iter().for_each(|dim| {
assert!( assert!(
lat_lon_lookup.contains_key(*dim), header_lookup.contains_key(*dim),
"table must define a {dim} column" "table must define a {dim} column"
); );
}); });
@ -60,8 +64,8 @@ fn set_node_locations(world: &mut OSRMWorld, step: &Step) {
assert_eq!(3, row.len()); assert_eq!(3, row.len());
assert_eq!(row[0].len(), 1, "node name not in [0..9][a..z]"); assert_eq!(row[0].len(), 1, "node name not in [0..9][a..z]");
let name = &row[0].chars().next().expect("node name cannot be empty"); // the error is unreachable let name = &row[0].chars().next().expect("node name cannot be empty"); // the error is unreachable
let lon = &row[lat_lon_lookup["lon"]]; let lon = &row[header_lookup["lon"]];
let lat = &row[lat_lon_lookup["lat"]]; let lat = &row[header_lookup["lat"]];
let location = point!(x: lon.parse::<f64>().expect("lon {lon} needs to be a f64"), y: lat.parse::<f64>().expect("lat {lat} needs to be a f64")); let location = point!(x: lon.parse::<f64>().expect("lon {lon} needs to be a f64"), y: lat.parse::<f64>().expect("lat {lat} needs to be a f64"));
match name { match name {
'0'...'9' => world.add_location(*name, location), '0'...'9' => world.add_location(*name, location),
@ -179,24 +183,24 @@ fn request_nearest(world: &mut OSRMWorld, step: &Step) {
} }
// parse query data // parse query data
let t = &step.table.as_ref().expect("no query table specified"); let table = &step.table.as_ref().expect("no query table specified");
let test_cases: Vec<_> = t // the following lookup allows to define lat lon columns in any order
let header = table.rows.first().expect("node locations table empty");
// TODO: move to common functionality
let test_cases: Vec<_> = table
.rows .rows
.iter() .iter()
.skip(1) .skip(1)
.map(|row| { .map(|row| {
assert!( let row_map: HashMap<String, String> = row
row.len() >= 2, .iter()
"test case broken: row needs to have at least two entries. One for query input, one for expected result" .enumerate()
); .map(|(column_index, value)| {
let query = row.first().unwrap(); let key = header[column_index].clone();
let expected = row.get(1).unwrap(); (key, value.clone())
assert_eq!(query.len(), 1); })
assert_eq!(expected.len(), 1); .collect();
( row_map
query.chars().next().unwrap(),
expected.chars().next().unwrap(),
)
}) })
.collect(); .collect();
@ -215,9 +219,23 @@ fn request_nearest(world: &mut OSRMWorld, step: &Step) {
.build(); .build();
// parse and run test cases // parse and run test cases
for (query, expected) in test_cases { for test_case in test_cases {
let query_location = world.get_location(query); let query_location = world.get_location(
let expected_location = world.get_location(expected); test_case
.get("in")
.expect("node name is one char long")
.chars()
.next()
.expect("node name is one char long"),
);
let expected_location = world.get_location(
test_case
.get("out")
.expect("node name is one char long")
.chars()
.next()
.expect("node name is one char long"),
);
// debug!("{query_location:?} => {expected_location:?}"); // debug!("{query_location:?} => {expected_location:?}");
// run queries // run queries
@ -235,15 +253,20 @@ fn request_nearest(world: &mut OSRMWorld, step: &Step) {
}; };
// debug!("body: {body}"); // debug!("body: {body}");
let v: NearestResponse = match serde_json::from_str(&body) { let response: NearestResponse = match serde_json::from_str(&body) {
Ok(v) => v, Ok(response) => response,
Err(e) => panic!("parsing error {e}"), Err(e) => panic!("parsing error {e}"),
}; };
let result_location = v.waypoints[0].location(); if test_case.contains_key("out") {
// check results // check that result node is (approximately) equivalent
assert!(approx_equal(result_location.x(), expected_location.x(), 5)); let result_location = response.waypoints[0].location();
assert!(approx_equal(result_location.y(), expected_location.y(), 5)); assert!(approx_equal(result_location.x(), expected_location.x(), 5));
assert!(approx_equal(result_location.y(), expected_location.y(), 5));
}
if test_case.contains_key("data_version") {
assert_eq!(test_case.get("data_version"), response.data_version.as_ref());
}
} }
} }