Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Matchers: Numeric matcher passing test sending String value #484

Open
surpher opened this issue Jan 28, 2025 · 0 comments
Open

Matchers: Numeric matcher passing test sending String value #484

surpher opened this issue Jan 28, 2025 · 0 comments
Labels
bug Indicates an unexpected problem or unintended behavior

Comments

@surpher
Copy link

surpher commented Jan 28, 2025

🌎 Environment

  • Platform: pact_ffi
  • Version/Release: 0.4.25
  • Pact spec: v3, v4
  • FFI used:
bool pactffi_with_body(
   InteractionHandle interaction,
   enum InteractionPart part,
   const char *content_type,
   const char *body
);

💬 Description

Setting up unit tests for PactSwift verifying matchers in request body, specifically Numeric matcher. When executing the API request and Pact verification, verification succeeds with false positive:

2025-01-28T03:42:33.886570Z  INFO tokio-runtime-worker pact_mock_server::hyper_server: Request matched, sending response
2025-01-28T03:42:33.886572Z DEBUG tokio-runtime-worker pact_mock_server::hyper_server: 
          ----------------------------------------------------------------------------------------
           status: 200
           headers: None
           body: Missing
          ----------------------------------------------------------------------------------------
          
2025-01-28T03:42:33.886586Z TRACE tokio-runtime-worker encode_headers: hyper::proto::h1::role: Server::encode status=200, body=None, req_method=Some(POST)

🦶 Reproduction Steps

Steps to reproduce the behaviour:

  1. Setup a pact interaction that expects request body with Numeric value, ie
"{\"value\”:{
   \"key2\":{\"value\":321,\"pact:matcher:type\":\"number\”},
   \"key1\”:{\"pact:matcher:type\":\"number\",\"value\":123.1}},
   \"pact:matcher:type\":\"type\”
}"
  1. Prepare an encodable type Body(key1: String, key2: String) that takes strings for property’s values,
  2. Send a POST request with the Body type and string values,
  3. Verify pact interaction,

🤔 Expected Results

Pact test should fail due to invalid type being passed for the body keys’ values.

😲 Actual Results

Pact test succeeds with Request matched, sending response

----------------------------------------------------------------------------------------
           status: 200
           headers: None
           body: Missing
----------------------------------------------------------------------------------------

🌳 Logs

...
2025-01-28T04:09:13.515623Z TRACE ThreadId(02) pact_ffi::mock_server::handles: with_interaction - inner = PactHandleInner { pact: V4Pact { consumer: Consumer { name: "Consumer" }, provider: Provider { name: "Provider" }, interactions: [SynchronousHttp { id: None, key: None, description: "a request for a known path with a body matching number", provider_states: [], request: HttpRequest { method: "POST", path: "/jsonbody", query: None, headers: Some({"Content-Type": ["application/json"]}), body: Present(b"{\"key1\":123.1,\"key2\":321}", Some(ContentType { main_type: "application", sub_type: "json", attributes: {}, suffix: None }), None), matching_rules: MatchingRules { rules: {PATH: MatchingRuleCategory { name: PATH, rules: {} }, BODY: MatchingRuleCategory { name: BODY, rules: {DocPath { path_tokens: [Root, Field("key2")], expr: "$.key2" }: RuleList { rules: [Number], rule_logic: And, cascaded: false }, DocPath { path_tokens: [Root, Field("key1")], expr: "$.key1" }: RuleList { rules: [Number], rule_logic: And, cascaded: false }, DocPath { path_tokens: [Root], expr: "$" }: RuleList { rules: [Type], rule_logic: And, cascaded: false }} }} }, generators: Generators { categories: {} } }, response: HttpResponse { status: 200, headers: None, body: Missing, matching_rules: MatchingRules { rules: {} }, generators: Generators { categories: {} } }, comments: {}, pending: false, plugin_config: {}, interaction_markup: InteractionMarkup { markup: "", markup_type: "" }, transport: None }], metadata: {"namespace1": Object {"name1": String("value1")}, "namespace2": Object {"name2": String("value2")}, "pactRust": Object {"ffi": String("0.4.25")}}, plugin_data: [] }, mock_server_started: false, specification_version: V4 }

