{"id":22772342,"url":"https://github.com/pactflow/pact-protobuf-plugin","last_synced_at":"2025-08-23T14:32:14.539Z","repository":{"id":43489611,"uuid":"414445960","full_name":"pactflow/pact-protobuf-plugin","owner":"pactflow","description":"Pact plugin for Protobufs and gRPC","archived":false,"fork":false,"pushed_at":"2025-08-19T23:45:44.000Z","size":1625,"stargazers_count":17,"open_issues_count":9,"forks_count":12,"subscribers_count":8,"default_branch":"main","last_synced_at":"2025-08-20T01:22:28.779Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pactflow.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2021-10-07T03:16:04.000Z","updated_at":"2025-08-19T23:45:48.000Z","dependencies_parsed_at":"2023-11-08T05:54:16.045Z","dependency_job_id":"88597b56-691c-4550-b518-44c91acb180c","html_url":"https://github.com/pactflow/pact-protobuf-plugin","commit_stats":null,"previous_names":[],"tags_count":56,"template":false,"template_full_name":null,"purl":"pkg:github/pactflow/pact-protobuf-plugin","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pactflow%2Fpact-protobuf-plugin","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pactflow%2Fpact-protobuf-plugin/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pactflow%2Fpact-protobuf-plugin/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pactflow%2Fpact-protobuf-plugin/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pactflow","download_url":"https://codeload.github.com/pactflow/pact-protobuf-plugin/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pactflow%2Fpact-protobuf-plugin/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":271752100,"owners_count":24814745,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-23T02:00:09.327Z","response_time":69,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-12-11T17:08:11.823Z","updated_at":"2025-08-23T14:32:14.502Z","avatar_url":"https://github.com/pactflow.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ca href=\"https://pactflow.io\"\u003e\u003cimg src=\"docs/pactflow-logo-s.png\" alt=\"pactflow logo\" height=\"60px\" align=\"right\"\u003e\u003c/a\u003e\n\n# Pact Protobuf/gRPC Plugin [![Pact-Protobuf-Plugin Build](https://github.com/pactflow/pact-protobuf-plugin/actions/workflows/build.yml/badge.svg)](https://github.com/pactflow/pact-protobuf-plugin/actions/workflows/build.yml)\n\n\u003e Pact plugin for testing messages and gRPC service calls encoded with as [Protocol buffers](https://developers.google.com/protocol-buffers)\n\u003e using the [Pact](https://docs.pact.io) contract testing framework.\n\n## About this plugin\n\nThis plugin provides support for matching and verifying Protobuf messages and gRPC service calls. It fits into the\n[Pact contract testing framework](https://docs.pact.io) and extends Pact testing for [Protocol buffer](https://developers.google.com/protocol-buffers) \npayloads and gRPC. \n\n## Table of Content\n\n- [Requirements to use it](#requirements-to-use-it)\n- [Installation](#installation)\n  - [Installing the plugin](#installing-the-plugin)\n  - [Installing the Protocol buffer protoc compiler](#installing-the-protocol-buffer-protoc-compiler) \n- [Supported features](#supported-features)\n- [Unsupported features](#unsupported-features)\n- [Using the plugin](#using-the-plugin)\n    - [Testing an interaction with a single Protobuf message](#testing-an-interaction-with-a-single-protobuf-message)\n    - [Testing a gRPC service interaction](#testing-a-grpc-service-interaction)\n- [Support](#support)\n- [Contributing to the plugin](#contributing)\n- [Development Roadmap](#development-roadmap)\n\n## Requirements to use it\n\nThis plugin provides matching and verification of Protobuf proto3 encoded messages and gRPC service methods to the Pact\ncontract testing framework. It requires a version of the Pact framework that supports the [V4 Pact specification](https://github.com/pact-foundation/pact-specification/tree/version-4) \nas well as the [Pact plugin framework](https://github.com/pact-foundation/pact-plugins).\n\nSupported Pact framework versions:\n- [Pact-JVM v4.4.x](https://github.com/pact-foundation/pact-jvm)\n- [Pact-Rust Consumer v0.9.x](https://github.com/pact-foundation/pact-reference/tree/master/rust/pact_consumer)\n- [Pact-Rust Verifier v0.9.x](https://github.com/pact-foundation/pact-reference/tree/master/rust/pact_verifier_cli)\n- [Pact-Go v2.0.0-beta](https://github.com/pact-foundation/pact-go)\n\nTo support compiling Protocol Buffer proto files requires a version of the [Protocol Buffer compiler](https://github.com/protocolbuffers/protobuf).\n\n## Installation\n\nThe executable binaries and plugin manifest file for the plugin can be downloaded from the project [releases page](../../releases). \nThere will be an executable for each operating system and architecture. If your particular operating system or \narchitecture is not supported, please send a request to [support@pactflow.io](support@pactflow.io) with the details.\n\n### Installing the plugin\nTo install the plugin requires the plugin executable binary as well as the plugin manifest file to be unpacked/copied into\na Pact plugin directory. By default, this will be `.pact/plugins/protobuf-\u003cversion\u003e` in the home directory (i.e. \n`$HOME/.pact/plugins/protobuf-0.1.5` for version 0.1.5).\n\n#### Installing the plugin using the pact-plugin-cli\n\nThe [pact-plugin-cli](https://github.com/pact-foundation/pact-plugins/tree/main/cli) can be used to install the Protobuf/gRPC\nplugin. See the [CLI installation](https://github.com/pact-foundation/pact-plugins/tree/main/cli#installing) on how to install it.\n\nTo install the latest version, run\n\n```shell\npact-plugin-cli -y install https://github.com/pactflow/pact-protobuf-plugin/releases/latest\n```\n\n#### Manually installing the plugin\n\nExample installation of Linux version 0.1.5 (replace with the actual version you are using): \n1. Create the plugin directory if needed: `mkdir -p ~/.pact/plugins/protobuf-0.1.5`\n2. Download the plugin manifest into the directory: `wget https://github.com/pactflow/pact-protobuf-plugin/releases/download/v-0.1.5/pact-plugin.json -O ~/.pact/plugins/protobuf-0.1.3/pact-plugin.json`\n3. Download the plugin executable into the directory: `wget https://github.com/pactflow/pact-protobuf-plugin/releases/download/v-0.1.5/pact-protobuf-plugin-linux-x86_64.gz  -O ~/.pact/plugins/protobuf-0.1.5/pact-protobuf-plugin.gz`\n4. Unpack the plugin executable: `gunzip -N ~/.pact/plugins/protobuf-0.1.5/pact-protobuf-plugin.gz`\n5. Make the plugin executable: `chmod +x ~/.pact/plugins/protobuf-0.1.5/pact-protobuf-plugin`\n\n**Note:** The unpacked executable name must match the `entryPoint` value in the manifest file. By default, this is\n`pact-protobuf-plugin` on unix* and `pact-protobuf-plugin.exe` on Windows.\n\n#### Overriding the default Pact plugin directory\n\nThe default plugin directory (`$HOME/.pact/plugins`) can be changed by setting the `PACT_PLUGIN_DIR` environment variable.\n\n### Installing the Protocol buffer protoc compiler\n\nThe plugin can automatically download the correct version of the Protocol buffer compiler for the current operating system\nand architecture. By default, it will download the compiler from https://github.com/protocolbuffers/protobuf/releases\nand then unpack it into the plugin's installation directory.\n\nThe plugin executes the following steps:\n\n1. Look for a valid `protoc/bin/protoc` in the plugin installation directory\n2. If not found, look for a `protoc-{version}-{OS}.zip` in the plugin installation directory and unpack that (i.e. for Linux it will look for `protoc-3.19.1-linux-x86_64.zip`).\n3. If not found, try download protoc using the `downloadUrl` entry in the plugin manifest file\n4. Otherwise, fallback to using the system installed protoc\n\n#### Dealing with network and firewall issues\n\nIf the plugin is going to run in an environment that does not allow automatic downloading of files, then you can do any of the following:\n\n1. Download the protoc archive and place it in the plugin installation directory. It will need to be the correct version and operating system/architecture.\n2. Download the protoc archive and unpack it into the plugin installation directory. It will need to be in a `protoc` directory. _Do this if the current version is not supported for your operating system/architecture._\n3. Change the `downloadUrl` entry in the plugin manifest to point to a location that the file can be downloaded from.\n4. Install the correct version of the protoc compiler as an operating system package. It must then be on the executable path when the plugin runs. For instance, for Alpine Linux this will need to be done as the downloaded versions will not work.\n\n## Logging\n\n_NOTE: Since 0.1.3, the logging was switched to the Rust tracing crate and a log configuration file is no longer supported._ \n\nThe plugin will log to both standard output and two files (log/plugin.log.* and log/plugin.log.json.*) in the plugin \ninstallation directory. Each file will be rolled per day and be suffixed with the current date. The JSON log file will\nbe formatted in the [bunyan format](https://github.com/trentm/node-bunyan). The log level will be set by the `LOG_LEVEL`\nenvironment variable that is passed into the plugin process (this should be set by the framework calling it).\n\n## Configuration\n\nThe Protobuf plugin supports the following configuration options, which can be set in the plugin manifest file under\n`pluginConfig`:\n\n#### `protocVersion` [string]\n\nThe Protobuf compiler version to download if required.\n\n#### `downloadUrl` [string]\n\nThe URL to download the Protobuf compiler from. By default, this will be the Protocol Buffers GitHub release page.\n\n#### `hostToBindTo` [string]\n\nHost to bind to. Default is the IP4 loopback adapter `127.0.0.1`, to use the IP6 loopback set it to `::1`. \n\n#### `additionalIncludes` [string or list\\\u003cstring\\\u003e]\n\nAdditional directories to include to add to the Protocol buffers compiler to search for proto files. Each value will be\nadded verbatim to the protoc command line using `-I`. **THESE ARE DIRECTORIES NOT FILES!**\n\n### Specifying configuration values in the tests\n\n*Version 0.2.4+*\n\nConfiguration values can also be passed in from the test. They need to be passed in via the [test configuration data](#the-protobuf-test-configuration)\nunder the `pact:protobuf-config` key. For example, to add additional proto file include directories in the test:\n\n```java\n  \"pact:proto\", filePath(\"../proto/test_enum.proto\"),\n  \"pact:content-type\", \"application/grpc\",\n  \"pact:proto-service\", \"Test/GetFeature\",\n  \"pact:protobuf-config\", Map.of(\n    \"additionalIncludes\", List.of(filePath(\"../proto2\"))\n  )\n```\n\n## Supported features\n\nThe plugin currently supports proto3 formatted messages and service calls.\n\nIt supports the following:\n* Scalar fields (Double, Float, Int64, Uint64, Int32, Uint32, Fixed64, Fixed32, Bool, Sfixed32, Sfixed64, Sint32, Sint64).\n* Variable length fields (String, Bytes).\n* Enum fields.\n* Embedded messages.\n* Map fields (with a string key).\n* Repeated fields.\n* Packed repeated fields.\n* oneOf fields.\n* gRPC Service method calls. \n* Testing/verifying gRPC service call metadata.\n* Verifying gRPC error responses.  \n\n## Unsupported features\n\nThe following features are currently unsupported, but may be supported in a later release:\n* Map fields with scalar keys.\n* Map fields with enum keys.\n* default values for fields.\n* required fields (note that this is deprecated in Proto 3).\n* Testing/verifying Protobuf options.\n\nThe following features will **not** be supported by this plugin:\n* proto2\n* Groups\n\nThe following features may be supported in a future release, but are not currently planned to be supported:\n* Map fields where the key is not a string or scalar value.\n* gRPC streaming (either oneway or bidirectional).\n\n## Using the plugin\n\nThis plugin will register itself with the Pact framework for the `application/protobuf` and `application/gRPC` content types.\n\nUsing this plugin, you can write Pact tests that verify either a single Protobuf message (i.e. a message provider sends\na single, or one-shot, message to a consumer), or you can verify a service method call where there is an input message \nand an output message.\n\nSingle message tests are supported by using the V4 asynchronous message Pact format, and the service method calls use the\nV4 synchronous message Pact format.\n\n### Testing an interaction with a single Protobuf message\n\nFor an overview how asynchronous messages work with Pact, see [Non-HTTP testing (Message Pact)](https://docs.pact.io/getting_started/how_pact_works/#non-http-testing-message-pact).\n\nIn this scenario, a message provider writes a Protocol Buffer message to some one-way transport mechanism, like a \nmessage queue, and a consumer then reads it. With this style of testing, the transport mechanism is abstracted away.\n\n#### Protocol Buffer message consumer\n\nThe message consumer test is written using the Pact Message test DSL. The test DSL defines the expected message format,\nand then the consumer is tested with an example message generated by the test framework.\n\nFor an example of a message consumer test:\n* [Java example consumer test](https://github.com/pact-foundation/pact-plugins/blob/main/examples/protobuf/protobuf-consumer-jvm/src/test/java/io/pact/example/protobuf/provider/PactConsumerTest.java)\n* [Rust example consumer test](https://github.com/pact-foundation/pact-plugins/blob/main/examples/protobuf/protobuf-consumer-rust/src/lib.rs)\n\n#### Verifying the message provider\n\nThe message provider is verified by getting it to generate a message, and then this is verified against the Pact file\nfrom the consumer. There are two main ways of verifying the provider:\n\n1. Write a test in the provider code base that can call the provider to generate the message. \n2. Use an HTTP proxy server that can call the provider and return the generated message, and then use a Pact framework verifier to verify it.\n\nFor an example of the latter form, see [Simple Example Protobuf provider](https://github.com/pact-foundation/pact-plugins/tree/main/examples/protobuf/protobuf-provider).\n\n### Testing a gRPC service method interaction\n\nWith a service method call, the consumer creates an input message, then invokes a service method and gets an output message\nas the response. The most common service call is via the gRPC framework.\n\n#### Testing a gRPC service method interaction with a gRPC server\n\nThis plugin supports testing service method calls via gRPC on both the consumer and provider side.\n\n##### Service method consumer\n\nThe service method consumer is tested by configuring a test that starts a gRPC mock server based on the proto file for\nthe service. Each test first configures a Pact from the proto file. The Pact framework (via this plugin)\nwill then create a gRPC mock server for the test. The gRPC consumer can then be pointed at the mock server during the\ntest and send the input message and then verify the output message that is received back.\n\nFor an example:\n* [JVM example gRPC consumer test](https://github.com/pact-foundation/pact-plugins/blob/main/examples/gRPC/area_calculator/consumer-jvm/src/test/java/io/pact/example/grpc/consumer/PactConsumerTest.java)\n* [Rust example gRPC consumer test](https://github.com/pact-foundation/pact-plugins/blob/main/examples/gRPC/area_calculator/consumer-rust/src/lib.rs)\n\n##### Service method provider\n\nThe Pact framework (using this plugin) can test gRPC service method calls to a running gRPC server. The server can be\ntested by either using a unit test, or by using the Rust Verifier CLI. It will need the Pact file created from the\nconsumer test with the compiled protobuf descriptors in it (these will have been added by this plugin during the consumer test).\n\nFor an example Java unit test: See the [example gRPC verification test](https://github.com/pact-foundation/pact-plugins/blob/main/examples/gRPC/area_calculator/provider-jvm/server/src/test/java/io/pact/example/grpc/provider/PactVerificationTest.java).\n\nBy starting the gRPC server, we can then also use the [Pact Verifier](https://github.com/pact-foundation/pact-reference/tree/master/rust/pact_verifier_cli) to check it.\n\n###### For example (using the [example gRPC project](https://github.com/pact-foundation/pact-plugins/blob/main/examples/gRPC/area_calculator/provider-jvm)):\n\n_Running the gRPC server:_\n\n```console\ngRPC/area_calculator/provider-jvm: \n❯ ./gradlew run\n\n\u003e Task :server:run\n14:56:17,785 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback-test.xml]\n14:56:17,786 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback.groovy]\n14:56:17,787 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Found resource [logback.xml] at [file:/home/ronald/Development/Projects/Pact/pact-plugins/examples/gRPC/area_calculator/provider-jvm/server/build/resources/main/logback.xml]\n14:56:17,862 |-INFO in ch.qos.logback.classic.joran.action.ConfigurationAction - debug attribute not set\n14:56:17,863 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - About to instantiate appender of type [ch.qos.logback.core.ConsoleAppender]\n14:56:17,869 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - Naming appender as [STDOUT]\n14:56:17,874 |-INFO in ch.qos.logback.core.joran.action.NestedComplexPropertyIA - Assuming default type [ch.qos.logback.classic.encoder.PatternLayoutEncoder] for [encoder] property\n14:56:17,928 |-INFO in ch.qos.logback.classic.joran.action.RootLoggerAction - Setting level of ROOT logger to ERROR\n14:56:17,928 |-INFO in ch.qos.logback.core.joran.action.AppenderRefAction - Attaching appender named [STDOUT] to Logger[ROOT]\n14:56:17,930 |-ERROR in ch.qos.logback.core.joran.spi.Interpreter@13:36 - no applicable action for [io.grpc.netty], current ElementPath  is [[configuration][io.grpc.netty]]\n14:56:17,930 |-INFO in ch.qos.logback.classic.joran.action.ConfigurationAction - End of configuration.\n14:56:17,932 |-INFO in ch.qos.logback.classic.joran.JoranConfigurator@2b662a77 - Registering current configuration as safe fallback point\n\nStarted calculator service on 37621\n\u003c===========--\u003e 87% EXECUTING [18s]\n\u003e :server:run\n```\n\nWe can see that the gRPC server was started on a random port (37621 above). So we can then provide the Pact file and\nport number to the verifier.\n\n```console\ngRPC/area_calculator/provider-jvm: \n❯ pact_verifier_cli -f ../consumer-jvm/build/pacts/protobuf-consumer-area-calculator-provider.json -p 37621\n\nVerifying a pact between protobuf-consumer and area-calculator-provider\n\n  calculate rectangle area request\n\n  Test Name: io.pact.example.grpc.consumer.PactConsumerTest.calculateRectangleArea(MockServer, SynchronousMessages)\n\n  Given a Calculator/calculate request\n      with an input .area_calculator.ShapeMessage message\n      will return an output .area_calculator.AreaResponse message [OK]\n```\n\n#### Testing a gRPC service method interaction without a gRPC server\n\nIf you can mock out the gRPC channel or stub, it is fairly easy to test the service method call without requiring a\ngRPC server.\n\n##### Service method consumer\n\nTo test the service message consumer, we write a Pact test that defines the expected input (or request) message and the \nexpected output (or response message). The Pact test framework will generate an example input and output message.\n\nTo execute the test, we need to intercept the service method call and verify that the message the consumer generated was\ncorrect, then we return the output message and verify that the consumer processed it correctly. This can be achieved using\na test mocking library.\n\nFor an example:\n* [JVM example service consumer test](https://github.com/pact-foundation/pact-plugins/blob/main/drivers/jvm/core/src/test/groovy/io/pact/plugins/jvm/core/DriverPactTest.groovy#L116)\n* [Rust example service consumer test](https://github.com/pact-foundation/pact-plugins/blob/main/drivers/rust/driver/tests/pact.rs#L43)\n\n##### Service method provider\n\nThe Protocol Buffer service providers normally extend an interface generated by the protoc compiler. To test them, we\nneed a mechanism to get the Pact verifier to pass in the input message from the Pact file and then get the output message\nfrom the service and compare that to the output message from the Pact file.\n\nWe can use the same mechanism as for message pact (see [Non-HTTP testing (Message Pact)](https://docs.pact.io/getting_started/how_pact_works/#non-http-testing-message-pact)),\nwere we create an HTTP proxy server to receive the input message from the verifier and invoke the service method implementation\nto get the output message.\n\nThere are two main ways to run the verification:\n\n1. Execute the Pact verifier, providing the source of the Pact file, and configure it to use the HTTP mock server.\n2. Write a test in the provider's code base. For an example of doing this in Rust, see [a test that verifies this plugin](tests/pact_verify.rs).\n\n#### Verifying gRPC error responses (0.3.1+)\n\nYou can use this plugin to test negative cases where an error response is expected to be returned (for an example see\n[gRPC status](https://github.com/pact-foundation/pact-plugins/tree/main/examples/gRPC/grpc_status)). This works by\nchecking if there is an expected `grpc-status` attribute set when an error response is returned (and also can check\nfor a `grpc-message` attribute).\n\nTo use it, don't configure a response message, but add the expected status (and message if required) to the response\nmetadata. I.e, in the consumer test:\n\n```java\n.with(Map.of(\n    \"pact:proto\", filePath(\"../proto/grpc_status.proto\"),\n    \"pact:content-type\", \"application/grpc\",\n    \"pact:proto-service\", \"Calculator/calculate\",\n\n    \"request\", Map.of(\n      \"parallelogram\", Map.of(\n        \"base_length\", \"matching(number, 3)\",\n        \"height\", \"matching(number, 4)\"\n      )\n    ),\n\n    // We are expecting an error response for this message\n    \"responseMetadata\", Map.of(\n      \"grpc-status\", \"UNIMPLEMENTED\",\n      \"grpc-message\", \"matching(type, 'we do not currently support parallelograms')\"\n    )\n))\n```\n\nthen when the interaction is verified you will see (assuming the provider returns the correct response):\n\n```console\nVerifying a pact between grpc-consumer-rust and grpc-provider\n\n  invalid request (0s loading, 54ms verification)\n\n  Given a Calculator/calculate request\n      with an input .area_calculator.ShapeMessage message\n      will return an error response Operation is not implemented or not supported [OK]\n        with metadata\n          key 'grpc-message' with value 'we do not currently support parallelograms' [OK]\n          key 'grpc-status' with value 'UNIMPLEMENTED' [OK]\n```\n\n### The Protobuf test configuration\n\nThe consumer tests need to get the plugin loaded and configure the expected messages to use in the test. This is done\nusing the `usingPlugin` (or `using_plugin`, depending on the language implementation) followed by the content for the test\nin some type of map form.\n\nFor each field of the message that we want in the contract, we define an entry with the field name as the key and\na matching definition as the value. For documentation on the matching definition format, see [Matching Rule definition expressions](https://github.com/pact-foundation/pact-plugins/blob/main/docs/matching-rule-definition-expressions.md).\n\nFor example, for a JVM test (taken from [Protocol Buffer Java examples](https://developers.google.com/protocol-buffers/docs/javatutorial)) we would use the PactBuilder class:\n\n```protobuf\n// this example taken from https://developers.google.com/protocol-buffers/docs/javatutorial#defining-your-protocol-format\nmessage Person {\n  string name = 1;\n  int32 id = 2;\n  string email = 3;\n\n  enum PhoneType {\n    MOBILE = 0;\n    HOME = 1;\n    WORK = 2;\n  }\n\n  message PhoneNumber {\n    string number = 1;\n    PhoneType type = 2 [default = HOME];\n  }\n\n  repeated PhoneNumber phones = 4;\n}\n```\n\n```java\nbuilder\n  // Tell the Pact framework to load the protobuf plugin      \n  .usingPlugin(\"protobuf\")\n        \n  // Define the expected message (description) and the type of interaction. Here is is an asynchronous message.\n  .expectsToReceive(\"Person Message\", \"core/interaction/message\")\n        \n  // Provide the data for the test\n  .with(Map.of(\n    // For a single asynchronous message, we just provide the contents for the message. For RPC service calls, there\n    // will be a request and response message\n    \"message.contents\", Map.of(\n      // set the content type, so the Pact framework will know to send it to the Protobuf plugin\n      \"pact:content-type\", \"application/protobuf\",\n      // pact:proto contains the source proto file, which is required to be able to test the interaction\n      \"pact:proto\", filePath(\"addressbook.proto\"),\n      // provide the name of the message type we are going to test (defined in the proto file)\n      \"pact:message-type\", \"Person\",\n      \n      // We can then setup the expected fields of the message\n      \"name\", \"notEmpty('Fred')\", // The name field must not be empty, and we use Fred in our tests\n      \"id\", \"matching(regex, '100\\\\d+', '1000001')\", // The id field must match the regular expression, and we use 1000001 in the tests \n      \"email\", \"matching(regex, '\\\\w+@[a-z0-9\\\\.]+', 'test@ourtest.com')\" // Emails must match a regular expression\n\n      // phones is a repeated field, so we define an example that all values must match against\n      \"phones\", Map.of(\n        \"number\", \"matching(regex, '(\\\\+\\\\d+)?(\\\\d+\\\\-)?\\\\d+\\\\-\\\\d+', '+61-03-1234-5678')\" // Phone numbers must match a regular expression\n        // We don't include type, as it is an emum and has a default value, so it is optional\n        // but we could have done something like matching(equalTo, 'WORK')\n      )\n    )\n  ))\n```\n\n### Matching repeated fields\n\nYou can apply matching rules to enforce the minimum or maximum number fo fields, as well as applying rules for each\nitem. \n\nFor instance, assume that `numbers` is a repeated String field. You could define\n```json\n    \"numbers\": \"atLeast(1), eachValue(matching(regex, '\\\\d+', '100))\"\n```\nThis will make aure that there is always at least one number, and that any numbers match the given regular expression.\n\n**Note: `atLeast` and `atMost` require version 0.3.12+**\n\nThis would also work if `numbers` was a numeric repeated field. In fact, it would work with any primitive field by\napplying the regex to the string representation of the field value.\n\n### Matching on map fields\n\nWith maps, you can apply matching rules on either the keys in the map, or the values, or both. For instance, given\n```protobuf\nmessage ExampleRequest {\n  map\u003cstring, string\u003e labels = 1;\n  bool ok = 2;\n}\n```\n\nYou could define a test like\n```json\n    \"request\": {\n        \"labels\": {\n          \"pact:match\": \"eachKey(matching(regex, '\\\\d+', '')), eachValue(matching(regex, '(\\\\w|\\\\s)+', '')), atLeast(1)\",\n          \"100\": \"this is a label\"\n        },\n        \"ok\": \"true\"\n    }\n```\nThis will require the map of labels to only have keys and values that match the given regular expressions, and the map\nmust have at least one entry. `\"100\": \"this is a label\"` is the example value used in the consumer test.\n\n### Provider state injected values\n_Requires 0.5.0+ of the Protobuf plugin._\n\nValues from [provider states](https://docs.pact.io/getting_started/provider_states) can be injected into Protobuf \nmessage fields and gRPC metadata. This can be done by using the `fromProviderState` function in the consumer test.\n\nFor example (taken from an [example Java Consumer Test](https://github.com/pact-foundation/pact-plugins/blob/main/examples/gRPC/provider-states/consumer-jvm/src/test/java/io/pact/example/grpc/consumer/PactConsumerTest.java)):\n```json\n{\n  \"request\": {\n    \"rectangle\": {\n      \"length\": \"matching(number, fromProviderState('${rectangleLength}', 3))\",\n      \"width\": \"matching(number, fromProviderState('${rectangleWidth}', 3))\"\n    },\n    \"requestMetadata\": {\n      \"Auth\": \"matching(equalTo, fromProviderState('${Auth}', 'AST00004'))\"\n    },\n    \"response\": {\n      \"value\": \"matching(number, 12)\"\n    }\n  }\n}\n```\n\nThis example allows the rectangle length and width to be changed from values from the provider state callback, as well\nas the `Auth` metadata value. You can see an example doing that [here](https://github.com/pact-foundation/pact-plugins/blob/main/examples/gRPC/provider-states/provider-jvm/server/src/test/java/io/pact/example/grpc/provider/PactVerificationTest.java#L54).\n\n### Handling binary non-UTF-8 data\n_Requires 0.6.4+ of the Protobuf plugin._\n\nFor byte array fields (`byte` or `.google.protobuf.BytesValue` types), you can specify the values using either a string \nvalue (which must be valid UTF-8), an array of unsigned byte values (0-255), or a base 64 encoded string.\n\nFor instance:\n```json\n{\n  \"request\": {\n    \"raw_bytes\": [1, 2, 3, 4, 5]\n  }\n}\n```\nor\n```json\n{\n  \"request\": {\n    \"raw_bytes\": \"AQIDBAU=\"\n  }\n}\n```\n\n## Running within docker containers\n\nThe plugin will try to use an IP6 address when opening the port for the gRPC server. Docker will only support IP6\naddresses with extra configuration applied and this will not be available by default. To use an IP4 address instead,\nyou can either add the host parameter as a command line parameter, or add `hostToBindTo` value to the plugin \nconfiguration in the manifest file.\n\nI.e., updated manifest to use 127.0.0.1 as the host to bind to\n\n```json\n{\n  \"manifestVersion\": 1,\n  \"pluginInterfaceVersion\": 1,\n  \"name\": \"protobuf\",\n  \"version\": \"0.1.8\",\n  \"executableType\": \"exec\",\n  \"entryPoint\": \"pact-protobuf-plugin\",\n  \"pluginConfig\": {\n    \"protocVersion\": \"3.19.1\",\n    \"downloadUrl\": \"https://github.com/protocolbuffers/protobuf/releases/download\",\n    \"hostToBindTo\": \"127.0.0.1\"\n  }\n}\n```\n\n## Compatibility\n\n\u003cdetails\u003e\u003csummary\u003eSupported Platforms\u003c/summary\u003e\n\n| OS      | Architecture | Supported  | Pact Protobuf Plugin Version |\n| ------- | ------------ | ---------  | ---------------- |\n| OSX     | x86_64       | ✅         | All              |\n| Linux   | x86_64       | ✅         | All              |\n| Windows | x86_64       | ✅         | All              |\n| OSX     | arm64        | ✅         | All              |\n| Linux   | arm64        | ✅         | \u003e=0.1.11         |\n| Windows | arm64        | ✅         | \u003e=0.3.15         |\n| Alpine  | x86_64       | ✅         | \u003e=0.1.9          |\n| Alpine  | arm64        | ✅         | \u003e=0.3.15         |\n\n_Note:_ From v0.3.15, All Linux executables are statically built with `musl` and are designed to work against `glibc` (eg, Debian) and `musl` (eg, Alpine) based distos. \n\n\u003c/details\u003e\n\n## Support\n\nJoin us on slack [![slack](https://slack.pact.io/badge.svg)](https://slack.pact.io) in the **#protobufs** channel\n\nor\n\n    Twitter: @pact_up\n    Stack Overflow: stackoverflow.com/questions/tagged/pact\n\n## Contributing\n\nPRs are always welcome!\n\nFor details on the V4 Pact specification, refer to https://github.com/pact-foundation/pact-specification/tree/version-4\n\nFor details on the Pact plugin framework, refer to https://github.com/pact-foundation/pact-plugins\n\n### Raising defects\n\nBefore raising an issue, make sure you have checked the open and closed issues to see if an answer is provided there.\nThere may also be an answer to your question on [stackoverflow](https://stackoverflow.com/questions/tagged/pact).\n\nPlease provide the following information with your issue to enable us to respond as quickly as possible.\n\n1. The relevant versions of the packages you are using (plugin and Pact versions).\n1. The steps to recreate your issue.\n1. An executable code example where possible.\n\n### New features / changes\n\n1. Fork it\n1. Create your feature branch (git checkout -b my-new-feature)\n1. Commit your changes (git commit -am 'feat: Add some feature')\n1. Push to the branch (git push origin my-new-feature)\n1. Create new Pull Request\n\n#### Commit messages\n\nWe follow the [Conventional Changelog](https://github.com/bcoe/conventional-changelog-standard/blob/master/convention.md)\nmessage conventions. Please ensure you follow the guidelines.\n\n### Building the plugin\n\nTo build the plugin, you need a working Rust environment (version 1.58+). Refer to the [Rust Guide](https://www.rust-lang.org/learn/get-started).\n\nThe build tool used is `cargo` and you can build the plugin by running `cargo build`. This will compile the plugin and \nput the generated files in `target/debug`. The main plugin executable is `pact-protobuf-plugin`\nand this will need to be copied into the Pact plugin directory. See the installation instructions above.\n\n### Running the tests\n\nYou can run all the unit tests by executing `cargo test --lib`.\n\nThere is a Pact test that verifies the plugin aqainst the Pact file published to [pact-foundation.pactflow.io](https://pact-foundation.pactflow.io).\nRunning this test requires a Pactflow API token and the plugin to be built and installed. See the installation instructions above.\nThe test is run using `cargo test --test pact_verify`.\n\n### Developer notes\n#### Base64-encoded strings in unit-tests\nSeveral unit-tests have base64 encoded proto descriptors as input. They're hard to read and update.\nTo decode and check out the contents:\n- save the encoded string into a file, e.g. `/tmp/some.b64` and then `base64 -d /tmp/some.b64 | protoc --decode_raw`\n- this will be somewhat readable, even if not a proper proto3 syntax, but it will be possible to reconstruct it.\n- github copilot can decode the raw base64 string easily too\n\nTo encode a .proto file into a base64-encoded FileDescriptorSet, \ne.g. if you modified `tests/simple.proto` and need to update its encoded form in tests:\n- `protoc --descriptor_set_out=/dev/stdout tests/simple.proto | base64`\n\n## License and Copyright\n\nThis plugin is released under the **MIT License** and is copyright © 2021-24 [SmartBear](https://pactflow.io).\n\nThe Pactflow logos are copyright © [SmartBear](https://pactflow.io) and may not be used without permission.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpactflow%2Fpact-protobuf-plugin","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpactflow%2Fpact-protobuf-plugin","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpactflow%2Fpact-protobuf-plugin/lists"}