Make the first 3 nearest/pick.feature scenarios pass
This commit is contained in:
parent
59cbb08c0e
commit
5cf37a0c7c
8
Cargo.lock
generated
8
Cargo.lock
generated
@ -548,6 +548,12 @@ version = "0.5.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "help"
|
||||||
|
version = "0.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b5d2c6714f78261bbacbd07338eb21943fa5a25c67760287aecb6aefbec89062"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "humantime"
|
name = "humantime"
|
||||||
version = "2.1.0"
|
version = "2.1.0"
|
||||||
@ -740,6 +746,8 @@ dependencies = [
|
|||||||
"cucumber",
|
"cucumber",
|
||||||
"futures",
|
"futures",
|
||||||
"geo-types",
|
"geo-types",
|
||||||
|
"help",
|
||||||
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"ureq",
|
"ureq",
|
||||||
"xml-builder",
|
"xml-builder",
|
||||||
|
@ -10,6 +10,8 @@ clap = "4.5.4"
|
|||||||
cucumber = "0.21.0"
|
cucumber = "0.21.0"
|
||||||
futures = "0.3.30"
|
futures = "0.3.30"
|
||||||
geo-types = "0.7.13"
|
geo-types = "0.7.13"
|
||||||
|
help = "0.0.0"
|
||||||
|
serde = { version = "1.0.203", features = ["serde_derive"] }
|
||||||
serde_json = "1.0.117"
|
serde_json = "1.0.117"
|
||||||
ureq = "2.9.7"
|
ureq = "2.9.7"
|
||||||
xml-builder = "0.5.2"
|
xml-builder = "0.5.2"
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include "util/json_container.hpp"
|
#include "util/json_container.hpp"
|
||||||
|
|
||||||
#include <boost/format.hpp>
|
#include <boost/format.hpp>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
namespace osrm::server::service
|
namespace osrm::server::service
|
||||||
{
|
{
|
||||||
@ -30,11 +31,11 @@ std::string getWrongOptionHelp(const engine::api::NearestParameters ¶meters)
|
|||||||
return help;
|
return help;
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
engine::Status NearestService::RunQuery(std::size_t prefix_length,
|
engine::Status NearestService::RunQuery(std::size_t prefix_length,
|
||||||
std::string &query,
|
std::string &query,
|
||||||
osrm::engine::api::ResultT &result)
|
osrm::engine::api::ResultT &result)
|
||||||
{
|
{
|
||||||
|
std::cout << "running query: " << query << "\n";
|
||||||
result = util::json::Object();
|
result = util::json::Object();
|
||||||
auto &json_result = std::get<util::json::Object>(result);
|
auto &json_result = std::get<util::json::Object>(result);
|
||||||
|
|
||||||
|
@ -1,4 +1,8 @@
|
|||||||
use std::{collections::VecDeque, fs, path::{Path, PathBuf}};
|
use std::{
|
||||||
|
collections::VecDeque,
|
||||||
|
fs,
|
||||||
|
path::{Path, PathBuf},
|
||||||
|
};
|
||||||
|
|
||||||
// TODO: port into toolbox-rs
|
// TODO: port into toolbox-rs
|
||||||
pub struct LexicographicFileWalker {
|
pub struct LexicographicFileWalker {
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
pub mod lexicographic_file_walker;
|
pub mod lexicographic_file_walker;
|
||||||
|
pub mod nearest_response;
|
||||||
pub mod osm;
|
pub mod osm;
|
||||||
pub mod osm_db;
|
pub mod osm_db;
|
||||||
pub mod osrm_world;
|
pub mod osrm_world;
|
||||||
|
23
tests/common/nearest_response.rs
Normal file
23
tests/common/nearest_response.rs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
use geo_types::{point, Point};
|
||||||
|
use serde::Deserialize;
|
||||||
|
|
||||||
|
#[derive(Deserialize, Debug)]
|
||||||
|
pub struct Waypoint {
|
||||||
|
hint: String,
|
||||||
|
nodes: Vec<u64>,
|
||||||
|
distance: f64,
|
||||||
|
name: String,
|
||||||
|
location: [f64; 2],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Waypoint {
|
||||||
|
pub fn location(&self) -> Point {
|
||||||
|
point!(self.location)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Debug)]
|
||||||
|
pub struct NearestResponse {
|
||||||
|
code: String,
|
||||||
|
pub waypoints: Vec<Waypoint>,
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
use xml_builder::{XMLBuilder, XMLElement, XMLVersion};
|
|
||||||
use super::osm::{OSMNode, OSMWay};
|
use super::osm::{OSMNode, OSMWay};
|
||||||
|
use xml_builder::{XMLBuilder, XMLElement, XMLVersion};
|
||||||
|
|
||||||
// TODO: better error handling in XML creation
|
// TODO: better error handling in XML creation
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use std::{collections::HashMap, fs::File, path::PathBuf};
|
|
||||||
use crate::Point;
|
use crate::Point;
|
||||||
use cucumber::World;
|
use cucumber::World;
|
||||||
|
use std::{collections::HashMap, fs::File, path::PathBuf};
|
||||||
|
|
||||||
use super::{osm::OSMNode, osm_db::OSMDb};
|
use super::{osm::OSMNode, osm_db::OSMDb};
|
||||||
|
|
||||||
@ -58,10 +58,17 @@ impl OSRMWorld {
|
|||||||
pub fn get_location(&self, name: char) -> Point {
|
pub fn get_location(&self, name: char) -> Point {
|
||||||
match name {
|
match name {
|
||||||
// TODO: move lookup to world
|
// TODO: move lookup to world
|
||||||
'0'..='9' => self.known_locations.get(&name).expect("test case specifies unknown location: {name}"),
|
'0'..='9' => self
|
||||||
'a'..='z' => self.known_osm_nodes.get(&name).expect("test case specifies unknown osm node: {name}"),
|
.known_locations
|
||||||
|
.get(&name)
|
||||||
|
.expect("test case specifies unknown location: {name}"),
|
||||||
|
'a'..='z' => self
|
||||||
|
.known_osm_nodes
|
||||||
|
.get(&name)
|
||||||
|
.expect("test case specifies unknown osm node: {name}"),
|
||||||
_ => unreachable!("nodes have to be name in [0-9][a-z]"),
|
_ => unreachable!("nodes have to be name in [0-9][a-z]"),
|
||||||
}.clone()
|
}
|
||||||
|
.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_location(&mut self, name: char, location: Point) {
|
pub fn add_location(&mut self, name: char, location: Point) {
|
||||||
|
@ -6,20 +6,20 @@ use crate::common::osrm_world::OSRMWorld;
|
|||||||
use cheap_ruler::CheapRuler;
|
use cheap_ruler::CheapRuler;
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use common::lexicographic_file_walker::LexicographicFileWalker;
|
use common::lexicographic_file_walker::LexicographicFileWalker;
|
||||||
|
use common::nearest_response::NearestResponse;
|
||||||
use common::osm::OSMWay;
|
use common::osm::OSMWay;
|
||||||
use serde_json::Value;
|
|
||||||
use ureq::Agent;
|
|
||||||
use core::panic;
|
use core::panic;
|
||||||
use std::time::Duration;
|
|
||||||
use cucumber::{self, gherkin::Step, given, when, World};
|
use cucumber::{self, gherkin::Step, given, when, World};
|
||||||
use futures::{future, FutureExt};
|
use futures::{future, FutureExt};
|
||||||
use geo_types::{point, Point};
|
use geo_types::{point, Point};
|
||||||
use std::fmt::Display;
|
use std::fmt::{format, Display};
|
||||||
use std::fs::{create_dir_all, File};
|
use std::fs::{create_dir_all, File};
|
||||||
use std::io::{Read, Write};
|
use std::io::{BufRead, BufReader, Read, Write};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::process::Command;
|
use std::process::{Command, Stdio};
|
||||||
|
use std::time::Duration;
|
||||||
use std::{env, fs};
|
use std::{env, fs};
|
||||||
|
use ureq::Agent;
|
||||||
|
|
||||||
const DEFAULT_ORIGIN: [f64; 2] = [1., 1.]; // TODO: move to world?
|
const DEFAULT_ORIGIN: [f64; 2] = [1., 1.]; // TODO: move to world?
|
||||||
const DEFAULT_GRID_SIZE: f64 = 100.; // TODO: move to world?
|
const DEFAULT_GRID_SIZE: f64 = 100.; // TODO: move to world?
|
||||||
@ -192,12 +192,32 @@ fn request_nearest(world: &mut OSRMWorld, step: &Step) {
|
|||||||
|
|
||||||
let data_path = cache_path.join(world.scenario_id.to_owned() + ".osrm");
|
let data_path = cache_path.join(world.scenario_id.to_owned() + ".osrm");
|
||||||
println!("{routed_path:?} {}", data_path.to_str().unwrap());
|
println!("{routed_path:?} {}", data_path.to_str().unwrap());
|
||||||
let handle = Command::new(routed_path)
|
|
||||||
|
// TODO: move the child handling into a convenience struct
|
||||||
|
let mut handle = Command::new(routed_path)
|
||||||
.arg(data_path.to_str().unwrap())
|
.arg(data_path.to_str().unwrap())
|
||||||
|
.stdout(Stdio::piped())
|
||||||
.spawn();
|
.spawn();
|
||||||
|
|
||||||
if let Err(e) = handle {
|
let child = match &mut handle {
|
||||||
panic!("{e}");
|
Ok(o) => o,
|
||||||
|
Err(e) => panic!("cannot access handle: {e}"),
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut running = false;
|
||||||
|
if let Some(output) = &mut child.stdout {
|
||||||
|
let mut reader = BufReader::new(output);
|
||||||
|
let mut line = String::new();
|
||||||
|
while let Ok(count) = reader.read_line(&mut line) {
|
||||||
|
println!("count: {count} ->{line}");
|
||||||
|
if line.contains("running and waiting for requests") {
|
||||||
|
running = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !running {
|
||||||
|
panic! {"routed not started"}
|
||||||
}
|
}
|
||||||
|
|
||||||
let agent: Agent = ureq::AgentBuilder::new()
|
let agent: Agent = ureq::AgentBuilder::new()
|
||||||
@ -213,23 +233,50 @@ fn request_nearest(world: &mut OSRMWorld, step: &Step) {
|
|||||||
println!("{query_location:?} => {expected_location:?}");
|
println!("{query_location:?} => {expected_location:?}");
|
||||||
// run queries
|
// run queries
|
||||||
// "http://localhost:5000/nearest/v1/testbot/1.0008984512067491,1.0"
|
// "http://localhost:5000/nearest/v1/testbot/1.0008984512067491,1.0"
|
||||||
let url = format!("http://localhost:5000/nearest/v1/{}/{},{}", world.profile, query_location.x(), query_location.y());
|
let url = format!(
|
||||||
let body: String = agent.get(&url)
|
"http://localhost:5000/nearest/v1/{}/{},{}",
|
||||||
.call().unwrap()
|
world.profile,
|
||||||
.into_string().unwrap();
|
query_location.x(),
|
||||||
|
query_location.y()
|
||||||
|
);
|
||||||
|
let call = agent.get(&url).call();
|
||||||
|
|
||||||
let v: Value = serde_json::from_str(&body).unwrap();
|
let body = match call {
|
||||||
let result_location = point!{ x: v["location"][0].as_f64().unwrap(), y: v["location"][1].as_f64().unwrap()};
|
Ok(response) => response.into_string().expect("response not parseable"),
|
||||||
assert_eq!(result_location, expected_location)
|
Err(e) => panic!("http error: {e}"),
|
||||||
|
};
|
||||||
|
|
||||||
|
println!("body: {body}");
|
||||||
|
|
||||||
|
let v: NearestResponse = match serde_json::from_str(&body) {
|
||||||
|
Ok(v) => v,
|
||||||
|
Err(e) => panic!("parsing error {e}"),
|
||||||
|
};
|
||||||
|
|
||||||
|
let result_location = v.waypoints[0].location();
|
||||||
|
// assert_eq!(result_location, expected_location)
|
||||||
|
assert!(approx_equal(result_location.x(), expected_location.x(), 5));
|
||||||
|
assert!(approx_equal(result_location.y(), expected_location.y(), 5));
|
||||||
// println!("{body}");
|
// println!("{body}");
|
||||||
// check results
|
// check results
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Err(e) = handle.expect("osrm-routed died unexpectedly").kill() {
|
if let Err(e) = child.kill() {
|
||||||
panic!("shutdown failed: {e}");
|
panic!("shutdown failed: {e}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// matchLocation (got, want) {
|
||||||
|
// if (got == null || want == null) return false;
|
||||||
|
// return this.match(got[0], util.format('%d ~0.0025%', want.lon)) &&
|
||||||
|
// this.match(got[1], util.format('%d ~0.0025%', want.lat));
|
||||||
|
// }
|
||||||
|
|
||||||
|
pub fn approx_equal(a: f64, b: f64, dp: u8) -> bool {
|
||||||
|
let p = 10f64.powi(-(dp as i32));
|
||||||
|
(a - b).abs() < p
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: move to different file
|
// TODO: move to different file
|
||||||
fn get_file_as_byte_vec(path: &PathBuf) -> Vec<u8> {
|
fn get_file_as_byte_vec(path: &PathBuf) -> Vec<u8> {
|
||||||
println!("opening {path:?}");
|
println!("opening {path:?}");
|
||||||
|
Loading…
Reference in New Issue
Block a user