…

2025-01-28T04:09:54.935771Z  INFO tokio-runtime-worker pact_mock_server::hyper_server: Received request POST /jsonbody
2025-01-28T04:09:54.935775Z DEBUG tokio-runtime-worker pact_mock_server::hyper_server: 
      ----------------------------------------------------------------------------------------
       method: POST
       path: /jsonbody
       query: None
       headers: Some({"content-length": ["29"], "accept-encoding": ["gzip", "deflate"], "accept": ["*/*"], "accept-language": ["en-AU", "en;q=0.9"], "user-agent": ["xctest/23600 CFNetwork/1568.300.101 Darwin/24.2.0"], "host": ["127.0.0.1:4516"], "content-type": ["application/json"], "connection": ["keep-alive"]})
       body: Present(29 bytes, application/json) '{"key2":"456","key1":"321.1"}'
      ----------------------------------------------------------------------------------------

…

2025-01-28T04:09:54.935896Z DEBUG tokio-runtime-worker pact_matching: comparing to expected HTTP Request ( method: POST, path: /jsonbody, query: None, headers: Some({"Content-Type": ["application/json"]}), body: Present(25 bytes, application/json) )
2025-01-28T04:09:54.935904Z DEBUG tokio-runtime-worker pact_matching:      body: '{"key1":123.1,"key2":321}'
2025-01-28T04:09:54.935907Z DEBUG tokio-runtime-worker pact_matching:      matching_rules: MatchingRules { rules: {PATH: MatchingRuleCategory { name: PATH, rules: {} }, BODY: MatchingRuleCategory { name: BODY, rules: {DocPath { path_tokens: [Root, Field("key2")], expr: "$.key2" }: RuleList { rules: [Number], rule_logic: And, cascaded: false }, DocPath { path_tokens: [Root, Field("key1")], expr: "$.key1" }: RuleList { rules: [Number], rule_logic: And, cascaded: false }, DocPath { path_tokens: [Root], expr: "$" }: RuleList { rules: [Type], rule_logic: And, cascaded: false }} }} }

…

2025-01-28T04:09:54.962229Z DEBUG tokio-runtime-worker pact_matching: --> Mismatches: []
2025-01-28T04:09:54.962254Z DEBUG tokio-runtime-worker pact_mock_server::hyper_server: Test context = {"mockServer": Object {"port": Number(4516), "url": String("http://127.0.0.1:4516")}}
2025-01-28T04:09:54.962257Z TRACE tokio-runtime-worker pact_matching: generate_response response=HttpResponse { status: 200, headers: None, body: Missing, matching_rules: MatchingRules { rules: {} }, generators: Generators { categories: {} } } mode=Consumer context={"mockServer": Object {"port": Number(4516), "url": String("http://127.0.0.1:4516")}}
2025-01-28T04:09:54.962262Z  INFO tokio-runtime-worker pact_mock_server::hyper_server: Request matched, sending response
2025-01-28T04:09:54.962521Z DEBUG tokio-runtime-worker pact_mock_server::hyper_server: 
          ----------------------------------------------------------------------------------------
           status: 200
           headers: None
           body: Missing
          ----------------------------------------------------------------------------------------
          
2025-01-28T04:09:54.962539Z TRACE tokio-runtime-worker encode_headers: hyper::proto::h1::role: Server::encode status=200, body=None, req_method=Some(POST)
2025-01-28T04:09:54.962570Z DEBUG tokio-runtime-worker hyper::proto::h1::io: flushed 319 bytes

….

📄 Stack Traces

See attached false-positive-numeric-body-value for full standardOut: .trace log:

false-positive-numeric-body-value.log

🤝 Relationships

  • Related PRs or Issues:
@rholshausen rholshausen added the bug Indicates an unexpected problem or unintended behavior label Jan 29, 2025
rholshausen added a commit that referenced this issue Jan 29, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Indicates an unexpected problem or unintended behavior
Projects
None yet
Development

No branches or pull requests

2 participants