Skip to content

Commit

Permalink
feat(ffi): allow setting comments
Browse files Browse the repository at this point in the history
Signed-off-by: JP-Ellis <[email protected]>
  • Loading branch information
JP-Ellis committed Feb 26, 2024
1 parent 8ac21bd commit 93f02c7
Show file tree
Hide file tree
Showing 2 changed files with 127 additions and 0 deletions.
72 changes: 72 additions & 0 deletions rust/pact_ffi/src/mock_server/handles.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2138,6 +2138,78 @@ ffi_fn!{
}
}

ffi_fn!{
/// Add a comment to the interaction.
///
/// * `interaction` - Interaction handle to set the comments for.
/// * `key` - Key value
/// * `value` - Comment value. This may be any valid JSON value, or a NULL to
/// clear the comment.
///
/// This function will return `true` if the comments were successfully
/// updated. Both `key` and `value` must be valid UTF-8 null-terminated
/// strings; or in the case of `value`, it may also be a NULL pointer in which
/// case the comment will be cleared.
///
/// Note that a `value` that deserialize to a JSON null will result in a
/// comment being added, with the value being the JSON null.
///
/// # Safety
///
/// The comments parameter must be a valid pointer to a NULL terminated UTF-8,
/// or NULL if the comment is to be cleared.
fn pactffi_set_comment(interaction: InteractionHandle, key: *const c_char, value: *const c_char) -> bool {
let key = match convert_cstr("key", key) {
Some(key) => key,
None => {
error!("set_comments: Key value is not valid (NULL or non-UTF-8)");
return Err(anyhow!("Key value is not valid (NULL or non-UTF-8)"));
}
};
let value: Option<serde_json::Value> = if value.is_null() {
None
} else {
match convert_cstr("value", value) {
Some(value) =>{ match serde_json::from_str(value) {
Ok(value) => Some(value),
Err(_) => Some(serde_json::Value::String(value.to_string())),
}},
None => {
error!("set_comments: Value is not valid (non-UTF-8)");
return Err(anyhow!("Value is not valid (non-UTF-8)"));
}
}
};

interaction.with_interaction(&|_, _, inner| {
if let Some(reqres) = inner.as_v4_http_mut() {
match &value {
Some(value) => reqres.comments.insert(key.to_string(), value.clone()),
None => reqres.comments.remove(key)
};
Ok(())
} else if let Some(message) = inner.as_v4_async_message_mut() {
match &value {
Some(value) => message.comments.insert(key.to_string(), value.clone()),
None => message.comments.remove(key)
};
Ok(())
} else if let Some(sync_message) = inner.as_v4_sync_message_mut() {
match &value {
Some(value) => sync_message.comments.insert(key.to_string(), value.clone()),
None => sync_message.comments.remove(key)
};
Ok(())
} else {
error!("Interaction is an unknown type, is {}", inner.type_of());
Err(anyhow!("Interaction is an unknown type, is {}", inner.type_of()))
}
}).unwrap_or(Err(anyhow!("Not value to unwrap"))).is_ok()
} {
false
}
}

fn convert_ptr_to_body(body: *const u8, size: size_t, content_type: Option<ContentType>) -> OptionalBody {
if body.is_null() {
OptionalBody::Null
Expand Down
55 changes: 55 additions & 0 deletions rust/pact_ffi/tests/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ use pact_ffi::mock_server::handles::{
pactffi_new_pact,
pactffi_pact_handle_write_file,
pactffi_response_status,
pactffi_set_comment,
pactffi_set_key,
pactffi_set_pending,
pactffi_upon_receiving,
Expand Down Expand Up @@ -291,6 +292,60 @@ fn set_pending() {
});
}

#[test]
fn set_comment() {
let consumer_name = CString::new("consumer").unwrap();
let provider_name = CString::new("provider").unwrap();
let pact_handle = pactffi_new_pact(consumer_name.as_ptr(), provider_name.as_ptr());
let description = CString::new("set_comment").unwrap();
let interaction = pactffi_new_interaction(pact_handle, description.as_ptr());

let key_int = CString::new("key_int").unwrap();
let value_int = CString::new("1234").unwrap();
let key_str = CString::new("key_str").unwrap();
let value_str = CString::new("some string").unwrap();
let key_bool = CString::new("key_bool").unwrap();
let value_bool = CString::new("true").unwrap();
let key_float = CString::new("key_float").unwrap();
let value_float = CString::new("12.34").unwrap();
let key_array = CString::new("key_array").unwrap();
let value_array = CString::new("[1, 2, 3]").unwrap();
let key_obj = CString::new("key_object").unwrap();
let value_obj = CString::new("{\"key\": \"value\"}").unwrap();

assert!(pactffi_set_comment(interaction, key_int.as_ptr(), value_int.as_ptr()));
assert!(pactffi_set_comment(interaction, key_str.as_ptr(), value_str.as_ptr()));
assert!(pactffi_set_comment(interaction, key_bool.as_ptr(), value_bool.as_ptr()));
assert!(pactffi_set_comment(interaction, key_float.as_ptr(), value_float.as_ptr()));
assert!(pactffi_set_comment(interaction, key_array.as_ptr(), value_array.as_ptr()));
assert!(pactffi_set_comment(interaction, key_obj.as_ptr(), value_obj.as_ptr()));

interaction.with_interaction(&|_, _, i| {
let interaction = i.as_v4_http().unwrap();
assert_eq!(interaction.comments["key_int"], json!(1234));
assert_eq!(interaction.comments["key_str"], json!("some string"));
assert_eq!(interaction.comments["key_bool"], json!(true));
assert_eq!(interaction.comments["key_float"], json!(12.34));
assert_eq!(interaction.comments["key_array"], json!([1, 2, 3]));
assert_eq!(interaction.comments["key_object"], json!({"key": "value"}));
});

assert!(pactffi_set_comment(interaction, key_int.as_ptr(), null()));
assert!(pactffi_set_comment(interaction, key_str.as_ptr(), null()));
assert!(pactffi_set_comment(interaction, key_bool.as_ptr(), null()));
assert!(pactffi_set_comment(interaction, key_float.as_ptr(), null()));
assert!(pactffi_set_comment(interaction, key_array.as_ptr(), null()));
assert!(pactffi_set_comment(interaction, key_obj.as_ptr(), null()));

interaction.with_interaction(&|_, _, i| {
let interaction = i.as_v4_http().unwrap();
assert_eq!(
interaction.comments,
hashmap!{}
)
});
}

#[test_log::test]
#[allow(deprecated)]
fn http_consumer_feature_test() {
Expand Down

0 comments on commit 93f02c7

Please sign in to comment.