use crate::{pretty_comparison, ProtocolTestFailure};
use regex_lite::Regex;
fn rewrite_url_encoded_map_keys(input: &str) -> (String, String) {
let mut itr = input.split('=');
let (key, value) = (itr.next().unwrap(), itr.next().unwrap());
let regex = Regex::new(r"^(.+)\.\d+\.(.+)$").unwrap();
if let Some(captures) = regex.captures(key) {
let rewritten_key = format!(
"{}.N.{}",
captures.get(1).unwrap().as_str(),
captures.get(2).unwrap().as_str()
);
(rewritten_key, value.to_string())
} else {
(key.to_string(), value.to_string())
}
}
fn rewrite_url_encoded_body(input: &str) -> String {
let mut entries: Vec<(String, String)> = input
.split('&')
.map(|entry| entry.trim())
.filter(|s| !s.is_empty())
.map(rewrite_url_encoded_map_keys)
.collect();
if entries.len() > 2 {
entries[2..].sort_by(|a, b| a.1.cmp(&b.1));
}
let entries: Vec<String> = entries
.into_iter()
.map(|kv| format!("{}={}", kv.0, kv.1))
.collect();
entries.join("\n&")
}
pub(crate) fn try_url_encoded_form_equivalent(
expected: &str,
actual: &str,
) -> Result<(), ProtocolTestFailure> {
let expected = rewrite_url_encoded_body(expected);
let actual = rewrite_url_encoded_body(actual);
if actual == expected {
Ok(())
} else {
Err(ProtocolTestFailure::BodyDidNotMatch {
comparison: pretty_comparison(&expected, &actual),
hint: "".into(),
})
}
}
#[cfg(test)]
mod tests {
use crate::urlencoded::try_url_encoded_form_equivalent;
#[test]
fn test_url_encoded_form_equivalent() {
assert_eq!(
Ok(()),
try_url_encoded_form_equivalent(
"Action=Something&Version=test",
"Action=Something&Version=test",
)
);
assert!(try_url_encoded_form_equivalent(
"Action=Something&Version=test&Property=bar",
"Action=Something&Version=test&Property=foo",
)
.is_err());
assert!(try_url_encoded_form_equivalent(
"Action=Something&Version=test&Property=foo",
"Action=Something&Version=test&WrongProperty=foo",
)
.is_err());
assert_eq!(
Ok(()),
try_url_encoded_form_equivalent(
"Action=Something&Version=test\
&SomeMap.1.key=bar\
&SomeMap.1.value=Bar\
&SomeMap.2.key=foo\
&SomeMap.2.value=Foo",
"Action=Something&Version=test\
&SomeMap.1.key=foo\
&SomeMap.1.value=Foo\
&SomeMap.2.key=bar\
&SomeMap.2.value=Bar",
)
);
}
}