diff options
author | Daniel Silverstone <dsilvers@digital-scurf.org> | 2023-12-27 17:37:27 +0000 |
---|---|---|
committer | Daniel Silverstone <dsilvers@digital-scurf.org> | 2023-12-27 17:38:43 +0000 |
commit | 439bbfe88e971bfa5f07a1faec8ff4a48bbeeb86 (patch) | |
tree | 52b0fc07d789e5d49bc52eef07c066b021834d9a | |
parent | d7d4a575e0d09e05928eba1180b49211149d49af (diff) | |
download | subplot-439bbfe88e971bfa5f07a1faec8ff4a48bbeeb86.tar.gz |
bindings: Remember filename when loading bindings
Signed-off-by: Daniel Silverstone <dsilvers@digital-scurf.org>
-rw-r--r-- | src/bindings.rs | 148 | ||||
-rw-r--r-- | tests/bindings-ubm.rs | 9 |
2 files changed, 130 insertions, 27 deletions
diff --git a/src/bindings.rs b/src/bindings.rs index b937edb..c342432 100644 --- a/src/bindings.rs +++ b/src/bindings.rs @@ -167,6 +167,7 @@ pub struct Binding { impls: HashMap<String, Arc<BindingImpl>>, types: HashMap<String, CaptureType>, doc: Option<String>, + filename: Arc<Path>, } impl Binding { @@ -177,6 +178,7 @@ impl Binding { case_sensitive: bool, mut types: HashMap<String, CaptureType>, doc: Option<String>, + filename: Arc<Path>, ) -> Result<Binding, SubplotError> { let regex = RegexBuilder::new(&format!("^{pattern}$")) .case_insensitive(!case_sensitive) @@ -196,6 +198,7 @@ impl Binding { impls: HashMap::new(), types, doc, + filename, }) } @@ -307,6 +310,10 @@ impl Binding { Some(m) } + + fn filename(&self) -> &Path { + &self.filename + } } impl PartialEq for Binding { @@ -325,10 +332,25 @@ mod test_binding { use crate::ScenarioStep; use crate::StepKind; use std::collections::HashMap; + use std::path::Path; + use std::path::PathBuf; + use std::sync::Arc; + + fn path() -> Arc<Path> { + PathBuf::new().into() + } #[test] fn creates_new() { - let b = Binding::new(StepKind::Given, "I am Tomjon", false, HashMap::new(), None).unwrap(); + let b = Binding::new( + StepKind::Given, + "I am Tomjon", + false, + HashMap::new(), + None, + path(), + ) + .unwrap(); assert_eq!(b.kind(), StepKind::Given); assert!(b.regex().is_match("I am Tomjon")); assert!(!b.regex().is_match("I am Tomjon of Lancre")); @@ -337,20 +359,45 @@ mod test_binding { #[test] fn equal() { - let a = Binding::new(StepKind::Given, "I am Tomjon", false, HashMap::new(), None).unwrap(); - let b = Binding::new(StepKind::Given, "I am Tomjon", false, HashMap::new(), None).unwrap(); + let a = Binding::new( + StepKind::Given, + "I am Tomjon", + false, + HashMap::new(), + None, + path(), + ) + .unwrap(); + let b = Binding::new( + StepKind::Given, + "I am Tomjon", + false, + HashMap::new(), + None, + path(), + ) + .unwrap(); assert_eq!(a, b); } #[test] fn not_equal() { - let a = Binding::new(StepKind::Given, "I am Tomjon", false, HashMap::new(), None).unwrap(); + let a = Binding::new( + StepKind::Given, + "I am Tomjon", + false, + HashMap::new(), + None, + path(), + ) + .unwrap(); let b = Binding::new( StepKind::Given, "I am Tomjon of Lancre", false, HashMap::new(), None, + path(), ) .unwrap(); assert_ne!(a, b); @@ -359,21 +406,21 @@ mod test_binding { #[test] fn does_not_match_with_wrong_kind() { let step = ScenarioStep::new(StepKind::Given, "given", "yo", Location::Unknown); - let b = Binding::new(StepKind::When, "yo", false, HashMap::new(), None).unwrap(); + let b = Binding::new(StepKind::When, "yo", false, HashMap::new(), None, path()).unwrap(); assert!(b.match_with_step("", &step).is_none()); } #[test] fn does_not_match_with_wrong_text() { let step = ScenarioStep::new(StepKind::Given, "given", "foo", Location::Unknown); - let b = Binding::new(StepKind::Given, "bar", false, HashMap::new(), None).unwrap(); + let b = Binding::new(StepKind::Given, "bar", false, HashMap::new(), None, path()).unwrap(); assert!(b.match_with_step("", &step).is_none()); } #[test] fn match_with_fixed_pattern() { let step = ScenarioStep::new(StepKind::Given, "given", "foo", Location::Unknown); - let b = Binding::new(StepKind::Given, "foo", false, HashMap::new(), None).unwrap(); + let b = Binding::new(StepKind::Given, "foo", false, HashMap::new(), None, path()).unwrap(); let m = b.match_with_step("", &step).unwrap(); assert_eq!(m.kind(), StepKind::Given); let mut parts = m.parts(); @@ -396,6 +443,7 @@ mod test_binding { false, HashMap::new(), None, + path(), ) .unwrap(); let m = b.match_with_step("", &step).unwrap(); @@ -413,9 +461,25 @@ mod test_binding { #[test] fn case_sensitive_mismatch() { let step = ScenarioStep::new(StepKind::Given, "given", "I am Tomjon", Location::Unknown); - let b = Binding::new(StepKind::Given, r"i am tomjon", false, HashMap::new(), None).unwrap(); + let b = Binding::new( + StepKind::Given, + r"i am tomjon", + false, + HashMap::new(), + None, + path(), + ) + .unwrap(); assert!(b.match_with_step("", &step).is_some()); - let b = Binding::new(StepKind::Given, r"i am tomjon", true, HashMap::new(), None).unwrap(); + let b = Binding::new( + StepKind::Given, + r"i am tomjon", + true, + HashMap::new(), + None, + path(), + ) + .unwrap(); assert!(b.match_with_step("", &step).is_none()); } } @@ -493,11 +557,11 @@ impl Bindings { } /// Add bindings from a YAML string - pub fn add_from_yaml(&mut self, yaml: &str) -> Result<(), SubplotError> { + pub fn add_from_yaml(&mut self, yaml: &str, filename: Arc<Path>) -> Result<(), SubplotError> { let bindings: Vec<ParsedBindingWrapper> = serde_yaml::from_str(yaml).map_err(SubplotError::Metadata)?; for wrapper in bindings { - self.add(from_hashmap(&wrapper.binding)?); + self.add(from_hashmap(&wrapper.binding, Arc::clone(&filename))?); } Ok(()) } @@ -539,12 +603,12 @@ impl Bindings { where P: AsRef<Path> + Debug, { - let yaml = resource::read_as_string(filename.as_ref(), template) - .map_err(|e| SubplotError::BindingsFileNotFound(filename.as_ref().into(), e))?; + let filename = filename.as_ref(); + let yaml = resource::read_as_string(filename, template) + .map_err(|e| SubplotError::BindingsFileNotFound(filename.into(), e))?; trace!("Loaded file content"); - self.add_from_yaml(&yaml).map_err(|e| { - SubplotError::BindingFileParseError(filename.as_ref().to_owned(), Box::new(e)) - })?; + self.add_from_yaml(&yaml, filename.to_owned().into()) + .map_err(|e| SubplotError::BindingFileParseError(filename.to_owned(), Box::new(e)))?; Ok(()) } @@ -558,7 +622,7 @@ impl Bindings { } } -fn from_hashmap(parsed: &ParsedBinding) -> Result<Binding, SubplotError> { +fn from_hashmap(parsed: &ParsedBinding, filename: Arc<Path>) -> Result<Binding, SubplotError> { let given: i32 = parsed.given.is_some().into(); let when: i32 = parsed.when.is_some().into(); let then: i32 = parsed.then.is_some().into(); @@ -601,6 +665,7 @@ fn from_hashmap(parsed: &ParsedBinding) -> Result<Binding, SubplotError> { parsed.case_sensitive, types, parsed.doc.clone(), + filename, )?; trace!("Binding parsed OK"); for (template, pimpl) in &parsed.impls { @@ -622,6 +687,13 @@ mod test_bindings { use crate::SubplotError; use std::collections::HashMap; + use std::path::Path; + use std::path::PathBuf; + use std::sync::Arc; + + fn path() -> Arc<Path> { + PathBuf::new().into() + } #[test] fn has_no_bindings_initially() { @@ -637,6 +709,7 @@ mod test_bindings { false, HashMap::new(), None, + path(), ) .unwrap(); let mut bindings = Bindings::new(); @@ -672,7 +745,7 @@ mod test_bindings { total: word "; let mut bindings = Bindings::new(); - bindings.add_from_yaml(yaml).unwrap(); + bindings.add_from_yaml(yaml, path()).unwrap(); println!("test: {bindings:?}"); assert!(bindings.has(StepKind::Given, "I am Tomjon")); assert!(bindings.has(StepKind::When, "I declare myself king")); @@ -692,7 +765,7 @@ mod test_bindings { python: FUNCTION: set_name "; - match Bindings::new().add_from_yaml(yaml) { + match Bindings::new().add_from_yaml(yaml, path()) { Ok(_) => unreachable!(), Err(SubplotError::BindingHasManyKeywords(_)) => (), Err(e) => panic!("Incorrect error: {}", e), @@ -709,7 +782,7 @@ mod test_bindings { types: age: number "; - match Bindings::new().add_from_yaml(yaml) { + match Bindings::new().add_from_yaml(yaml, path()) { Ok(_) => unreachable!(), Err(SubplotError::SimplePatternKindMismatch(_)) => (), Err(e) => panic!("Incorrect error: {}", e), @@ -719,8 +792,15 @@ mod test_bindings { #[test] fn does_not_find_match_for_unmatching_kind() { let step = ScenarioStep::new(StepKind::Given, "given", "I am Tomjon", Location::Unknown); - let binding = - Binding::new(StepKind::When, r"I am Tomjon", false, HashMap::new(), None).unwrap(); + let binding = Binding::new( + StepKind::When, + r"I am Tomjon", + false, + HashMap::new(), + None, + path(), + ) + .unwrap(); let mut bindings = Bindings::new(); bindings.add(binding); assert!(matches!( @@ -738,6 +818,7 @@ mod test_bindings { false, HashMap::new(), None, + path(), ) .unwrap(); let mut bindings = Bindings::new(); @@ -753,7 +834,15 @@ mod test_bindings { let step = ScenarioStep::new(StepKind::Given, "given", "I am Tomjon", Location::Unknown); let mut bindings = Bindings::default(); bindings.add( - Binding::new(StepKind::Given, r"I am Tomjon", false, HashMap::new(), None).unwrap(), + Binding::new( + StepKind::Given, + r"I am Tomjon", + false, + HashMap::new(), + None, + path(), + ) + .unwrap(), ); bindings.add( Binding::new( @@ -763,6 +852,7 @@ mod test_bindings { false, HashMap::new(), None, + path(), ) .unwrap(), ); @@ -775,8 +865,15 @@ mod test_bindings { #[test] fn finds_match_for_fixed_string_pattern() { let step = ScenarioStep::new(StepKind::Given, "given", "I am Tomjon", Location::Unknown); - let binding = - Binding::new(StepKind::Given, r"I am Tomjon", false, HashMap::new(), None).unwrap(); + let binding = Binding::new( + StepKind::Given, + r"I am Tomjon", + false, + HashMap::new(), + None, + path(), + ) + .unwrap(); let mut bindings = Bindings::new(); bindings.add(binding); let m = bindings.find("", &step).unwrap(); @@ -799,6 +896,7 @@ mod test_bindings { false, HashMap::new(), None, + path(), ) .unwrap(); let mut bindings = Bindings::new(); diff --git a/tests/bindings-ubm.rs b/tests/bindings-ubm.rs index 4c4aaa0..e4232d1 100644 --- a/tests/bindings-ubm.rs +++ b/tests/bindings-ubm.rs @@ -4,12 +4,17 @@ // there are a large number of them. use regex::RegexBuilder; -use std::collections::HashMap; +use std::path::{Path, PathBuf}; use std::time::SystemTime; +use std::{collections::HashMap, sync::Arc}; use subplot::{html::Location, Binding, Bindings, ScenarioStep, StepKind}; const N: i32 = 1000; +fn path() -> Arc<Path> { + PathBuf::new().into() +} + #[test] fn bindings_microbenchmark() { let time = SystemTime::now(); @@ -34,7 +39,7 @@ fn bindings_microbenchmark() { let mut toadd = vec![]; for t in texts.iter() { - toadd.push(Binding::new(StepKind::Given, t, false, HashMap::new(), None).unwrap()); + toadd.push(Binding::new(StepKind::Given, t, false, HashMap::new(), None, path()).unwrap()); } let created = time.elapsed().unwrap(); |