Skip to content

Commit

Permalink
Merge pull request #327 from tienvx/limit-content-type-matching-rule-…
Browse files Browse the repository at this point in the history
…by-specification

fix: Only specification v3 or higher support binary body's content type matching rule
  • Loading branch information
rholshausen authored Oct 18, 2023
2 parents 10174b2 + 335d52d commit c7cbcb6
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 12 deletions.
1 change: 1 addition & 0 deletions rust/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions rust/pact_ffi/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ test-log = "0.2.11"
tempfile = "3.5.0"
home = "0.5.4"
pretty_assertions = "1.3.0"
rstest = "0.17.0"

[lib]
crate-type = ["cdylib", "staticlib", "rlib"]
Expand Down
25 changes: 15 additions & 10 deletions rust/pact_ffi/src/mock_server/handles.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1539,6 +1539,9 @@ pub extern fn pactffi_with_binary_file(
size: size_t
) -> bool {
let content_type_header = "Content-Type".to_string();
let support_content_type_matching_rule = interaction.with_pact(
&|_, pact| pact.specification_version >= PactSpecification::V3
).unwrap_or(false);
match convert_cstr("content_type", content_type) {
Some(content_type) => {
interaction.with_interaction(&|_, mock_server_started, inner| {
Expand All @@ -1556,8 +1559,7 @@ pub extern fn pactffi_with_binary_file(
}
}
};
reqres.request.matching_rules.add_category("body").add_rule(
DocPath::root(), MatchingRule::ContentType(content_type.into()), RuleLogic::And);
add_content_type_matching_rule_to_body(support_content_type_matching_rule, &mut reqres.request.matching_rules, content_type);
},
InteractionPart::Response => {
reqres.response.body = convert_ptr_to_body(body, size);
Expand All @@ -1571,30 +1573,26 @@ pub extern fn pactffi_with_binary_file(
}
}
}
reqres.response.matching_rules.add_category("body").add_rule(
DocPath::root(), MatchingRule::ContentType(content_type.into()), RuleLogic::And);
add_content_type_matching_rule_to_body(support_content_type_matching_rule, &mut reqres.response.matching_rules, content_type);
}
};
!mock_server_started
} else if let Some(message) = inner.as_v4_async_message_mut() {
message.contents.contents = convert_ptr_to_body(body, size);
message.contents.matching_rules.add_category("body").add_rule(
DocPath::root(), MatchingRule::ContentType(content_type.into()), RuleLogic::And);
add_content_type_matching_rule_to_body(support_content_type_matching_rule, &mut message.contents.matching_rules, content_type);
message.contents.metadata.insert("contentType".to_string(), json!(content_type));
true
} else if let Some(sync_message) = inner.as_v4_sync_message_mut() {
match part {
InteractionPart::Request => {
sync_message.request.contents = convert_ptr_to_body(body, size);
sync_message.request.matching_rules.add_category("body").add_rule(
DocPath::root(), MatchingRule::ContentType(content_type.into()), RuleLogic::And);
add_content_type_matching_rule_to_body(support_content_type_matching_rule, &mut sync_message.request.matching_rules, content_type);
sync_message.request.metadata.insert("contentType".to_string(), json!(content_type));
},
InteractionPart::Response => {
let mut response = MessageContents::default();
response.contents = convert_ptr_to_body(body, size);
response.matching_rules.add_category("body").add_rule(
DocPath::root(), MatchingRule::ContentType(content_type.into()), RuleLogic::And);
add_content_type_matching_rule_to_body(support_content_type_matching_rule, &mut response.matching_rules, content_type);
response.metadata.insert("contentType".to_string(), json!(content_type));
sync_message.response.push(response);
}
Expand All @@ -1613,6 +1611,13 @@ pub extern fn pactffi_with_binary_file(
}
}

fn add_content_type_matching_rule_to_body(is_supported: bool, matching_rules: &mut MatchingRules, content_type: &str) {
if is_supported {
matching_rules.add_category("body").add_rule(
DocPath::root(), MatchingRule::ContentType(content_type.into()), RuleLogic::And);
}
}

/// Adds a binary file as the body as a MIME multipart with the expected content type and example contents. Will use
/// a mime type matcher to match the body. Returns an error if the interaction or Pact can't be
/// modified (i.e. the mock server for it has already started) or an error occurs.
Expand Down
21 changes: 19 additions & 2 deletions rust/pact_ffi/tests/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@ use itertools::Itertools;
use libc::c_char;
use maplit::*;
use pact_models::bodies::OptionalBody;
use pact_models::PactSpecification;
use pretty_assertions::assert_eq;
use reqwest::blocking::Client;
use reqwest::header::CONTENT_TYPE;
use tempfile::TempDir;
use serde_json::{json, Value};
use rstest::rstest;

#[allow(deprecated)]
use pact_ffi::mock_server::{
Expand All @@ -37,6 +39,7 @@ use pact_ffi::mock_server::handles::{
pactffi_new_message,
pactffi_new_message_pact,
pactffi_new_pact,
pactffi_with_specification,
pactffi_response_status,
pactffi_upon_receiving,
pactffi_with_binary_file,
Expand Down Expand Up @@ -428,11 +431,20 @@ fn fixture_path(path: &str) -> PathBuf {
}

#[cfg(not(windows))]
#[test_log::test]
fn pactffi_with_binary_file_feature_test() {
#[rstest(
specification, expected_value,
case::specification_unknown(PactSpecification::Unknown, false),
case::specification_v1(PactSpecification::V1, false),
case::specification_v1_1(PactSpecification::V1_1, false),
case::specification_v2(PactSpecification::V2, false),
case::specification_v3(PactSpecification::V3, true),
case::specification_v4(PactSpecification::V4, true),
)]
fn pactffi_with_binary_file_feature_test(specification: PactSpecification, expected_value: bool) {
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());
pactffi_with_specification(pact_handle, specification);

let description = CString::new("request_with_matchers").unwrap();
let interaction = pactffi_new_interaction(pact_handle.clone(), description.as_ptr());
Expand Down Expand Up @@ -483,6 +495,11 @@ fn pactffi_with_binary_file_feature_test() {
pactffi_cleanup_mock_server(port);

expect!(mismatches).to(be_equal_to("[]"));

let actual_value = interaction.with_interaction(
&|_, _, inner| inner.as_v4_http().unwrap().request.matching_rules.add_category("body").is_not_empty()
).unwrap_or(false);
expect!(actual_value).to(be_equal_to(expected_value));
}

#[test_log::test]
Expand Down

0 comments on commit c7cbcb6

Please sign in to comment.