Skip to content

Conversation

@rholshausen
Copy link
Contributor

Supports optional query parameter values. With this change we can support:

  • name=value - query parameter with a value
  • name= - query parameter with empty value
  • name - query parameter with no value

@rholshausen rholshausen requested a review from JP-Ellis April 22, 2024 01:32
Copy link
Contributor

@JP-Ellis JP-Ellis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I understand correctly, the internal representations are:

Query String Key Value
foo=bar "foo" Some("bar")
foo= "foo" Some("")
foo "foo" None

If so, I just noticed a few instances where unwrap_or_default() might be used a bit too eagerly, resulting in a loss of distinction between Some("") and None (see this Rust Playground demo)

I'm flagging them to make sure they are all intentional, and won't result in inconsistent behaviours across different parts of the codebase.

Comment on lines 842 to 847
///
/// For a query parameter with no value, the value parameter can be set to a NULL pointer.
///
/// # Safety
/// The name and value parameters must be valid pointers to NULL terminated strings.
/// The name parameter must be a valid pointer to a NULL terminated string. If the value
/// parameter is not NULL, it must point to a valid NULL terminated string.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be good to make the documentation more explicit, with perhaps some example usage to distinguish an "empty value" from a "null".

E.g.:


For query parameters with no value, two distinct formats are provided:

  1. Parameters with blank values, as specified by ?foo=&bar=, require an empty string:

    pactffi_with_query_parameter_v2(handle, "foo", 0, "");
    pactffi_with_query_parameter_v2(handle, "bar", 0, "");
  2. Parameters with no associated valued, as specified by ?foo&bar, require a NULL pointer:

    pactffi_with_query_parameter_v2(handle, "foo", 0, NULL);
    pactffi_with_query_parameter_v2(handle, "bar", 0, NULL);

Note that the two formats are distinct; however, support for either variant can be provided through the integration JSON:

const char* value = "...";
pactffi_with_query_parameter_v2(handle, "foo", 0, value);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will copy your example docs :-D

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, the only one to fill out would be the last one (as I didn't bother filling out the Integration JSON text) 👍

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Integration JSON won't support it, it will always resolve to the empty string.

Comment on lines +261 to +262
let v = v.as_ref().map(|v| v.as_str()).unwrap_or_default();
regex.is_match(v)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the loss of distinction intentional?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is in the compatibility-suite, it doesn't matter

Comment on lines +2108 to +2110
let value = val.clone().unwrap_or_default();
if let Ok(v) = generator.generate_value(&value, context, &DefaultVariantMatcher.boxed()) {
generated[index] = Some(v);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As above, just double checking whether the loss of distinction between Some("") and None is intentional.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generator code, value doesn't matter.

) -> HashMap<String, Vec<Mismatch>> {
let mut result: HashMap<String, Vec<Mismatch>> = hashmap!{};
for (key, value) in &expected {
let expected_value = value.iter().map(|v| v.clone().unwrap_or_default()).collect_vec();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And here again

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just for display purposes, keeps previous behaviour

match actual.get(key) {
Some(actual_value) => {
let mismatches: Result<(), Vec<super::Mismatch>> = match_query_values(key, value, actual_value, context)
let actual_value = actual_value.iter().map(|v| v.clone().unwrap_or_default()).collect_vec();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Idem

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just for display purposes, keeps previous behaviour

parameter: key.clone(),
expected: "".to_string(),
actual: format!("{:?}", value),
actual: format!("{:?}", value.iter().map(|v| v.clone().unwrap_or_default()).collect_vec()),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For debugging, it probably would be best to distinguish Some("") from None.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just for display purposes, keeps previous behavior. The expected and actual values are not actually used by anything.

@rholshausen rholshausen merged commit d7952e1 into master Apr 22, 2024
@rholshausen rholshausen deleted the feat/optional-query-parameter-values branch April 22, 2024 05:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants