From 3ba8001807858db6cd76692bcfff0ffa131a3dd2 Mon Sep 17 00:00:00 2001 From: Dennis Date: Thu, 30 May 2024 17:10:23 +0200 Subject: [PATCH] Untangle large source file --- tests/common/mod.rs | 4 +- tests/common/osm.rs | 130 +------------------------------------ tests/common/osm_db.rs | 127 ++++++++++++++++++++++++++++++++++++ tests/common/osrm_world.rs | 64 ++++++++++++++++++ tests/cucumber.rs | 64 +----------------- 5 files changed, 197 insertions(+), 192 deletions(-) create mode 100644 tests/common/osm_db.rs create mode 100644 tests/common/osrm_world.rs diff --git a/tests/common/mod.rs b/tests/common/mod.rs index 8e72731eb..e5cb08593 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -1,2 +1,4 @@ pub mod lexicographic_file_walker; -pub mod osm; \ No newline at end of file +pub mod osm; +pub mod osm_db; +pub mod osrm_world; diff --git a/tests/common/osm.rs b/tests/common/osm.rs index a6d7b4bd4..f24deffde 100644 --- a/tests/common/osm.rs +++ b/tests/common/osm.rs @@ -1,10 +1,6 @@ -// TODO: consider trait for OSM entities -// TODO: better error handling in XML creation -// FIXME: today nodes are stored twice -// TODO: move node lookup by name to here use std::collections::HashMap; -use xml_builder::{XMLBuilder, XMLElement, XMLVersion}; +use xml_builder::XMLElement; static OSM_USER: &str = "osrm"; static OSM_TIMESTAMP: &str = "2000-01-01T00:00:00Z"; @@ -134,127 +130,3 @@ impl OSMWay { // self.tags.insert(key.into(), value.into()); // } // } - -#[derive(Debug, Default)] -pub struct OSMDb { - nodes: Vec<(char, OSMNode)>, - ways: Vec, - // relations: Vec, -} - -impl OSMDb { - pub fn add_node(&mut self, node: OSMNode) { - let name = node.tags.get("name").unwrap(); - assert!( - name.len() == 1, - "name needs to be of length 1, but was \"{name}\"" - ); - self.nodes.push((name.chars().next().unwrap(), node)); - } - - pub fn find_node(&self, search_name: char) -> Option<&(char, OSMNode)> { - // TODO: this is a linear search. - self.nodes.iter().find(|(name, _node)| search_name == *name) - } - - pub fn add_way(&mut self, way: OSMWay) { - self.ways.push(way); - } - - // pub fn add_relation(&mut self, relation: OSMRelation) { - // self.relations.push(relation); - // } - - // pub fn clear(&mut self) { - // self.nodes.clear(); - // self.ways.clear(); - // // self.relations.clear(); - // } - - pub fn to_xml(&self) -> String { - let mut xml = XMLBuilder::new() - .version(XMLVersion::XML1_0) - .encoding("UTF-8".into()) - .build(); - - let mut osm = XMLElement::new("osm"); - osm.add_attribute("generator", "osrm-test"); - osm.add_attribute("version", "0.6"); - - for (_, node) in &self.nodes { - osm.add_child(node.to_xml()).unwrap(); - } - - for way in &self.ways { - osm.add_child(way.to_xml()).unwrap(); - } - - xml.set_root_element(osm); - - let mut writer: Vec = Vec::new(); - xml.generate(&mut writer).unwrap(); - String::from_utf8(writer).unwrap() - } - - // pub fn node_len(&self) -> usize { - // self.nodes.len() - // } - // pub fn way_len(&self) -> usize { - // self.ways.len() - // } - // pub fn relation_len(&self) -> usize { - // self.relations.len() - // } -} - -#[cfg(test)] -mod tests { - - #[test] - fn empty_db_by_default() { - use super::*; - let osm_db = OSMDb::default(); - assert_eq!(0, osm_db.node_len()); - assert_eq!(0, osm_db.way_len()); - // assert_eq!(0, osm_db.relation_len()); - } - - #[test] - fn osm_db_with_single_node() { - use super::*; - let mut osm_db = OSMDb::default(); - - let mut node1 = OSMNode { - id: 123, - lat: 50.1234, - lon: 8.9876, - ..Default::default() - }; - - let mut node2 = OSMNode { - id: 321, - lat: 50.1234, - lon: 8.9876, - ..Default::default() - }; - node1.add_tag("name", "a"); - node2.add_tag("name", "b"); - osm_db.add_node(node1.clone()); - osm_db.add_node(node2.clone()); - - let mut way = OSMWay { - id: 890, - ..Default::default() - }; - way.nodes.push(node1); - way.nodes.push(node2); - - osm_db.add_way(way); - - let actual = osm_db.to_xml(); - let expected = "\n\n\t\n\t\t\n\t\n\t\n\t\t\n\t\n\t\n\t\t\n\t\t\n\t\n\n"; - - println!("{actual}"); - assert_eq!(actual, expected); - } -} diff --git a/tests/common/osm_db.rs b/tests/common/osm_db.rs new file mode 100644 index 000000000..c0de48da6 --- /dev/null +++ b/tests/common/osm_db.rs @@ -0,0 +1,127 @@ +use xml_builder::{XMLBuilder, XMLElement, XMLVersion}; +use super::osm::{OSMNode, OSMWay}; + +// TODO: better error handling in XML creation +#[derive(Debug, Default)] +pub struct OSMDb { + nodes: Vec<(char, OSMNode)>, + ways: Vec, + // relations: Vec, +} + +impl OSMDb { + pub fn add_node(&mut self, node: OSMNode) { + let name = node.tags.get("name").unwrap(); + assert!( + name.len() == 1, + "name needs to be of length 1, but was \"{name}\"" + ); + self.nodes.push((name.chars().next().unwrap(), node)); + } + + pub fn find_node(&self, search_name: char) -> Option<&(char, OSMNode)> { + // TODO: this is a linear search. + self.nodes.iter().find(|(name, _node)| search_name == *name) + } + + pub fn add_way(&mut self, way: OSMWay) { + self.ways.push(way); + } + + // pub fn add_relation(&mut self, relation: OSMRelation) { + // self.relations.push(relation); + // } + + // pub fn clear(&mut self) { + // self.nodes.clear(); + // self.ways.clear(); + // // self.relations.clear(); + // } + + pub fn to_xml(&self) -> String { + let mut xml = XMLBuilder::new() + .version(XMLVersion::XML1_0) + .encoding("UTF-8".into()) + .build(); + + let mut osm = XMLElement::new("osm"); + osm.add_attribute("generator", "osrm-test"); + osm.add_attribute("version", "0.6"); + + for (_, node) in &self.nodes { + osm.add_child(node.to_xml()).unwrap(); + } + + for way in &self.ways { + osm.add_child(way.to_xml()).unwrap(); + } + + xml.set_root_element(osm); + + let mut writer: Vec = Vec::new(); + xml.generate(&mut writer).unwrap(); + String::from_utf8(writer).unwrap() + } + + // pub fn node_len(&self) -> usize { + // self.nodes.len() + // } + // pub fn way_len(&self) -> usize { + // self.ways.len() + // } + // pub fn relation_len(&self) -> usize { + // self.relations.len() + // } +} + +#[cfg(test)] +mod tests { + + #[test] + fn empty_db_by_default() { + use super::*; + let osm_db = OSMDb::default(); + assert_eq!(0, osm_db.node_len()); + assert_eq!(0, osm_db.way_len()); + // assert_eq!(0, osm_db.relation_len()); + } + + #[test] + fn osm_db_with_single_node() { + use super::*; + let mut osm_db = OSMDb::default(); + + let mut node1 = OSMNode { + id: 123, + lat: 50.1234, + lon: 8.9876, + ..Default::default() + }; + + let mut node2 = OSMNode { + id: 321, + lat: 50.1234, + lon: 8.9876, + ..Default::default() + }; + node1.add_tag("name", "a"); + node2.add_tag("name", "b"); + osm_db.add_node(node1.clone()); + osm_db.add_node(node2.clone()); + + let mut way = OSMWay { + id: 890, + ..Default::default() + }; + way.nodes.push(node1); + way.nodes.push(node2); + + osm_db.add_way(way); + + let actual = osm_db.to_xml(); + let expected = "\n\n\t\n\t\t\n\t\n\t\n\t\t\n\t\n\t\n\t\t\n\t\t\n\t\n\n"; + + println!("{actual}"); + assert_eq!(actual, expected); + } +} \ No newline at end of file diff --git a/tests/common/osrm_world.rs b/tests/common/osrm_world.rs new file mode 100644 index 000000000..d32423dce --- /dev/null +++ b/tests/common/osrm_world.rs @@ -0,0 +1,64 @@ +use std::{collections::{HashMap, HashSet}, fs::File, path::PathBuf}; +use crate::Point; +use cucumber::World; + +use super::{osm::OSMNode, osm_db::OSMDb}; + +#[derive(Debug, Default, World)] +pub struct OSRMWorld { + pub feature_path: Option, + pub scenario_id: String, + pub feature_digest: String, + pub osrm_digest: String, + pub osm_id: u64, + pub profile: String, + + pub known_osm_nodes: HashSet, + pub known_locations: HashMap, + + pub osm_db: OSMDb, +} + +impl OSRMWorld { + pub fn set_scenario_specific_paths_and_digests(&mut self, path: Option) { + self.feature_path.clone_from(&path); + + let file = File::open(path.clone().unwrap()) + .unwrap_or_else(|_| panic!("filesystem broken? can't open file {:?}", path)); + self.feature_digest = chksum_md5::chksum(file) + .expect("md5 could not be computed") + .to_hex_lowercase(); + } + + pub fn make_osm_id(&mut self) -> u64 { + // number implicitly starts a 1. This is in line with previous implementations + self.osm_id += 1; + self.osm_id + } + + pub fn add_osm_node(&mut self, name: char, location: Point, id: Option) { + if self.known_osm_nodes.contains(&name) { + panic!("duplicate node: {name}"); + } + let id = match id { + Some(id) => id, + None => self.make_osm_id(), + }; + let node = OSMNode { + id, + lat: location.y(), + lon: location.x(), + tags: HashMap::from([("name".to_string(), name.to_string())]), + }; + + self.known_osm_nodes.insert(name); + self.osm_db.add_node(node); + } + + pub fn add_location(&mut self, name: char, location: Point) { + if self.known_locations.contains_key(&name) { + panic!("duplicate location: {name}") + } + self.known_locations.insert(name, location); + } +} \ No newline at end of file diff --git a/tests/cucumber.rs b/tests/cucumber.rs index 1f0dcceed..1b53195c2 100644 --- a/tests/cucumber.rs +++ b/tests/cucumber.rs @@ -3,80 +3,20 @@ extern crate clap; mod common; use core::panic; -use std::collections::{HashMap, HashSet}; use std::fmt::Display; use std::fs::{create_dir_all, File}; use std::io::{Read, Write}; use std::path::PathBuf; use std::{env, fs}; - +use crate::common::osrm_world::OSRMWorld; use cheap_ruler::CheapRuler; use clap::Parser; use common::lexicographic_file_walker::LexicographicFileWalker; -use common::osm::{OSMDb, OSMNode, OSMWay}; +use common::osm::OSMWay; use cucumber::{self, gherkin::Step, given, when, World}; use futures::{future, FutureExt}; use geo_types::{point, Point}; -#[derive(Debug, Default, World)] -struct OSRMWorld { - feature_path: Option, - scenario_id: String, - feature_digest: String, - osrm_digest: String, - osm_id: u64, - profile: String, - - known_osm_nodes: HashSet, - known_locations: HashMap, - - osm_db: OSMDb, -} - -impl OSRMWorld { - fn set_scenario_specific_paths_and_digests(&mut self, path: Option) { - self.feature_path.clone_from(&path); - - let file = File::open(path.clone().unwrap()) - .unwrap_or_else(|_| panic!("filesystem broken? can't open file {:?}", path)); - self.feature_digest = chksum_md5::chksum(file) - .expect("md5 could not be computed") - .to_hex_lowercase(); - } - - fn make_osm_id(&mut self) -> u64 { - // number implicitly starts a 1. This is in line with previous implementations - self.osm_id += 1; - self.osm_id - } - - fn add_osm_node(&mut self, name: char, location: Point, id: Option) { - if self.known_osm_nodes.contains(&name) { - panic!("duplicate node: {name}"); - } - let id = match id { - Some(id) => id, - None => self.make_osm_id(), - }; - let node = OSMNode { - id, - lat: location.y(), - lon: location.x(), - tags: HashMap::from([("name".to_string(), name.to_string())]), - }; - - self.known_osm_nodes.insert(name); - self.osm_db.add_node(node); - } - - fn add_location(&mut self, name: char, location: Point) { - if self.known_locations.contains_key(&name) { - panic!("duplicate location: {name}") - } - self.known_locations.insert(name, location); - } -} - const DEFAULT_ORIGIN: [f64; 2] = [1., 1.]; // TODO: move to world? const DEFAULT_GRID_SIZE: f64 = 100.; // TODO: move to world?