Repository navigation
Conversation
This enables creating a nicer API to expose publicly for use by plugin wrappers. See: pact-foundation#492
…ilder Setting the plugin contents completes a synchronous plugin interaction, so WithContent now returns void instead of the same builder. The plugin splits one contents document into the request and its responses itself: a second call would replace the request but append another response, which is why the builder no longer allows it. Provider states stay chainable via Given. Adds unit tests for the plugin request and pact builders and a docs page for the raw plugin API, linked from the README. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Add a public HTTP plugin pact/request/response API on top of the synchronous plugin prerequisite. Load content plugins through the existing factory, create HTTP rather than synchronous-message interactions, and route plugin contents independently to request and response parts. Reuse HTTP drivers for methods, paths, headers, queries and status; retain mock-server verification, logging, pact writing and plugin cleanup inside PactNet. Keep native handles and drivers internal. Reject repeated contents and response-stage reuse, validate HTTP status, and preserve header/query indexing. Add focused tests and HTTP plugin guidance. Asynchronous binary plugin message reification remains a separate contribution. Validation: 60 affected builder tests passed, including existing synchronous and HTTP behavior; the external Avro example passed native request/response and provider/mismatch verification with hominux avro 0.1.3 and FFI 0.4.27.
Add transport-free asynchronous plugin pact/message builders and configured consumer verification. Expose generated binary payloads, media type and cloned JSON metadata, write the pact only after successful consumption, and keep native reification and plugin cleanup internal. Decode the native V4 base64 envelope and free its allocated string. Apply user metadata after plugin content configuration, which can replace native message metadata. Preserve the existing JSON message APIs and add ordering, terminal-content, callback success/failure and disposal tests. Add an opt-in native Avro 0.1.3 synchronous capability check. With FFI 0.4.27, its unlabelled single-record configuration creates an empty sync request and no responses. Document the need for plugin request/response parts and a separate transport-free sync consumer matching API rather than presenting the transport-based gRPC builder as Avro sync support. Validation: 109 affected plugin/message/HTTP builder tests passed with the capability check enabled. External Avro async consumer/provider and mismatch checks passed with binary records and metadata. HTTP and gRPC regressions remained green.
…rotobuf plugin 0.8.0 Brings in 92748436 as requested in the PR pact-foundation#551 review. - pact-ffi 0.4.27 -> 0.5.10; a request header configured with multiple values is now matched as one joined value, so the tests and the upgrading-to-5 doc reflect that - pact fixtures regenerated (pactRust metadata, merged X-Request header) - grpc sample pact regenerated with pact-protobuf-plugin 0.8.0 - grpc sample and plugin docs now request plugin 0.8.0 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Upgrade the Avro async branch native package bootstrap from pact-ffi 0.4.27 to released 0.5.10. The extension's Avro provider verification returned HTTP 200 but plugin content comparison failed with a transport error on Windows under 0.4.27. Repacking the same PactNet source against 0.5.10 makes all five Avro sample tests pass locally, including provider matching and the expected provider mismatch. All five supported runtime libraries download with published SHA-256 verification. Other legacy PactNet fixture tests may need fixture metadata updates before the general branch suite runs against 0.5.10; this branch change is the Avro async bootstrap prerequisite.
Replace build/install-plugins.sh with the pact-foundation/pact-cli action and `pact plugin install`, as suggested in review. The plugin is still pre-installed before the tests run so parallel test projects do not race each other auto-downloading it. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Update native library downloads and refresh Rust version metadata in integration fixtures and the Orders API sample pact. Retain existing repeated-header expectations and pact representations.
…ssages PactNet already supports writing asynchronous (fire-and-forget) message pacts, but had no way to write V4 synchronous message pacts (used by e.g. AsyncAPI 3 operations with a reply block), even though the underlying pact_ffi native library already exposes pactffi_new_sync_message_interaction and can set request/response bodies and metadata on it via the existing generic pactffi_with_body/pactffi_with_metadata functions. This adds: - IPactV4.WithSynchronousMessageInteractions() entry point - ISyncMessagePactBuilderV4 / ISyncMessageBuilderV4 / IConfiguredSyncMessageVerifier public API, mirroring the existing async IMessagePactBuilderV4 API - SyncMessageInteractionDriver, wiring the above onto the native FFI calls The consumer-side Verify<TRequest, TResponse> reads the generated request contents (matchers stripped, generators applied) via the new pactffi_sync_message_reify FFI function and feeds it to the handler under test; the response content is stored but not currently asserted against, matching the existing async message Verify<T> semantics. Depends on pactffi_sync_message_reify, proposed in pact-foundation/pact-reference#555. Until that lands in a released pact_ffi build, calling ConfiguredSyncMessageVerifier.Verify will fail with EntryPointNotFoundException - the corresponding FFI integration test is marked Skip until then.
Removed redundant phrase from summary comment.
Callers of PactNet don't need to know the Pact-internal term "reify" - GenerateContents describes what the method actually returns. Matches the pactffi_sync_message_generate_contents rename on the pact-reference side (pact-foundation/pact-reference#555). The pre-existing async message Reify()/pactffi_message_reify naming is untouched.
Adds a section to messaging-pacts.md covering WithSynchronousMessageInteractions, alongside the existing fire-and-forget message docs. Notes that provider verification isn't covered yet and that this depends on pactffi_sync_message_generate_contents landing upstream.
Removed information about provider verification support and related issues.
MessageInteractionDriver.Reify() and SyncMessageInteractionDriver.GenerateContents() copied the FFI-returned string into managed memory but never freed the native allocation, leaking it on every call.
Verify/VerifyAsync already required the handler to return a TResponse but never checked it, so a consumer test would pass regardless of what the handler returned. Compare it against the FFI-generated response content (matchers stripped, generators applied) via a structural JSON equality check, so a mismatch fails the test instead of being silently written to the pact file.
pact-foundation#551 reorganises Drivers/ into Http/, Message/ and Plugins/ subfolders. The sync message driver belongs in Message/ alongside the async one, since it's the same message-queue-style request/response category, not a plugin. Namespace stays PactNet.Drivers for now since the rest of the tree hasn't moved yet; that follows once pact-foundation#551 lands.
pactffi_with_metadata only applies response metadata to responses that already exist, and the response is created by the terminal WithResponseJsonContent call, so response metadata was always dropped. The builder now buffers it and applies it after the response content. Request/response metadata values are now dynamic and serialised as JSON, so strings, numbers, booleans and matchers keep their type in the pact instead of relying on the FFI's parse-or-fallback-to-string behaviour.
Un-skip the FFI integration test now that 0.5.10 ships pactffi_sync_message_generate_contents, and compare the written pact against a fixture. Add public API tests for WithSynchronousMessageInteractions covering body matchers, typed metadata, response metadata matchers and a mismatching response.
Links a sync message interaction to an external resource such as an
AsyncAPI operation via pactffi_add_interaction_reference, written to
comments.references.{group}.{name}. Same signature as the async
WithReference proposed in pact-foundation#559.
The FFI parses the value as JSON, so the driver encodes it to keep a
string reference value a string in the pact.
Verify/VerifyAsync compared the handler's response to the generated example by exact JSON equality, so a type matcher still required the example value. They now call pactffi_sync_message_match_response_contents, which applies the response's matching rules the same way the verifier does: Match.Type checks the type of the example, Match.Integer and Match.Decimal the kind of number, Match.Regex the format (e.g. datetimes), and unexpected keys are allowed. Mismatches are reported by path. Requires a pact_ffi release with pactffi_sync_message_match_response_contents.
Aligns the sync message integration fixtures with the ffi 0.5.12 / models 1.3.17 metadata from the pact-ffi upgrade.
…h the DSL Merge the synchronous plugin interaction DSL (pr551, pact_ffi 0.5.10) and move the gRPC/matt transport mock server scenarios to WithSynchronousPluginInteractions. HTTP and message provider verifications use PactVerifier when they pass, re-running through the FFI verifier for mismatch details. Pact writes without a mock server, plugin-transport verification and HTTP/async plugin contents stay on the FFI. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Resolve conflicts with the plugin DSL: keep both WithSynchronousMessageInteractions and WithSynchronousPluginInteractions (using LogToBuffer), drop the duplicated NewSyncMessageInteraction import, add the PactNet.Drivers.Message usings, take FFI 0.5.12 and regenerate the integration fixtures against it. The synchronous message DSL only takes JSON request/response bodies and cannot load a plugin, so the plugin sync message scenarios stay on the FFI. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ugh the DSL HTTP plugin interactions are now recorded lazily and built with WithHttpPluginInteractions when they share one plugin, have a request line and no plain body, and run against a mock server (4 plugin_http consumer scenarios). Pact generation without a mock server, mixed plain/plugin and multi-plugin pacts stay on the FFI. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ough the DSL Conflicts: build/download-native-libs.sh keeps pact_ffi 0.5.12 (theirs was 0.5.10); MessageInteractionDriver.Reify takes the try/finally free from pr-avro-async. Asynchronous plugin message pacts, consumer and provider side, are now written with WithAsynchronousPluginInteractions. Successful message verifications therefore run end to end on the DSL. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Stacks the PactNet plugin PRs on top of the plugin runner (passes 2–5). Plugin scenarios move from the FFI onto the DSL wherever the new interfaces allow it.
Stacked on the pass-1 PR #41 (
feat/compat-suite-plugins). Merges in:The grpc wrapper lives in pact-net-extensions main. The avro wrapper is in pact-net-extensions PRs #1 (avro-http) and #2 (avro-async).
This branch is for compat measurement only. Don't merge it. It contains the four PRs above.
Depends on the suite branch
feat/plugin-features(YOU54F/pact-compatibility-suite#1). The plugin features are included only whenPACT_COMPAT_SUITEpoints at a checkout that hasfeatures/V4/plugins. Needs plugins matt 0.1.1, csv 0.0.6, avro 0.1.3 and protobuf 0.8.0 installed.PACT_COMPAT_SUITE=/path/to/pact-compatibility-suite dotnet test tests/PactNet.Compatibility.TestsEach run writes the routes it took to
tests/PactNet.Compatibility.Tests/bin/Debug/net10.0/plugin-routes.txt.Results
48/48 pass on every pass. V1 consumer is still 24 pass. There are no
src/changes beyond resolving merge conflicts.Counts are DSL/FFI. A scenario counts as DSL only if it makes no FFI calls.
Pass 3 had conflicts:
PactExtensions.cs: kept both sides.Limitations (none raised)
Even with the full stack, 31 of the 48 scenarios still need the FFI:
WithPlugin(name, version)or arbitrary-transport surface. There are only three per-shape entry points (WithSynchronousPluginInteractions,WithHttpPluginInteractions,WithAsynchronousPluginInteractions), each with one plugin per builder.mock_server.rs:463unwrap on None).PactVerifierhas no plugin-transport API and gives no JSON or mismatch output.🤖 Generated with Claude Code