Skip to content

Commit

Permalink
fix: content type matcher was not being applied if content type was n…
Browse files Browse the repository at this point in the history
…ot octet_stream #171
  • Loading branch information
uglyog committed Aug 17, 2022
1 parent 3c5c45d commit 65d0514
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 6 deletions.
Binary file added rust/pact_ffi/tests/1px.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
73 changes: 72 additions & 1 deletion rust/pact_ffi/tests/tests.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
use std::env;
use std::ffi::{CStr, CString};
use std::fs::File;
use std::io::Read;
use std::path::PathBuf;

use bytes::Bytes;
use expectest::prelude::*;
Expand All @@ -23,10 +27,11 @@ use pact_ffi::mock_server::handles::{
pactffi_message_with_metadata,
pactffi_new_interaction,
pactffi_new_message,
pactffi_new_message_pact,
pactffi_new_message_pact,
pactffi_new_pact,
pactffi_response_status,
pactffi_upon_receiving,
pactffi_with_binary_file,
pactffi_with_body,
pactffi_with_header,
pactffi_with_multipart_file,
Expand Down Expand Up @@ -340,3 +345,69 @@ fn pactffi_verifier_cli_args_test() {
assert!(options_flags.options.len() > 0);
assert!(options_flags.flags.len() > 0);
}

/// Get the path to one of our sample *.json files.
fn fixture_path(path: &str) -> PathBuf {
env::current_dir()
.expect("could not find current working directory")
.join("tests")
.join(path)
.to_owned()
}

#[test_log::test]
fn pactffi_with_binary_file_feature_test() {
let consumer_name = CString::new("http-consumer").unwrap();
let provider_name = CString::new("image-provider").unwrap();
let pact_handle = pactffi_new_pact(consumer_name.as_ptr(), provider_name.as_ptr());

let description = CString::new("request_with_matchers").unwrap();
let interaction = pactffi_new_interaction(pact_handle.clone(), description.as_ptr());

let content_type = CString::new("image/gif").unwrap();
let path = CString::new("/upload").unwrap();
let address = CString::new("127.0.0.1:0").unwrap();
let file_path = CString::new("/tmp/pact").unwrap();
let description = CString::new("a request to test the FFI interface").unwrap();
let method = CString::new("POST").unwrap();

let mut buffer = Vec::new();
let gif_file = fixture_path("1px.gif");
File::open(gif_file).unwrap().read_to_end(&mut buffer).unwrap();

pactffi_upon_receiving(interaction.clone(), description.as_ptr());
pactffi_with_request(interaction.clone(), method.as_ptr(), path.as_ptr());
pactffi_with_binary_file(interaction.clone(), InteractionPart::Request, content_type.as_ptr(),
buffer.as_ptr(), buffer.len());
// will respond with...
pactffi_response_status(interaction.clone(), 201);

let port = pactffi_create_mock_server_for_pact(pact_handle.clone(), address.as_ptr(), false);

expect!(port).to(be_greater_than(0));

let client = Client::default();
let result = client.post(format!("http://127.0.0.1:{}/upload", port).as_str())
.header("Content-Type", "image/gif")
.body(buffer)
.send();

let mismatches = unsafe {
CStr::from_ptr(pactffi_mock_server_mismatches(port)).to_string_lossy().into_owned()
};

match result {
Ok(res) => {
let status = res.status();
expect!(status).to(be_eq(201));
},
Err(err) => {
panic!("expected 201 response but request failed - {}", err);
}
};

pactffi_write_pact_file(port, file_path.as_ptr(), true);
pactffi_cleanup_mock_server(port);

expect!(mismatches).to(be_equal_to("[]"));
}
20 changes: 15 additions & 5 deletions rust/pact_matching/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -635,8 +635,8 @@ lazy_static! {
= [
(|content_type| { content_type.is_json() }, json::match_json),
(|content_type| { content_type.is_xml() }, xml::match_xml),
(|content_type| { content_type.base_type() == "application/octet-stream" }, binary_utils::match_octet_stream),
(|content_type| { content_type.base_type() == "multipart/form-data" }, binary_utils::match_mime_multipart)
(|content_type| { content_type.base_type() == "multipart/form-data" }, binary_utils::match_mime_multipart),
(|content_type| { content_type.is_binary() || content_type.base_type() == "application/octet-stream" }, binary_utils::match_octet_stream)
];
}

Expand Down Expand Up @@ -1291,9 +1291,19 @@ fn compare_bodies_core(
}
},
None => {
debug!("No body matcher defined for content type '{}', using plain text matcher", content_type);
if let Err(m) = match_text(&expected.body().value(), &actual.body().value(), context) {
mismatches.extend_from_slice(&*m);
debug!("No body matcher defined for content type '{}', checking for a content type matcher", content_type);
let path = DocPath::root();
if context.matcher_is_defined(&path) && context.select_best_matcher(&path).rules
.iter().any(|rule| if let MatchingRule::ContentType(_) = rule { true } else { false }) {
debug!("Found a content type matcher");
if let Err(m) = binary_utils::match_octet_stream(expected, actual, context) {
mismatches.extend_from_slice(&*m);
}
} else {
debug!("No body matcher defined for content type '{}', using plain text matcher", content_type);
if let Err(m) = match_text(&expected.body().value(), &actual.body().value(), context) {
mismatches.extend_from_slice(&*m);
}
}
}
};
Expand Down
26 changes: 26 additions & 0 deletions rust/pact_matching/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -659,3 +659,29 @@ fn values_matcher_defined() {
expect!(context.values_matcher_defined(&path_x.join("0").join("z"))).to(be_false());
expect!(context.values_matcher_defined(&path_y.join("0").join("y"))).to(be_false());
}

const IMAGE_BYTES: [u8; 16] = [ 0o107, 0o111, 0o106, 0o070, 0o067, 0o141, 0o001, 0o000, 0o001, 0o000, 0o200, 0o000, 0o000, 0o377, 0o377, 0o377 ];

#[test]
fn compare_bodies_core_should_check_for_content_type_matcher() {
let content_type = ContentType::parse("application/gif").unwrap();
let matching_rules = matchingrules!{ "body" => { "$" => [ MatchingRule::ContentType("application/gif".to_string()) ] } };
let expected = Request {
body: OptionalBody::Present(Bytes::from_static(&IMAGE_BYTES), Some(content_type.clone()), None),
matching_rules: matching_rules.clone(),
.. Request::default()
};
let actual = Request {
body: OptionalBody::Present(Bytes::from_static(&IMAGE_BYTES), Some(content_type.clone()), None),
.. Request::default()
};
let context = CoreMatchingContext::new(DiffConfig::AllowUnexpectedKeys,
&matching_rules.rules_for_category("body").unwrap(),
&hashmap!{}
);

let result = compare_bodies_core(&content_type, &expected, &actual, &context);

expect!(result.len()).to(be_equal_to(1));
expect!(result.first().unwrap().description()).to(be_equal_to("$ -> Expected binary contents to have content type 'application/gif' but detected contents was 'image/gif'"));
}

0 comments on commit 65d0514

Please sign in to comment.