pub(crate) const MOCK_REQUESTS_ROOT: &str = "mock.requests";
#[cfg_attr(
not(test),
expect(
dead_code,
reason = "no emitter consumes it until the reference-backend wave -- #433"
)
)]
pub(crate) const MOCK_VIRTUAL_FIELDS: &[&str] = &["mock.requests.total"];
pub(crate) const MOCK_RECIPE: &str = "mock_requests";
#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) enum MockQuery {
Total,
Count(String),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum MockFieldSyntax {
NotMockField,
BareRoot,
UnrecognizedTail,
UnbalancedBracket,
MissingQuotedKey,
EmptyKey,
}
pub(crate) fn parse_mock_field(field: &str) -> Result<MockQuery, MockFieldSyntax> {
let Some(rest) = field.strip_prefix(MOCK_REQUESTS_ROOT) else {
return Err(MockFieldSyntax::NotMockField);
};
if rest.is_empty() {
return Err(MockFieldSyntax::BareRoot);
}
if rest == ".total" {
return Ok(MockQuery::Total);
}
let Some(bracketed) = rest.strip_prefix('[') else {
return Err(MockFieldSyntax::UnrecognizedTail);
};
let Some(inner) = bracketed.strip_suffix(']') else {
return Err(MockFieldSyntax::UnbalancedBracket);
};
let Some(key) = inner.strip_prefix('"').and_then(|rest| rest.strip_suffix('"')) else {
return Err(MockFieldSyntax::MissingQuotedKey);
};
if key.is_empty() {
return Err(MockFieldSyntax::EmptyKey);
}
Ok(MockQuery::Count(key.to_string()))
}
pub(crate) fn is_mock_virtual_field(field: &str) -> bool {
parse_mock_field(field).is_ok()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn total_parses() {
assert_eq!(parse_mock_field("mock.requests.total"), Ok(MockQuery::Total));
}
#[test]
fn method_and_path_key_parses() {
assert_eq!(
parse_mock_field(r#"mock.requests["POST /v1/chat"]"#),
Ok(MockQuery::Count("POST /v1/chat".to_string()))
);
}
#[test]
fn bare_path_key_parses() {
assert_eq!(
parse_mock_field(r#"mock.requests["/v1/chat"]"#),
Ok(MockQuery::Count("/v1/chat".to_string()))
);
}
#[test]
fn round_trips_the_documented_grammar() {
for field in [
"mock.requests.total",
r#"mock.requests["POST /v1/chat"]"#,
r#"mock.requests["/v1/chat"]"#,
] {
assert!(is_mock_virtual_field(field), "expected {field} to parse");
}
}
#[test]
fn rejects_bare_root() {
assert_eq!(parse_mock_field("mock.requests"), Err(MockFieldSyntax::BareRoot));
assert!(!is_mock_virtual_field("mock.requests"));
}
#[test]
fn rejects_unrelated_root() {
assert_eq!(parse_mock_field("mock.foo"), Err(MockFieldSyntax::NotMockField));
assert!(!is_mock_virtual_field("mock.foo"));
}
#[test]
fn rejects_unbalanced_brackets() {
assert_eq!(
parse_mock_field("mock.requests[\"POST /v1/chat\""),
Err(MockFieldSyntax::UnbalancedBracket)
);
assert_eq!(
parse_mock_field("mock.requests["),
Err(MockFieldSyntax::UnbalancedBracket)
);
assert!(!is_mock_virtual_field("mock.requests["));
}
#[test]
fn rejects_an_unquoted_key() {
assert_eq!(
parse_mock_field("mock.requests[chat]"),
Err(MockFieldSyntax::MissingQuotedKey)
);
}
#[test]
fn rejects_an_empty_key() {
assert_eq!(parse_mock_field(r#"mock.requests[""]"#), Err(MockFieldSyntax::EmptyKey));
}
#[test]
fn rejects_an_unrecognized_tail() {
assert_eq!(
parse_mock_field("mock.requests.count"),
Err(MockFieldSyntax::UnrecognizedTail)
);
}
#[test]
fn every_static_field_parses() {
for field in MOCK_VIRTUAL_FIELDS {
assert!(is_mock_virtual_field(field), "{field} is listed but does not parse");
}
}
}