Implement geometry comparison
This commit is contained in:
parent
85eb7a9383
commit
772f9ccc21
@ -200,7 +200,7 @@ curl 'http://router.project-osrm.org/nearest/v1/driving/13.388860,52.517037?numb
|
|||||||
Finds the fastest route between coordinates in the supplied order.
|
Finds the fastest route between coordinates in the supplied order.
|
||||||
|
|
||||||
```endpoint
|
```endpoint
|
||||||
GET /route/v1/{profile}/{coordinates}?alternatives={true|false|number}&steps={true|false}&geometries={polyline|polyline6|geojson}&overview={full|simplified|false}&annotations={true|false}
|
GET /route/v1/{profile}/{coordinates}?alternatives={true|false|number}&steps={true|false}&geometries={polyline|polyline6|geojson}&overview={full|simplified|false}&annotations={true|false}&continue_straight={default|true|false}
|
||||||
```
|
```
|
||||||
|
|
||||||
In addition to the [general options](#general-options) the following options are supported for this service:
|
In addition to the [general options](#general-options) the following options are supported for this service:
|
||||||
|
@ -29,8 +29,6 @@ module.exports = function () {
|
|||||||
var params = this.paramsToString(parameters);
|
var params = this.paramsToString(parameters);
|
||||||
this.query = baseUri + (params.length ? '/' + params : '');
|
this.query = baseUri + (params.length ? '/' + params : '');
|
||||||
|
|
||||||
console.log(this.query);
|
|
||||||
|
|
||||||
request(this.query, (err, res, body) => {
|
request(this.query, (err, res, body) => {
|
||||||
if (err && err.code === 'ECONNREFUSED') {
|
if (err && err.code === 'ECONNREFUSED') {
|
||||||
return cb(new Error('*** osrm-routed is not running.'));
|
return cb(new Error('*** osrm-routed is not running.'));
|
||||||
|
@ -24,7 +24,7 @@ impl LocalTask {
|
|||||||
// TODO: also check that process is running
|
// TODO: also check that process is running
|
||||||
self.ready
|
self.ready
|
||||||
}
|
}
|
||||||
pub fn arg(&mut self, argument: &str) -> &mut Self {
|
pub fn arg(mut self, argument: &str) -> Self {
|
||||||
self.arguments.push(argument.into());
|
self.arguments.push(argument.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ pub struct OSRMWorld {
|
|||||||
pub extraction_parameters: Vec<String>,
|
pub extraction_parameters: Vec<String>,
|
||||||
|
|
||||||
pub request_with_flatbuffers: bool,
|
pub request_with_flatbuffers: bool,
|
||||||
pub bearings: Option<String>,
|
pub query_options: HashMap<String, String>,
|
||||||
|
|
||||||
pub grid_size: f32,
|
pub grid_size: f32,
|
||||||
pub origin: Location,
|
pub origin: Location,
|
||||||
@ -60,7 +60,13 @@ impl Default for OSRMWorld {
|
|||||||
osm_db: Default::default(),
|
osm_db: Default::default(),
|
||||||
extraction_parameters: Default::default(),
|
extraction_parameters: Default::default(),
|
||||||
request_with_flatbuffers: Default::default(),
|
request_with_flatbuffers: Default::default(),
|
||||||
bearings: None,
|
query_options: HashMap::from([
|
||||||
|
// default parameters // TODO: check if necessary
|
||||||
|
("steps".into(), "true".into()),
|
||||||
|
("alternatives".into(), "false".into()),
|
||||||
|
("annotations".into(), "true".into()),
|
||||||
|
]),
|
||||||
|
|
||||||
grid_size: DEFAULT_GRID_SIZE,
|
grid_size: DEFAULT_GRID_SIZE,
|
||||||
origin: DEFAULT_ORIGIN,
|
origin: DEFAULT_ORIGIN,
|
||||||
way_spacing: WAY_SPACING,
|
way_spacing: WAY_SPACING,
|
||||||
@ -206,9 +212,7 @@ impl OSRMWorld {
|
|||||||
.artefact_cache_path()
|
.artefact_cache_path()
|
||||||
.join(self.scenario_id.to_owned() + ".osrm");
|
.join(self.scenario_id.to_owned() + ".osrm");
|
||||||
|
|
||||||
// TODO: this should not require a temporary and behave like the API of std::process
|
self.task = LocalTask::new(self.routed_path().to_string_lossy().into())
|
||||||
self.task = LocalTask::new(self.routed_path().to_string_lossy().into());
|
|
||||||
self.task
|
|
||||||
.arg(data_path.to_str().expect("data path unwrappable"));
|
.arg(data_path.to_str().expect("data path unwrappable"));
|
||||||
self.task
|
self.task
|
||||||
.spawn_wait_till_ready("running and waiting for requests");
|
.spawn_wait_till_ready("running and waiting for requests");
|
||||||
@ -229,6 +233,19 @@ impl OSRMWorld {
|
|||||||
if self.request_with_flatbuffers {
|
if self.request_with_flatbuffers {
|
||||||
url += ".flatbuffers";
|
url += ".flatbuffers";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !self.query_options.is_empty() {
|
||||||
|
let options = self
|
||||||
|
.query_options
|
||||||
|
.iter()
|
||||||
|
.map(|(key, value)| format!("{key}={value}"))
|
||||||
|
.collect::<Vec<String>>()
|
||||||
|
.join("&");
|
||||||
|
url += "?";
|
||||||
|
url += &options;
|
||||||
|
}
|
||||||
|
|
||||||
|
// panic!("url: {url}");
|
||||||
let call = self.agent.get(&url).call();
|
let call = self.agent.get(&url).call();
|
||||||
|
|
||||||
let body = match call {
|
let body = match call {
|
||||||
@ -253,15 +270,21 @@ impl OSRMWorld {
|
|||||||
.join(";");
|
.join(";");
|
||||||
|
|
||||||
let mut url = format!(
|
let mut url = format!(
|
||||||
"http://localhost:5000/route/v1/{}/{waypoint_string}?steps=true&alternatives=false",
|
"http://localhost:5000/route/v1/{}/{waypoint_string}",
|
||||||
self.profile,
|
self.profile,
|
||||||
);
|
);
|
||||||
if self.request_with_flatbuffers {
|
if self.request_with_flatbuffers {
|
||||||
url += ".flatbuffers";
|
url += ".flatbuffers";
|
||||||
}
|
}
|
||||||
if let Some(bearings) = &self.bearings {
|
if !self.query_options.is_empty() {
|
||||||
url += "&bearings=";
|
let options = self
|
||||||
url += bearings;
|
.query_options
|
||||||
|
.iter()
|
||||||
|
.map(|(key, value)| format!("{key}={value}"))
|
||||||
|
.collect::<Vec<String>>()
|
||||||
|
.join("&");
|
||||||
|
url += "?";
|
||||||
|
url += &options;
|
||||||
}
|
}
|
||||||
// println!("url: {url}");
|
// println!("url: {url}");
|
||||||
let call = self.agent.get(&url).call();
|
let call = self.agent.get(&url).call();
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
use std::default;
|
||||||
|
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
use super::{location::Location, nearest_response::Waypoint};
|
use super::{location::Location, nearest_response::Waypoint};
|
||||||
@ -11,9 +13,25 @@ pub struct Maneuver {
|
|||||||
pub r#type: String, // TODO: should be an enum
|
pub r#type: String, // TODO: should be an enum
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
|
#[serde(untagged)]
|
||||||
|
pub enum Geometry {
|
||||||
|
A(String),
|
||||||
|
B {
|
||||||
|
coordinates: Vec<Location>,
|
||||||
|
r#type: String,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Geometry {
|
||||||
|
fn default() -> Self {
|
||||||
|
Geometry::A("".to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Default, Debug)]
|
#[derive(Deserialize, Default, Debug)]
|
||||||
pub struct Step {
|
pub struct Step {
|
||||||
pub geometry: String,
|
pub geometry: Geometry,
|
||||||
pub mode: String,
|
pub mode: String,
|
||||||
pub maneuver: Maneuver,
|
pub maneuver: Maneuver,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
@ -38,9 +56,9 @@ pub struct Leg {
|
|||||||
// pub annotation: Option<Vec<Annotation>>,
|
// pub annotation: Option<Vec<Annotation>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(Deserialize, Debug, Default)]
|
||||||
pub struct Route {
|
pub struct Route {
|
||||||
pub geometry: String,
|
pub geometry: Geometry,
|
||||||
pub weight: f64,
|
pub weight: f64,
|
||||||
pub duration: f64,
|
pub duration: f64,
|
||||||
pub legs: Vec<Leg>,
|
pub legs: Vec<Leg>,
|
||||||
@ -52,7 +70,7 @@ pub struct Route {
|
|||||||
pub struct RouteResponse {
|
pub struct RouteResponse {
|
||||||
pub code: String,
|
pub code: String,
|
||||||
pub routes: Vec<Route>,
|
pub routes: Vec<Route>,
|
||||||
pub waypoints: Vec<Waypoint>,
|
pub waypoints: Option<Vec<Waypoint>>,
|
||||||
pub data_version: Option<String>,
|
pub data_version: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,7 +84,6 @@ impl RouteResponse {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_string(input: &str) -> Self {
|
pub fn from_string(input: &str) -> Self {
|
||||||
// println!("{input}");
|
|
||||||
let response = match serde_json::from_str(input) {
|
let response = match serde_json::from_str(input) {
|
||||||
Ok(response) => response,
|
Ok(response) => response,
|
||||||
Err(e) => panic!("parsing error {e} => {input}"),
|
Err(e) => panic!("parsing error {e} => {input}"),
|
||||||
@ -74,3 +91,15 @@ impl RouteResponse {
|
|||||||
response
|
response
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #[cfg(test)]
|
||||||
|
// mod tests {
|
||||||
|
// use super::RouteResponse;
|
||||||
|
|
||||||
|
// #[test]
|
||||||
|
// fn parse_geojson() {
|
||||||
|
// let input = r#"{"code":"Ok","routes":[{"geometry":{"coordinates":[[1.00009,1],[1.000269,1]],"type":"LineString"},"weight":1.9,"duration":1.9,"legs":[{"annotation":{"speed":[10.5],"weight":[1.9],"nodes":[1,2],"duration":[1.9],"distance":[19.92332315]},"summary":"abc","weight":1.9,"duration":1.9,"steps":[{"geometry":{"coordinates":[[1.00009,1],[1.000269,1]],"type":"LineString"},"maneuver":{"location":[1.00009,1],"bearing_after":90,"bearing_before":0,"modifier":"right","type":"depart"},"mode":"driving","name":"abc","intersections":[{"out":0,"entry":[true],"bearings":[90],"location":[1.00009,1]}],"driving_side":"right","weight":1.9,"duration":1.9,"distance":19.9},{"geometry":{"coordinates":[[1.000269,1],[1.000269,1]],"type":"LineString"},"maneuver":{"location":[1.000269,1],"bearing_after":0,"bearing_before":90,"modifier":"right","type":"arrive"},"mode":"driving","name":"abc","intersections":[{"in":0,"entry":[true],"bearings":[270],"location":[1.000269,1]}],"driving_side":"right","weight":0,"duration":0,"distance":0}],"distance":19.9}],"weight_name":"duration","distance":19.9}],"waypoints":[{"name":"abc","hint":"AAAAgAEAAIAKAAAAHgAAAAAAAAAoAAAA6kYgQWyG70EAAAAA6kYgQgoAAAAeAAAAAAAAACgAAAABAACAmkIPAEBCDwCaQg8Ai0EPAAAArwUAAAAA","distance":20.01400211,"location":[1.00009,1]},{"name":"abc","hint":"AAAAgAEAAIAdAAAACwAAAAAAAAAoAAAAbIbvQepGIEEAAAAA6kYgQh0AAAALAAAAAAAAACgAAAABAACATUMPAEBCDwBNQw8Ai0EPAAAArwUAAAAA","distance":20.01400211,"location":[1.000269,1]}]} "#;
|
||||||
|
// let result = RouteResponse::from_string(&input);
|
||||||
|
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
@ -12,11 +12,14 @@ use common::{
|
|||||||
location::Location,
|
location::Location,
|
||||||
osm::OSMWay,
|
osm::OSMWay,
|
||||||
osrm_world::OSRMWorld,
|
osrm_world::OSRMWorld,
|
||||||
|
route_response,
|
||||||
};
|
};
|
||||||
use core::panic;
|
use core::panic;
|
||||||
use cucumber::{
|
use cucumber::{
|
||||||
gherkin::{Step, Table},
|
gherkin::{Step, Table},
|
||||||
given, then, when, World, WriterExt,
|
given, then, when,
|
||||||
|
writer::summarize,
|
||||||
|
World, WriterExt,
|
||||||
};
|
};
|
||||||
use futures::{future, FutureExt};
|
use futures::{future, FutureExt};
|
||||||
use geo_types::Point;
|
use geo_types::Point;
|
||||||
@ -48,6 +51,12 @@ fn set_profile(world: &mut OSRMWorld, profile: String) {
|
|||||||
world.profile = profile;
|
world.profile = profile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[given(expr = "the query options")]
|
||||||
|
fn set_query_options(world: &mut OSRMWorld, step: &Step) {
|
||||||
|
let table = parse_option_table(&step.table.as_ref());
|
||||||
|
world.query_options.extend(table.into_iter());
|
||||||
|
}
|
||||||
|
|
||||||
#[given(expr = "the node locations")]
|
#[given(expr = "the node locations")]
|
||||||
fn set_node_locations(world: &mut OSRMWorld, step: &Step) {
|
fn set_node_locations(world: &mut OSRMWorld, step: &Step) {
|
||||||
let table = step.table().expect("cannot get table");
|
let table = step.table().expect("cannot get table");
|
||||||
@ -189,6 +198,19 @@ fn set_ways(world: &mut OSRMWorld, step: &Step) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_option_table(table: &Option<&Table>) -> HashMap<String, String> {
|
||||||
|
let table = table.expect("no query table specified");
|
||||||
|
let result = table
|
||||||
|
.rows
|
||||||
|
.iter()
|
||||||
|
.map(|row| {
|
||||||
|
assert_eq!(2, row.len());
|
||||||
|
(row[0].clone(), row[1].clone())
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
fn parse_table_from_steps(table: &Option<&Table>) -> (Vec<String>, Vec<HashMap<String, String>>) {
|
fn parse_table_from_steps(table: &Option<&Table>) -> (Vec<String>, Vec<HashMap<String, String>>) {
|
||||||
// parse query data
|
// parse query data
|
||||||
let table = table.expect("no query table specified");
|
let table = table.expect("no query table specified");
|
||||||
@ -456,6 +478,15 @@ pub fn get_location_specification(test_case: &HashMap<String, String>) -> Waypoi
|
|||||||
// WaypointsOrLocation::Undefined
|
// WaypointsOrLocation::Undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[given(expr = r"skip waypoints")]
|
||||||
|
fn skip_waypoints(world: &mut OSRMWorld, step: &Step) {
|
||||||
|
// TODO: adapt test to use query options
|
||||||
|
// only used in features/testbot/basic.feature
|
||||||
|
world
|
||||||
|
.query_options
|
||||||
|
.insert("skip_waypoints".into(), "true".into());
|
||||||
|
}
|
||||||
|
|
||||||
#[when(regex = r"^I route( with flatbuffers|) I should get$")]
|
#[when(regex = r"^I route( with flatbuffers|) I should get$")]
|
||||||
fn request_route(world: &mut OSRMWorld, step: &Step, state: String) {
|
fn request_route(world: &mut OSRMWorld, step: &Step, state: String) {
|
||||||
world.request_with_flatbuffers = state == " with flatbuffers";
|
world.request_with_flatbuffers = state == " with flatbuffers";
|
||||||
@ -500,8 +531,11 @@ fn request_route(world: &mut OSRMWorld, step: &Step, state: String) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(bearing) = test_case.get("bearings").cloned() {
|
if let Some(bearings) = test_case.get("bearings").cloned() {
|
||||||
world.bearings = Some(bearing.replace(" ", ";"));
|
// TODO: change test cases to provide proper query options
|
||||||
|
world
|
||||||
|
.query_options
|
||||||
|
.insert("bearings".into(), bearings.replace(" ", ";"));
|
||||||
}
|
}
|
||||||
|
|
||||||
let response = world.route(&waypoints);
|
let response = world.route(&waypoints);
|
||||||
@ -510,7 +544,7 @@ fn request_route(world: &mut OSRMWorld, step: &Step, state: String) {
|
|||||||
.iter()
|
.iter()
|
||||||
.map(|(column_title, expectation)| (column_title.as_str(), expectation.as_str()))
|
.map(|(column_title, expectation)| (column_title.as_str(), expectation.as_str()))
|
||||||
.for_each(|(case, expectation)| match case {
|
.for_each(|(case, expectation)| match case {
|
||||||
"from" | "to" | "bearings"=> {}, // ignore input columns
|
"from" | "to" | "bearings" | "waypoints" | "#" => {}, // ignore input and comment columns
|
||||||
"route" => {
|
"route" => {
|
||||||
let route = if expectation.is_empty() {
|
let route = if expectation.is_empty() {
|
||||||
assert!(response.routes.is_empty());
|
assert!(response.routes.is_empty());
|
||||||
@ -607,9 +641,14 @@ fn request_route(world: &mut OSRMWorld, step: &Step, state: String) {
|
|||||||
.iter()
|
.iter()
|
||||||
.map(|step| {
|
.map(|step| {
|
||||||
let prefix = step.maneuver.r#type.clone();
|
let prefix = step.maneuver.r#type.clone();
|
||||||
|
if prefix == "depart" || prefix == "arrive" {
|
||||||
|
// TODO: this reimplements the behavior that depart and arrive are not checked for their modifier
|
||||||
|
// check if tests shall be adapted, since this is reported by the engine
|
||||||
|
return prefix;
|
||||||
|
}
|
||||||
let suffix = match &step.maneuver.modifier {
|
let suffix = match &step.maneuver.modifier {
|
||||||
Some(modifier) => " ".to_string() + &modifier,
|
Some(modifier) => " ".to_string() + &modifier,
|
||||||
None => "".into(),
|
_ => "".into(),
|
||||||
};
|
};
|
||||||
prefix + &suffix
|
prefix + &suffix
|
||||||
})
|
})
|
||||||
@ -633,10 +672,10 @@ fn request_route(world: &mut OSRMWorld, step: &Step, state: String) {
|
|||||||
// TODO: go over steps
|
// TODO: go over steps
|
||||||
|
|
||||||
let actual_times : Vec<f64>= response.routes.first().expect("no route returned").legs.iter().map(|leg| {
|
let actual_times : Vec<f64>= response.routes.first().expect("no route returned").legs.iter().map(|leg| {
|
||||||
leg.steps.iter().map(|step| step.duration).collect::<Vec<f64>>()
|
leg.steps.iter().filter(|step| step.duration > 0.).map(|step| step.duration).collect::<Vec<f64>>()
|
||||||
}).flatten().collect();
|
}).flatten().collect();
|
||||||
let (expected_times, offset) = extract_number_vector_and_offset("s", expectation);
|
let (expected_times, offset) = extract_number_vector_and_offset("s", expectation);
|
||||||
println!("{actual_times:?} == {expected_times:?} +- {offset}");
|
// println!("{actual_times:?} == {expected_times:?} +- {offset}");
|
||||||
assert_eq!(actual_times.len(), expected_times.len(), "times mismatch: {actual_times:?} != {expected_times:?} +- {offset}");
|
assert_eq!(actual_times.len(), expected_times.len(), "times mismatch: {actual_times:?} != {expected_times:?} +- {offset}");
|
||||||
|
|
||||||
zip(actual_times, expected_times).for_each(|(actual_time, expected_time)| {
|
zip(actual_times, expected_times).for_each(|(actual_time, expected_time)| {
|
||||||
@ -645,29 +684,20 @@ fn request_route(world: &mut OSRMWorld, step: &Step, state: String) {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
"distances" => {
|
"distances" => {
|
||||||
|
let actual_distances = response.routes.first().expect("no route returned").legs.iter().map(|leg| {
|
||||||
println!("{:?}",response.routes.first().expect("no route returned"));
|
leg.steps.iter().filter(|step| step.distance > 0.).map(|step| step.distance).collect::<Vec<f64>>()
|
||||||
// TODO: go over steps
|
}).flatten().collect::<Vec<f64>>();
|
||||||
let actual_distances : Vec<f64> = response.routes.first().expect("no route returned").legs.iter().map(|leg| leg.distance).collect();
|
|
||||||
let (expected_distances, offset) = extract_number_vector_and_offset("m", expectation);
|
let (expected_distances, offset) = extract_number_vector_and_offset("m", expectation);
|
||||||
println!("{expected_distances:?} == {actual_distances:?}");
|
|
||||||
println!("!");
|
|
||||||
assert_eq!(expected_distances.len(), actual_distances.len(), "distances mismatch {expected_distances:?} != {actual_distances:?} +- {offset}");
|
assert_eq!(expected_distances.len(), actual_distances.len(), "distances mismatch {expected_distances:?} != {actual_distances:?} +- {offset}");
|
||||||
|
|
||||||
zip(actual_distances, expected_distances).for_each(|(actual_distance, expected_distance)| {
|
zip(actual_distances, expected_distances).for_each(|(actual_distance, expected_distance)| {
|
||||||
assert!(approx_equal_within_offset_range(actual_distance, expected_distance, offset as f64),
|
assert!(approx_equal_within_offset_range(actual_distance, expected_distance, offset as f64),
|
||||||
"actual distance {actual_distance} not equal to expected value {expected_distance}");
|
"actual distance {actual_distance} not equal to expected value {expected_distance}");
|
||||||
});
|
});
|
||||||
// // println!("{actual_time} == {expected_time} +- {offset}");
|
|
||||||
// assert!(
|
|
||||||
// approx_equal_within_offset_range(actual_time, expected_time, offset as f64),
|
|
||||||
// "actual time {actual_time} not equal to expected value {expected_time}"
|
|
||||||
// );
|
|
||||||
},
|
},
|
||||||
"weight" => {
|
"weight" => {
|
||||||
let actual_weight = response.routes.first().expect("no route returned").weight;
|
let actual_weight = response.routes.first().expect("no route returned").weight;
|
||||||
let (expected_weight, offset) = extract_number_and_offset("s", expectation);
|
let (expected_weight, offset) = extract_number_and_offset("s", expectation);
|
||||||
// println!("{actual_weight} == {expected_weight} +- {offset}");
|
|
||||||
assert!(
|
assert!(
|
||||||
approx_equal_within_offset_range(
|
approx_equal_within_offset_range(
|
||||||
actual_weight,
|
actual_weight,
|
||||||
@ -689,7 +719,54 @@ fn request_route(world: &mut OSRMWorld, step: &Step, state: String) {
|
|||||||
"actual time {actual_distance} not equal to expected value {expected_distance}"
|
"actual time {actual_distance} not equal to expected value {expected_distance}"
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
"waypoints" => {},
|
"summary" => {
|
||||||
|
let actual_summary = response.routes.first().expect("no route returned").legs.iter().map(|leg| {
|
||||||
|
leg.summary.clone()
|
||||||
|
}).collect::<Vec<String>>().join(",");
|
||||||
|
assert_eq!(actual_summary,expectation, "summary mismatch");
|
||||||
|
},
|
||||||
|
"data_version" => {
|
||||||
|
let expected_data_version = match test_case.get("data_version") {
|
||||||
|
Some(s) if !s.is_empty() => Some(s),
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
assert_eq!(
|
||||||
|
expected_data_version,
|
||||||
|
response.data_version.as_ref(),
|
||||||
|
"data_version does not match"
|
||||||
|
);
|
||||||
|
},
|
||||||
|
"waypoints_count" => {
|
||||||
|
let expected_waypoint_count = match test_case.get("waypoints_count") {
|
||||||
|
Some(s) if !s.is_empty() => s.parse::<usize>().expect("waypoint_count is a number"),
|
||||||
|
_ => 0,
|
||||||
|
};
|
||||||
|
let actual_waypoint_count = match &response.waypoints {
|
||||||
|
Some(w) => w.len(),
|
||||||
|
None => 0,
|
||||||
|
};
|
||||||
|
assert_eq!(
|
||||||
|
expected_waypoint_count,
|
||||||
|
actual_waypoint_count,
|
||||||
|
"waypoint_count does not match"
|
||||||
|
);
|
||||||
|
},
|
||||||
|
"geometry" => {
|
||||||
|
let expected_geometry = test_case.get("geometry").expect("no geometry found");
|
||||||
|
match &response.routes.first().expect("no route").geometry {
|
||||||
|
route_response::Geometry::A(actual_geometry) => {
|
||||||
|
assert_eq!(
|
||||||
|
expected_geometry,
|
||||||
|
actual_geometry,
|
||||||
|
"geometry does not match"
|
||||||
|
);
|
||||||
|
},
|
||||||
|
route_response::Geometry::B { coordinates: _, r#type: _ } => unimplemented!("geojson comparison"),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
},
|
||||||
|
// "classes" => {},
|
||||||
// TODO: more checks need to be implemented
|
// TODO: more checks need to be implemented
|
||||||
_ => {
|
_ => {
|
||||||
let msg = format!("case {case} = {expectation} not implemented");
|
let msg = format!("case {case} = {expectation} not implemented");
|
||||||
@ -700,8 +777,7 @@ fn request_route(world: &mut OSRMWorld, step: &Step, state: String) {
|
|||||||
}
|
}
|
||||||
fn main() {
|
fn main() {
|
||||||
let args = Args::parse();
|
let args = Args::parse();
|
||||||
debug!("arguments: {:?}", args);
|
debug!("{args:?}");
|
||||||
|
|
||||||
let digest = md5_of_osrm_executables().digest().to_hex_lowercase();
|
let digest = md5_of_osrm_executables().digest().to_hex_lowercase();
|
||||||
|
|
||||||
futures::executor::block_on(
|
futures::executor::block_on(
|
||||||
@ -717,8 +793,7 @@ fn main() {
|
|||||||
future::ready(()).boxed()
|
future::ready(()).boxed()
|
||||||
})
|
})
|
||||||
// .with_writer(DotWriter::default().normalized())
|
// .with_writer(DotWriter::default().normalized())
|
||||||
.filter_run("features/testbot/time.feature", |_, _, sc| {
|
// .filter_run("features/testbot/geometry.feature", |_, _, sc| {
|
||||||
!sc.tags.iter().any(|t| t == "todo")
|
.filter_run("features", |_, _, sc| !sc.tags.iter().any(|t| t == "todo")),
|
||||||
}),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user