Skip to content

Commit

Permalink
fix: Regex generator panics if the regex has any anchors #311
Browse files Browse the repository at this point in the history
  • Loading branch information
rholshausen committed Jan 19, 2024
1 parent 1a4bcd2 commit e9f7c06
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 3 deletions.
27 changes: 24 additions & 3 deletions rust/pact_models/src/generators/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1049,12 +1049,17 @@ impl GenerateValue<Value> for Generator {
let mut parser = regex_syntax::ParserBuilder::new().unicode(false).build();
match parser.parse(regex) {
Ok(hir) => {
let gen = rand_regex::Regex::with_hir(hir, 20).unwrap();
Ok(json!(rand::thread_rng().sample::<String, _>(gen)))
match rand_regex::Regex::with_hir(hir, 20) {
Ok(gen) => Ok(json!(rand::thread_rng().sample::<String, _>(gen))),
Err(err) => {
warn!("Failed to generate a value from regular expression - {}", err);
Err(anyhow!("Failed to generate a value from regular expression - {}", err))
}
}
},
Err(err) => {
warn!("'{}' is not a valid regular expression - {}", regex, err);
Err(anyhow!("Could not generate a random string from {} - {}", regex, err))
Err(anyhow!("'{}' is not a valid regular expression - {}", regex, err))
}
}
},
Expand Down Expand Up @@ -1325,6 +1330,7 @@ mod tests {
use pretty_assertions::assert_eq;
use test_log::test;

use crate::contain;
use crate::generators::Generator::{RandomDecimal, RandomInt, Regex};

use super::*;
Expand Down Expand Up @@ -2060,6 +2066,21 @@ mod tests {
assert_that!(generated.unwrap(), matches_regex(r"^\d{1,2}/\d{1,2}$"));
}

#[test]
fn regex_generator_test_with_anchors() {
let generator = Generator::Regex(r"^\/api\/families\/[0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}$".into());

let generated = generator.generate_value(&"".to_string(), &hashmap!{}, &NoopVariantMatcher.boxed());
let err = generated.unwrap_err().to_string();
expect!(&err).to(contain("'^\\/api\\/families\\/[0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}$' is not a valid regular expression"));
expect!(&err).to(contain("error: unrecognized escape sequence"));

let generated = generator.generate_value(&json!(""), &hashmap!{}, &NoopVariantMatcher.boxed());
let err = generated.unwrap_err().to_string();
expect!(&err).to(contain("'^\\/api\\/families\\/[0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}$' is not a valid regular expression"));
expect!(&err).to(contain("error: unrecognized escape sequence"));
}

#[test]
fn uuid_generator_test() {
let generated = Generator::Uuid(None).generate_value(&"".to_string(), &hashmap!{}, &NoopVariantMatcher.boxed());
Expand Down
26 changes: 26 additions & 0 deletions rust/pact_models/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -430,3 +430,29 @@ impl Display for HttpStatus {

#[cfg(test)]
mod tests;

#[cfg(test)]
pub struct Contains {
expected: String
}

#[cfg(test)]
pub fn contain<S: Into<String>>(expected: S) -> Contains {
Contains { expected: expected.into() }
}

#[cfg(test)]
impl<A> expectest::core::Matcher<A, String> for Contains
where
A: Into<String> + Clone
{
fn failure_message(&self, _join: expectest::core::Join, actual: &A) -> String {
let s: String = actual.clone().into();
format!("expected '{}' to contain <{:?}>", s, self.expected)
}

fn matches(&self, actual: &A) -> bool {
let s: String = actual.clone().into();
s.contains(self.expected.as_str())
}
}

0 comments on commit e9f7c06

Please sign in to comment.