Adam Cox
03/21/2023, 12:05 PMTien Vo
03/25/2023, 4:07 AMTien Vo
03/25/2023, 4:02 PMpact_ffi::plugins: Failed to call out to plugin - Request to configure interaction failed: Failed to process protobuf: Failed to invoke protoc binary: exit code exit status: 1
According to this https://github.com/pactflow/pact-protobuf-plugin#logging, how can I set env LOG_LEVEL
exactly?
I checked /path/to/plugins/protobuf/log/*.log.Y-M-D
, all files are empty, and I can't see the real problem.
I tried this but it doesn't work:
LOG_LEVEL=debug PACT_LOGLEVEL=trace phpunit example/async-message/consumer/tests/Contract/
Tien Vo
03/27/2023, 1:46 AMPACT_PLUGIN_DIR
, or introduce new var PACT_PLUGIN_DIRS
Tien Vo
04/03/2023, 5:06 AM$response
->setStatus(200)
->setBody([
'csvHeaders' => true,
'column:id' => "matching(regex, '^[0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}$','{$id}')",
'column:name' => "matching(type,'{$name}')",
'column:gender' => "matching(regex, 'male|female|other','{$gender}')",
])
->setContentType('text/csv')
;
Mock server will return:
gender,id,name
$gender,$id,$name
Is this expected behavior?Tien Vo
04/03/2023, 5:51 AMPACT_LOGLEVEL=debug phpunit example/provider/ 12:41:36
Xdebug: [Step Debug] Could not connect to debugging client. Tried: 127.0.0.1:9003 (through xdebug.client_host/xdebug.client_port).
PHPUnit 9.5.20 #StandWithUkraine
2023-04-03T05:41:46.951993Z DEBUG ThreadId(01) pact_ffi::verifier: pact_ffi::verifier::pactffi_verifier_add_directory_source FFI function invoked
2023-04-03T05:41:46.952030Z DEBUG ThreadId(01) pact_ffi::verifier: pact_ffi::verifier::pactffi_verifier_execute FFI function invoked
2023-04-03T05:41:46.952033Z DEBUG ThreadId(01) pact_ffi::verifier::handle: Pact source to verify = Dir(/home/myname/Projects/pact-php-csv/example/provider/tests/Contract/../../../broker/pacts)
2023-04-03T05:41:46.952639Z DEBUG ThreadId(01) pact_plugin_driver::catalogue_manager: Updated catalogue entries:
core/content-generator/binary
core/content-generator/json
core/content-matcher/json
core/content-matcher/multipart-form-data
core/content-matcher/text
core/content-matcher/xml
2023-04-03T05:41:46.952667Z DEBUG ThreadId(01) pact_plugin_driver::catalogue_manager: Updated catalogue entries:
core/matcher/v1-equality
core/matcher/v2-max-type
core/matcher/v2-min-type
core/matcher/v2-minmax-type
core/matcher/v2-regex
core/matcher/v2-type
core/matcher/v3-content-type
core/matcher/v3-date
core/matcher/v3-datetime
core/matcher/v3-decimal-type
core/matcher/v3-includes
core/matcher/v3-integer-type
core/matcher/v3-null
core/matcher/v3-number-type
core/matcher/v3-time
core/matcher/v4-array-contains
core/matcher/v4-equals-ignore-order
core/matcher/v4-max-equals-ignore-order
core/matcher/v4-min-equals-ignore-order
core/matcher/v4-minmax-equals-ignore-order
core/matcher/v4-not-empty
core/matcher/v4-semver
2023-04-03T05:41:46.952718Z DEBUG ThreadId(01) pact_verifier: Scanning "/home/myname/Projects/pact-php-csv/example/provider/tests/Contract/../../../broker/pacts"
2023-04-03T05:41:46.952871Z INFO ThreadId(01) pact_verifier: Pact file requires plugins, will load those now
2023-04-03T05:41:46.952881Z DEBUG ThreadId(01) pact_plugin_driver::plugin_manager: Loading plugin PluginDependency { name: "csv", version: Some("0.0"), dependency_type: Plugin }
2023-04-03T05:41:46.952894Z DEBUG ThreadId(01) pact_plugin_driver::plugin_manager: Did not find plugin, will start it
2023-04-03T05:41:46.952896Z DEBUG ThreadId(01) pact_plugin_driver::plugin_manager: Loading plugin manifest for plugin PluginDependency { name: "csv", version: Some("0.0"), dependency_type: Plugin }
2023-04-03T05:41:46.952902Z DEBUG ThreadId(01) pact_plugin_driver::plugin_manager: Looking for plugin in "/home/myname/.pact/plugins"
2023-04-03T05:41:46.953001Z DEBUG ThreadId(01) pact_ffi::verifier: pact_ffi::verifier::pactffi_verifier_shutdown FFI function invoked
F 1 / 1 (100%)
Time: 00:00.080, Memory: 28.32 MB
There was 1 failure:
1) App\Provider\Tests\Contract\PactVerifyTest::testPactVerifyConsumer
Failed asserting that false is true.
/home/myname/Projects/pact-php-csv/example/provider/tests/Contract/PactVerifyTest.php:58
FAILURES!
Tests: 1, Assertions: 1, Failures: 1.
I think it should log an error message like:
Can't find plugin csv in /home/myname/.pact/plugins
Do you think so?Jordan Brooks
04/18/2023, 1:23 PMAdam Cox
04/28/2023, 2:18 PMws
and wss
connections, mostly to providers at the moment but it may be that we need it for consumers also. Currently our plugin just adds one "transport" to the catalogue: websockets
. But this means that when verifying contracts there is no way to tell the pact-standalone-verifier to use a wss
scheme when connecting to the provider server.
We noticed that the ProviderInfo
struct has a scheme
field which looks like it would be perfect for our use case but the pact-standalone-verifier does not expose this option. Looking at the source code here [1] it looks like it used to, but this is not listed in the docs a the top.
We considered having the plugin create two transports ws
and wss
but this then meant that the consumer would have to determine which transport to choose so that it is written into the contract. We weren't sure if this was correct as it doesn't really matter for the contract contents if the connection is secure or not. Also we wanted to avoid consumer users from having to create self-signed certs to create contracts unless they really wanted to test with the mock server over wss.
Guidance as to the intended approach would be most appreciated 🙂
Side, but related, note: in pact-consumer it looks like tls
is hard-coded to false [2]. Why is that? Has this not been implemented yet or are secure connections supposed to be solved a different way?
[1] https://github.com/pact-foundation/pact-reference/blob/master/rust/pact_verifier_cli/src/main.rs#L673
[2] https://github.com/pact-foundation/pact-reference/blob/master/rust/pact_consumer/src/mock_server/plugin_mock_server.rs#L64Adam Cox
05/09/2023, 1:28 PM<ws://localhost:9998/jsonrpc>
- specifically the /jsonrpc
bit
• Headers to send in the connection request
• Message payload encoding as text or binary
We are using synchronous message contracts to do the verification and we are trying to extend the plugin so that these metadata properties can be set, however we are struggling to find the code path that allows plugin config to be added to the contract files when a core matcher is being used.
Advice/guidance on how to achieve this would be greatly appreciatedAdam Cox
06/02/2023, 9:51 AM"request": { "id": 1 },
The configure interaction request receives a payload like this:
"request": Value { kind: Some(StructValue(Struct { fields: {"id": Value { kind: Some(NumberValue(1.0)) } } })) }
Now in the contract the the value to match against is 1.0
and not 1
. In the consumer test a message is sent to the mock server with the payload:
{
"id": 1
}
When the mock server receives this request we try to match against all interactions in the pact but we get a mismatch for this field as:
1.1) [$.id] Expected '0.0' to be equal to '0'
I have been trying to debug and fix this issue and it looks to me like the following is happening:
1. The pact framework is taking the consumer contract and converting it to a protobuf payload to send to the plugin
2. This process converted the id field to a Value:Kind:Number(&f64)
3. In the plugin we decode the protobuf payload using proto_value_to_json
(I think I took this directly from your protobuf plugin) and for a number Kind it runs: serde_json::json!(n)
4. serde is seeing the f64 and creating a Value::Number(Number::Float))
5. So now we have lost the information that the original number was an int and not a float and our comparison fails when we receive an int
It seems to me that serde has a good way of handling the different number types but the prost_types definition of Kind::NumberValue(f64),
is reducing the amount of information that can be conveyed to the plugin about a numeric field during the configure interaction request.
I had a search online around protobuf number types and it looked like different types of numbers are supported so I'm not understanding why prost_types treats all numbers as floats. I am not very familiar with protobuf at all though so I probably am just missing something.
In the mean time we are encouraging the users to define the contract as { "id": "matching(integer, 1)" }
but I think it should be possible for them to just specify the contract as { "id": 1 }
and have it work. This did work when we were using the core application/json matcher but I am assuming that is because the type information is not lost when passing the values around in rust.Adam Cox
06/14/2023, 1:51 PMAdam Cox
06/14/2023, 2:44 PM1) c9d8b50f42b5d1e7 - the following mismatches occurred:
1.1) [] Expected metadata key 'headers' to have value '{"sec-websocket-protocol":"json-rpc"}' but was '{"connection":"upgrade","host":"[::1]:64257","sec-websocket-key":"qtwa71ue1dhx8b0ffbiqyw==","sec-websocket-protocol":"json-rpc","sec-websocket-version":"13","upgrade":"websocket"}' - Expected '{"sec-websocket-protocol":"json-rpc"}' to be equal to '{"connection":"upgrade","host":"[::1]:64257","sec-websocket-key":"qtwa71ue1dhx8b0ffbiqyw==","sec-websocket-protocol":"json-rpc","sec-websocket-version":"13","upgrade":"websocket"}'
The contract specifies the "sec-websocket-protocol":"json-rpc"
header, but the request comes in with a lot of others. We only need the one header validated in the contract. The connection request we are establishing has the header and it has the correct value so this should pass. However as the contract doesn't contain all the other headers it fails.
I'd like to make the matching work like the header matching in HTTP contracts, however I want the headers in an object called headers and not on the root of the metadata object. This is because we are now trying to add query params as well and I'd like to keep the two separate.uglyog
Praveen Erode Mohanasundaram
07/14/2023, 2:15 PMPraveen Erode Mohanasundaram
07/14/2023, 2:15 PMPraveen Erode Mohanasundaram
07/14/2023, 2:19 PMRohit Krishnan
07/25/2023, 8:39 PMYousaf Nabi (pactflow.io)
Elena Doty
08/16/2023, 8:42 PMChristopher Tonog
01/29/2024, 6:06 PMBecca Liss
02/28/2024, 3:41 PMconsumerVersionSelectors: [{ branch: 'main' }]
, but when I use consumerVersionSelectors: [{ branch: 'feature-branch' }]
I get an error about not being able to find the protobuf plugin thinking2James Demaine
03/04/2024, 11:39 AMpact_ffi::plugins: Failed to call out to plugin - Request to configure interaction failed: Failed to process protobuf: Failed to invoke protoc binary: exit code exit status: 1
back when running it. I've checked in the plugins dir that it has actually downloaded protoc
and the executable is accessible - any help would be appreciated!s1apped
05/06/2024, 4:22 PMs1apped
05/06/2024, 4:23 PMBecca Liss
07/09/2024, 3:09 PMsyntax = "proto3";
package vts.central_entities.v1.service;
import "buf/validate/validate.proto"; // global package (from <https://github.com/bufbuild/protoc-gen-validate> I believe)
import "vts/central_entities/v1/service/entity.proto"; // local proto file
when I run the pact test, I get this error
2024-07-09T15:33:55.572407Z DEBUG tokio-runtime-worker pact_plugin_driver::child_process: Plugin(protobuf, 64004, STDOUT) || 2024-07-09T15:33:55.572237Z DEBUG tokio-runtime-worker Connection{peer=Server}: h2::codec::framed_write: send frame=Settings { flags: (0x1: ACK) }
2024-07-09T15:33:55.572411Z DEBUG tokio-runtime-worker pact_plugin_driver::child_process: Plugin(protobuf, 64004, STDOUT) || 2024-07-09T15:33:55.572258Z DEBUG tokio-runtime-worker Connection{peer=Server}: h2::codec::framed_read: received frame=WindowUpdate { stream_id: StreamId(0), size_increment: 5177345 }
2024-07-09T15:33:55.572488Z DEBUG ffi-setup_contents Connection{peer=Client}: h2::codec::framed_read: received frame=Settings { flags: (0x0), initial_window_size: 1048576, max_frame_size: 16384, max_header_list_size: 16777216 }
2024-07-09T15:33:55.572511Z DEBUG ffi-setup_contents Connection{peer=Client}: h2::codec::framed_write: send frame=Settings { flags: (0x1: ACK) }
2024-07-09T15:33:55.572519Z DEBUG ffi-setup_contents Connection{peer=Client}: h2::codec::framed_read: received frame=Settings { flags: (0x1: ACK) }
2024-07-09T15:33:55.572523Z DEBUG ffi-setup_contents Connection{peer=Client}: h2::proto::settings: received settings ACK; applying Settings { flags: (0x0), enable_push: 0, initial_window_size: 2097152, max_frame_size: 16384 }
2024-07-09T15:33:55.572532Z DEBUG ffi-setup_contents Connection{peer=Client}: h2::codec::framed_read: received frame=WindowUpdate { stream_id: StreamId(0), size_increment: 983041 }
2024-07-09T15:33:55.572558Z DEBUG ffi-setup_contents tower::buffer::worker: service.ready=true processing request
2024-07-09T15:33:55.572500Z DEBUG tokio-runtime-worker pact_plugin_driver::child_process: Plugin(protobuf, 64004, STDOUT) || 2024-07-09T15:33:55.572292Z DEBUG tokio-runtime-worker Connection{peer=Server}: h2::codec::framed_write: send frame=WindowUpdate { stream_id: StreamId(0), size_increment: 983041 }
2024-07-09T15:33:55.572670Z DEBUG tokio-runtime-worker pact_plugin_driver::child_process: Plugin(protobuf, 64004, STDOUT) || 2024-07-09T15:33:55.572610Z DEBUG tokio-runtime-worker Connection{peer=Server}: h2::codec::framed_read: received frame=Settings { flags: (0x1: ACK) }
2024-07-09T15:33:55.572680Z DEBUG tokio-runtime-worker pact_plugin_driver::child_process: Plugin(protobuf, 64004, STDOUT) || 2024-07-09T15:33:55.572630Z DEBUG tokio-runtime-worker Connection{peer=Server}: h2::proto::settings: received settings ACK; applying Settings { flags: (0x0), initial_window_size: 1048576, max_frame_size: 16384, max_header_list_size: 16777216 }
2024-07-09T15:33:55.572879Z DEBUG ffi-setup_contents Connection{peer=Client}: h2::codec::framed_write: send frame=Headers { stream_id: StreamId(1), flags: (0x4: END_HEADERS) }
2024-07-09T15:33:55.572911Z DEBUG ffi-setup_contents Connection{peer=Client}: h2::codec::framed_write: send frame=Data { stream_id: StreamId(1) }
2024-07-09T15:33:55.572941Z DEBUG ffi-setup_contents Connection{peer=Client}: h2::codec::framed_write: send frame=Data { stream_id: StreamId(1), flags: (0x1: END_STREAM) }
2024-07-09T15:33:55.573393Z DEBUG tokio-runtime-worker pact_plugin_driver::child_process: Plugin(protobuf, 64004, STDOUT) || 2024-07-09T15:33:55.573033Z DEBUG tokio-runtime-worker Connection{peer=Server}: h2::codec::framed_read: received frame=Headers { stream_id: StreamId(1), flags: (0x4: END_HEADERS) }
2024-07-09T15:33:55.573405Z DEBUG tokio-runtime-worker pact_plugin_driver::child_process: Plugin(protobuf, 64004, STDOUT) || 2024-07-09T15:33:55.573073Z DEBUG tokio-runtime-worker Connection{peer=Server}: h2::codec::framed_read: received frame=Data { stream_id: StreamId(1) }
2024-07-09T15:33:55.573410Z DEBUG tokio-runtime-worker pact_plugin_driver::child_process: Plugin(protobuf, 64004, STDOUT) || 2024-07-09T15:33:55.573092Z DEBUG tokio-runtime-worker Connection{peer=Server}: h2::codec::framed_read: received frame=Data { stream_id: StreamId(1), flags: (0x1: END_STREAM) }
2024-07-09T15:33:55.573415Z DEBUG tokio-runtime-worker pact_plugin_driver::child_process: Plugin(protobuf, 64004, STDOUT) || 2024-07-09T15:33:55.573150Z DEBUG tokio-runtime-worker request{method=POST uri=<http://127.0.0.1:63892/io.pact.plugin.PactPlugin/ConfigureInteraction> version=HTTP/2.0 headers={"te": "trailers", "content-type": "application/grpc", "authorization": Sensitive, "user-agent": "tonic/0.9.2"}}: tower_http::trace::on_request: started processing request
2024-07-09T15:33:55.573421Z DEBUG tokio-runtime-worker pact_plugin_driver::child_process: Plugin(protobuf, 64004, STDOUT) || 2024-07-09T15:33:55.573250Z DEBUG tokio-runtime-worker request{method=POST uri=<http://127.0.0.1:63892/io.pact.plugin.PactPlugin/ConfigureInteraction> version=HTTP/2.0 headers={"te": "trailers", "content-type": "application/grpc", "authorization": Sensitive, "user-agent": "tonic/0.9.2"}}: pact_protobuf_plugin::server: Configure interaction request for content type 'application/grpc': ConfigureInteractionRequest { content_type: "application/grpc", contents_config: Some(Struct { fields: {"additionalIncludes": Value { kind: Some(ListValue(ListValue { values: [Value { kind: Some(StringValue("/Users/becca.liss/Code/monorepo/apps/central-entities/service/idl/protobuf/vts/central_entities/v1/service")) }] })) }, "pact:content-type": Value { kind: Some(StringValue("application/protobuf")) }, "pact:proto": Value { kind: Some(StringValue("/Users/becca.liss/Code/monorepo/apps/central-entities/service/idl/protobuf/vts/central_entities/v1/service/service_commands.proto")) }, "pact:proto-service": Value { kind: Some(StringValue("CommandService/UpsertEntity")) } ...STUFF }
2024-07-09T15:33:55.669983Z DEBUG tokio-runtime-worker pact_plugin_driver::child_process: Plugin(protobuf, 64004, STDOUT) || 2024-07-09T15:33:55.669623Z DEBUG tokio-runtime-worker request{method=POST uri=<http://127.0.0.1:63892/io.pact.plugin.PactPlugin/ConfigureInteraction> version=HTTP/2.0 headers={"te": "trailers", "content-type": "application/grpc", "authorization": Sensitive, "user-agent": "tonic/0.9.2"}}: pact_protobuf_plugin::protoc: Detected OS: Mac OS 14.5.0 [64-bit]
2024-07-09T15:33:55.670174Z DEBUG tokio-runtime-worker pact_plugin_driver::child_process: Plugin(protobuf, 64004, STDOUT) || 2024-07-09T15:33:55.670124Z DEBUG tokio-runtime-worker request{method=POST uri=<http://127.0.0.1:63892/io.pact.plugin.PactPlugin/ConfigureInteraction> version=HTTP/2.0 headers={"te": "trailers", "content-type": "application/grpc", "authorization": Sensitive, "user-agent": "tonic/0.9.2"}}: pact_protobuf_plugin::protoc: Found unpacked protoc binary
2024-07-09T15:33:55.670190Z DEBUG tokio-runtime-worker pact_plugin_driver::child_process: Plugin(protobuf, 64004, STDOUT) || 2024-07-09T15:33:55.670153Z DEBUG tokio-runtime-worker request{method=POST uri=<http://127.0.0.1:63892/io.pact.plugin.PactPlugin/ConfigureInteraction> version=HTTP/2.0 headers={"te": "trailers", "content-type": "application/grpc", "authorization": Sensitive, "user-agent": "tonic/0.9.2"}}: pact_protobuf_plugin::protoc: Invoking protoc: './protoc/bin/protoc --version'
2024-07-09T15:33:55.727713Z DEBUG tokio-runtime-worker pact_plugin_driver::child_process: Plugin(protobuf, 64004, STDOUT) || 2024-07-09T15:33:55.727643Z DEBUG tokio-runtime-worker request{method=POST uri=<http://127.0.0.1:63892/io.pact.plugin.PactPlugin/ConfigureInteraction> version=HTTP/2.0 headers={"te": "trailers", "content-type": "application/grpc", "authorization": Sensitive, "user-agent": "tonic/0.9.2"}}: pact_protobuf_plugin::protoc: Protoc binary invoked OK: libprotoc 3.21.12
2024-07-09T15:33:55.727762Z DEBUG tokio-runtime-worker pact_plugin_driver::child_process: Plugin(protobuf, 64004, STDOUT) ||
2024-07-09T15:33:55.727776Z DEBUG tokio-runtime-worker pact_plugin_driver::child_process: Plugin(protobuf, 64004, STDOUT) || 2024-07-09T15:33:55.727715Z DEBUG tokio-runtime-worker request{method=POST uri=<http://127.0.0.1:63892/io.pact.plugin.PactPlugin/ConfigureInteraction> version=HTTP/2.0 headers={"te": "trailers", "content-type": "application/grpc", "authorization": Sensitive, "user-agent": "tonic/0.9.2"}}: pact_protobuf_plugin::protobuf: Parsing proto file '/Users/becca.liss/Code/monorepo/apps/central-entities/service/idl/protobuf/vts/central_entities/v1/service/service_commands.proto'
2024-07-09T15:33:55.728166Z DEBUG tokio-runtime-worker pact_plugin_driver::child_process: Plugin(protobuf, 64004, STDOUT) || 2024-07-09T15:33:55.728111Z DEBUG tokio-runtime-worker request{method=POST uri=<http://127.0.0.1:63892/io.pact.plugin.PactPlugin/ConfigureInteraction> version=HTTP/2.0 headers={"te": "trailers", "content-type": "application/grpc", "authorization": Sensitive, "user-agent": "tonic/0.9.2"}}: pact_protobuf_plugin::protoc: Invoking protoc: Command { std: "./protoc/bin/protoc" "-o/Users/becca.liss/.pact/plugins/protobuf-0.4.0/tmp/.tmp1ER5tw" "-I/Users/becca.liss/Code/monorepo/apps/central-entities/service/idl/protobuf/vts/central_entities/v1/service" "--include_imports" "/Users/becca.liss/Code/monorepo/apps/central-entities/service/idl/protobuf/vts/central_entities/v1/service/service_commands.proto" "-Iprotoc/include", kill_on_drop: false }
2024-07-09T15:33:55.739710Z DEBUG tokio-runtime-worker pact_plugin_driver::child_process: Plugin(protobuf, 64004, STDOUT) || 2024-07-09T15:33:55.739648Z ERROR tokio-runtime-worker request{method=POST uri=<http://127.0.0.1:63892/io.pact.plugin.PactPlugin/ConfigureInteraction> version=HTTP/2.0 headers={"te": "trailers", "content-type": "application/grpc", "authorization": Sensitive, "user-agent": "tonic/0.9.2"}}: pact_protobuf_plugin::protoc: Protoc output:
2024-07-09T15:33:55.739739Z DEBUG tokio-runtime-worker pact_plugin_driver::child_process: Plugin(protobuf, 64004, STDOUT) || 2024-07-09T15:33:55.739688Z ERROR tokio-runtime-worker request{method=POST uri=<http://127.0.0.1:63892/io.pact.plugin.PactPlugin/ConfigureInteraction> version=HTTP/2.0 headers={"te": "trailers", "content-type": "application/grpc", "authorization": Sensitive, "user-agent": "tonic/0.9.2"}}: pact_protobuf_plugin::protoc: Protoc stderr: buf/validate/validate.proto: File not found.
2024-07-09T15:33:55.739772Z DEBUG tokio-runtime-worker pact_plugin_driver::child_process: Plugin(protobuf, 64004, STDOUT) || vts/central_entities/v1/service/entity.proto: File not found.
I verified that the additionalIncludes
paths seem correct (added in the Pact struct as suggested here).
tldr: it seems like protoc
/ pact_protobuf_plugin
is not able to handle protobuf imports. Any help would be hugely appreciated, thank you!Becca Liss
07/24/2024, 2:31 PM.UsingPlugin
returns a SynchronousMessageWithPlugin
type, which only allows .WithContents
to be called on it; since .WithContents
takes a stringified blob of JSON, I assume it doesn't support using matchers (e.g.). If someone can verify that understanding and/or help me come up with an alternative solution, that would be great!Becca Liss
08/05/2024, 3:33 PMstruct
field, e.g.
message Request {
string name = 1;
google.protobuf.Struct params = 2;
}
In my test, I am creating a new struct
params, err := structpb.NewStruct(map[string]any{"kind": "general", "message": "test" })
and then marshaling it to JSON. The string I am passing to withContents
looks like this
{
"pact:proto": "whatever.proto",
"pact:proto-service": "Service/Endpoint",
"pact:content-type": "application/protobuf",
"request": {
"name": "name",
"params": {
"kind": "general",
"message": "test"
}
},
"response": {
"responses": [
{
"success": true,
"id": "test123"
}
]
}
}
I run the test once and get this error
Received generate templates error rpc error: code = FailedPrecondition desc = Failed to match the request message - BodyMismatches({"$.params": [BodyMismatch { path: "$.params.fields.key", expected: Some(b"\"message\""), actual: Some(b"\"kind\""), mismatch: "Expected 'kind' (String) to be equal to 'message' (String)" }, BodyMismatch { path: "$.params.fields.value.string_value", expected: Some(b"\"test\""), actual: Some(b"\"general\""), mismatch: "Expected 'general' (String) to be equal to 'test' (String)" }]})
and then I run the test again (changing nothing, with exact same contents string) and it passesFeisal Ahmad
11/29/2024, 9:20 PMpactffi_using_plugin
and passing in the handle, and it actually loads the plugin and calls InitPlugin
, but now I’m at a loss…
My assumption is the pact-cplusplus is so far out of date it doesn’t actually call any of the methods in the ffi interface to result in the plugin being called with ConfigureInteraction
, StartMockServer
, etc. Is that a correct assumption?
Where can I find some example code to follow for setting up a transport plugin, so I can figure out what the C++ wrapper should look like to work with plugins?Feisal Ahmad
12/11/2024, 2:54 PM/// Start a new plugin mock server (async version). This will send the start mock server request
/// to the plugin that provides the mock server.
pub async fn start_async(
pact: Box<dyn Pact + Send + Sync>,
output_path: Option<PathBuf>,
catalogue_entry: &CatalogueEntry
) -> anyhow::Result<Box<dyn ValidatingMockServer>> {
let test_context = hashmap!{};
let result = start_mock_server_v2(catalogue_entry, pact.boxed(), MockServerConfig {
output_path: output_path.clone(),
host_interface: None,
port: 0,
tls: false
}, test_context).await?;
Ok(Box::new(PluginMockServer {
mock_server_details: result,
pact: pact.boxed(),
output_path: output_path.clone(),
catalogue_entry: catalogue_entry.clone()
}))
}
It looks like the test_context isn’t hooked up yet to receive the value from the call to pactffi_create_mock_server_for_transport
?Feisal Ahmad
01/31/2025, 11:47 AMpact_verifier_cli
to verify the pact I have now managed to produce using pactffi with the plugin I wrote to add a custom transport as I described before.
I don’t know if I’m just expecting the wrong thing here, but what I hope is possible is to do the following:
1. Run pact_verifier_cli
pointing it to the pact file (I’m just using a local file for now)
2. pact_verifier_cli
loads the plugin and registers a custom transport
3. pact_verifier_cli
verifies the interactions by sending requests over the custom transport, I imagine this would be implemented by the various interaction related rpcs in the plugin service
So far I am seeing in the trace logs of the cli that it tries to send requests directly, ignoring the plugin. I’ve tried several arguments but haven’t gotten anywhere really. It’s loading the plugin fine, which is getting picked up from the pact file, and I see it in the printed catalogue entries:
2025-01-31T11:35:33.117935Z DEBUG main verify_provider{provider_name="provider"}: pact_plugin_driver::catalogue_manager: Updated catalogue entries:
core/content-generator/binary
...
core/matcher/v4-semver
plugin/pact-messagebroker/transport/application/adsk_MessageBroker
Is what I’m trying to do supported? Or do I need to use pactffi to implement the provider tests?