Skip to content

Commit

Permalink
feat: add example php pact test with gRPC/pact-protobuf-plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
YOU54F committed Nov 23, 2022
1 parent 4ecce05 commit 76c2ef0
Show file tree
Hide file tree
Showing 10 changed files with 254 additions and 12 deletions.
1 change: 1 addition & 0 deletions php/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"consumer-1-mismatches": "MATCHING=0 php src/consumer-1.php",
"consumer-2-matches": "MATCHING=1 php src/consumer-2.php",
"consumer-2-mismatches": "MATCHING=0 php src/consumer-2.php",
"consumer-plugin": "MATCHING=1 php src/consumer-plugin.php",
"provider": "php src/provider.php"
}
}
102 changes: 102 additions & 0 deletions php/pacts/grpc-consumer-php-area-calculator-provider.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
{
"consumer": {
"name": "grpc-consumer-php"
},
"interactions": [
{
"description": "A gRPC calculateOne request",
"interactionMarkup": {
"markup": "```protobuf\nmessage AreaResponse {\n repeated float value = 1;\n}\n```\n",
"markupType": "COMMON_MARK"
},
"key": "ab98c08a2562ef2e",
"pending": false,
"pluginConfiguration": {
"protobuf": {
"descriptorKey": "a85dff8f82655a9681aad113575dcfbb",
"service": "Calculator/calculateOne"
}
},
"request": {
"contents": {
"content": "EgoNAABAQBUAAIBA",
"contentType": "application/protobuf;message=ShapeMessage",
"contentTypeHint": "BINARY",
"encoded": "base64"
},
"matchingRules": {
"body": {
"$.rectangle.length": {
"combine": "AND",
"matchers": [
{
"match": "number"
}
]
},
"$.rectangle.width": {
"combine": "AND",
"matchers": [
{
"match": "number"
}
]
}
}
}
},
"response": [
{
"contents": {
"content": "CgQAAEBB",
"contentType": "application/protobuf;message=AreaResponse",
"contentTypeHint": "BINARY",
"encoded": "base64"
},
"matchingRules": {
"body": {
"$.value[0].*": {
"combine": "AND",
"matchers": [
{
"match": "number"
}
]
}
}
}
}
],
"transport": "grpc",
"type": "Synchronous/Messages"
}
],
"metadata": {
"pact-php": {
"ffi": "0.3.14"
},
"pactRust": {
"ffi": "0.3.14",
"mockserver": "0.9.5",
"models": "1.0.0"
},
"pactSpecification": {
"version": "4.0"
},
"plugins": [
{
"configuration": {
"a85dff8f82655a9681aad113575dcfbb": {
"protoDescriptors": "CsoHChVhcmVhX2NhbGN1bGF0b3IucHJvdG8SD2FyZWFfY2FsY3VsYXRvciK6AgoMU2hhcGVNZXNzYWdlEjEKBnNxdWFyZRgBIAEoCzIXLmFyZWFfY2FsY3VsYXRvci5TcXVhcmVIAFIGc3F1YXJlEjoKCXJlY3RhbmdsZRgCIAEoCzIaLmFyZWFfY2FsY3VsYXRvci5SZWN0YW5nbGVIAFIJcmVjdGFuZ2xlEjEKBmNpcmNsZRgDIAEoCzIXLmFyZWFfY2FsY3VsYXRvci5DaXJjbGVIAFIGY2lyY2xlEjcKCHRyaWFuZ2xlGAQgASgLMhkuYXJlYV9jYWxjdWxhdG9yLlRyaWFuZ2xlSABSCHRyaWFuZ2xlEkYKDXBhcmFsbGVsb2dyYW0YBSABKAsyHi5hcmVhX2NhbGN1bGF0b3IuUGFyYWxsZWxvZ3JhbUgAUg1wYXJhbGxlbG9ncmFtQgcKBXNoYXBlIikKBlNxdWFyZRIfCgtlZGdlX2xlbmd0aBgBIAEoAlIKZWRnZUxlbmd0aCI5CglSZWN0YW5nbGUSFgoGbGVuZ3RoGAEgASgCUgZsZW5ndGgSFAoFd2lkdGgYAiABKAJSBXdpZHRoIiAKBkNpcmNsZRIWCgZyYWRpdXMYASABKAJSBnJhZGl1cyJPCghUcmlhbmdsZRIVCgZlZGdlX2EYASABKAJSBWVkZ2VBEhUKBmVkZ2VfYhgCIAEoAlIFZWRnZUISFQoGZWRnZV9jGAMgASgCUgVlZGdlQyJICg1QYXJhbGxlbG9ncmFtEh8KC2Jhc2VfbGVuZ3RoGAEgASgCUgpiYXNlTGVuZ3RoEhYKBmhlaWdodBgCIAEoAlIGaGVpZ2h0IkQKC0FyZWFSZXF1ZXN0EjUKBnNoYXBlcxgBIAMoCzIdLmFyZWFfY2FsY3VsYXRvci5TaGFwZU1lc3NhZ2VSBnNoYXBlcyIkCgxBcmVhUmVzcG9uc2USFAoFdmFsdWUYASADKAJSBXZhbHVlMq0BCgpDYWxjdWxhdG9yEk4KDGNhbGN1bGF0ZU9uZRIdLmFyZWFfY2FsY3VsYXRvci5TaGFwZU1lc3NhZ2UaHS5hcmVhX2NhbGN1bGF0b3IuQXJlYVJlc3BvbnNlIgASTwoOY2FsY3VsYXRlTXVsdGkSHC5hcmVhX2NhbGN1bGF0b3IuQXJlYVJlcXVlc3QaHS5hcmVhX2NhbGN1bGF0b3IuQXJlYVJlc3BvbnNlIgBCHFoXaW8ucGFjdC9hcmVhX2NhbGN1bGF0b3LQAgFiBnByb3RvMw==",
"protoFile": "syntax = \"proto3\";\n\npackage area_calculator;\n\noption php_generic_services = true;\noption go_package = \"io.pact/area_calculator\";\n\nservice Calculator {\n rpc calculateOne (ShapeMessage) returns (AreaResponse) {}\n rpc calculateMulti (AreaRequest) returns (AreaResponse) {}\n}\n\nmessage ShapeMessage {\n oneof shape {\n Square square = 1;\n Rectangle rectangle = 2;\n Circle circle = 3;\n Triangle triangle = 4;\n Parallelogram parallelogram = 5;\n }\n}\n\nmessage Square {\n float edge_length = 1;\n}\n\nmessage Rectangle {\n float length = 1;\n float width = 2;\n}\n\nmessage Circle {\n float radius = 1;\n}\n\nmessage Triangle {\n float edge_a = 1;\n float edge_b = 2;\n float edge_c = 3;\n}\n\nmessage Parallelogram {\n float base_length = 1;\n float height = 2;\n}\n\nmessage AreaRequest {\n repeated ShapeMessage shapes = 1;\n}\n\nmessage AreaResponse {\n repeated float value = 1;\n}"
}
},
"name": "protobuf",
"version": "0.1.17"
}
]
},
"provider": {
"name": "area-calculator-provider"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -137,9 +137,9 @@
],
"metadata": {
"pactRust": {
"ffi": "0.2.3",
"mockserver": "0.8.7",
"models": "0.2.7"
"ffi": "0.3.14",
"mockserver": "0.9.5",
"models": "1.0.0"
},
"pactSpecification": {
"version": "3.0.0"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@
],
"metadata": {
"pactRust": {
"ffi": "0.2.3",
"mockserver": "0.8.7",
"models": "0.2.7"
"ffi": "0.3.14",
"mockserver": "0.9.5",
"models": "1.0.0"
},
"pactSpecification": {
"version": "3.0.0"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@
],
"metadata": {
"pactRust": {
"ffi": "0.2.3",
"models": "0.2.7"
"ffi": "0.3.14",
"models": "1.0.0"
},
"pactSpecification": {
"version": "3.0.0"
Expand Down
5 changes: 4 additions & 1 deletion php/src/consumer-1.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@

$code = file_get_contents(__DIR__ . '/../../rust/pact_ffi/include/pact.h');
$ffi = FFI::cdef($code, __DIR__ . '/../../rust/target/debug/libpact_ffi.so');
// Macs use dylib extension, following will assume os's downloaded in users home dir ~/.pact/ffi/arch/libpact_ffi.<dylib|so>
// $code = file_get_contents(posix_getpwnam(get_current_user())['dir'] . '/.pact/ffi/pact.h');
// $ffi = FFI::cdef($code, posix_getpwnam(get_current_user())['dir'] . '/.pact/ffi/osxaarch64/libpact_ffi.dylib');

$ffi->pactffi_init('LOG_LEVEL');

Expand Down Expand Up @@ -107,7 +110,7 @@
echo getenv('MATCHING') ? "Mock server matched all requests, Yay!" : "Mock server matched all requests, That Is Not Good (tm)";
echo "\n";

$ffi->pactffi_write_pact_file($port, __DIR__ . '/../pact', false);
$ffi->pactffi_write_pact_file($port, __DIR__ . '/../pacts', false);
} else {
echo getenv('MATCHING') ? "We got some mismatches, Boo!" : "We got some mismatches, as expected.";
echo "\n";
Expand Down
7 changes: 5 additions & 2 deletions php/src/consumer-2.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@

$code = file_get_contents(__DIR__ . '/../../rust/pact_ffi/include/pact.h');
$ffi = FFI::cdef($code, __DIR__ . '/../../rust/target/debug/libpact_ffi.so');
// Macs use dylib extension, following will assume os's downloaded in users home dir ~/.pact/ffi/arch/libpact_ffi.<dylib|so>
// $code = file_get_contents(posix_getpwnam(get_current_user())['dir'] . '/.pact/ffi/pact.h');
// $ffi = FFI::cdef($code, posix_getpwnam(get_current_user())['dir'] . '/.pact/ffi/osxaarch64/libpact_ffi.dylib');

$ffi->pactffi_init('LOG_LEVEL');

Expand Down Expand Up @@ -72,8 +75,8 @@
echo getenv('MATCHING') ? "Mock server matched all requests, Yay!" : "Mock server matched all requests, That Is Not Good (tm)";
echo "\n";

$ffi->pactffi_write_pact_file($port, __DIR__ . '/../pact', false);
$ffi->pactffi_write_message_pact_file($messagePact, __DIR__ . '/../pact', false);
$ffi->pactffi_write_pact_file($port, __DIR__ . '/../pacts', false);
$ffi->pactffi_write_message_pact_file($messagePact, __DIR__ . '/../pacts', false);
} else {
echo getenv('MATCHING') ? "We got some mismatches, Boo!" : "We got some mismatches, as expected.";
echo "\n";
Expand Down
77 changes: 77 additions & 0 deletions php/src/consumer-plugin.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<?php

require __DIR__ . '/../vendor/autoload.php';

use Symfony\Component\HttpClient\HttpClient;

$code = file_get_contents(__DIR__ . '/../../rust/pact_ffi/include/pact.h');
$ffi = FFI::cdef($code, __DIR__ . '/../../rust/target/debug/libpact_ffi.so');
// Macs use dylib extension, following will assume os's downloaded in users home dir ~/.pact/ffi/arch/libpact_ffi.<dylib|so>
// $code = file_get_contents(posix_getpwnam(get_current_user())['dir'] . '/.pact/ffi/pact.h');
// $ffi = FFI::cdef($code, posix_getpwnam(get_current_user())['dir'] . '/.pact/ffi/osxaarch64/libpact_ffi.dylib');

// Setup Loggers
$ffi->pactffi_logger_init();
$ffi->pactffi_logger_attach_sink('file ./logs/log-info.txt',5);
$ffi->pactffi_logger_attach_sink('file ./logs/log-error.txt',5);
$ffi->pactffi_logger_attach_sink('stdout', 3);
$ffi->pactffi_logger_attach_sink('stderr', 2);
$ffi->pactffi_logger_apply();
$ffi->pactffi_log_message('pact-php-ffi', 'INFO', 'hello from pact php ffi, using Pact FFI Version: ' . $ffi->pactffi_version());

// Setup pact for testing
$pact = $ffi->pactffi_new_pact('grpc-consumer-php', 'area-calculator-provider');
$ffi->pactffi_with_pact_metadata($pact, 'pact-php','ffi',$ffi->pactffi_version());
$message_pact = $ffi->pactffi_new_sync_message_interaction($pact, 'A gRPC calculateOne request');
$ffi->pactffi_with_specification($pact, $ffi->PactSpecification_V4);

// Setup contents

$proto_file_path = __DIR__ . '/../../proto/area_calculator.proto';

$contents = '{
"pact:proto": "'. $proto_file_path . '",
"pact:proto-service": "Calculator/calculateOne",
"pact:content-type": "application/protobuf",
"request": {
"rectangle": {
"length": "matching(number, 3)",
"width": "matching(number, 4)"
}
},
"response": {
"value": ["matching(number, 12)"]
}
}';

// Start mock server

$ffi->pactffi_using_plugin($pact, 'protobuf', '0.1.17');
$ffi->pactffi_interaction_contents($message_pact, 0, 'application/grpc', $contents);
$port = $ffi->pactffi_create_mock_server_for_transport($pact , '0.0.0.0',0,'grpc', null);

echo sprintf("Mock server port=%d\n", $port);

// This is where we would call our client, gRPC in this example plugin demo
// PHP gRPC is client only, so would need to use a provider from the following
// https://github.com/pact-foundation/pact-plugins/tree/main/examples/gRPC/area_calculator
// TODO build out an area calculator PHP example
// https://grpc.io/docs/languages/php/

// Check if requests match - Note this _should_ fail, but the pactffi_mock_server_matched is returning true
// even if no requests were made.

if ($ffi->pactffi_mock_server_matched($port)) {
echo getenv('MATCHING') ? "Mock server matched all requests, Yay!" : "Mock server matched all requests, That Is Not Good (tm)";
echo "\n";

$ffi->pactffi_write_pact_file($port, __DIR__ . '/../pacts', false);
// $ffi->pactffi_write_message_pact_file($messagePact, __DIR__ . '/../pacts', false);
} else {
echo getenv('MATCHING') ? "We got some mismatches, Boo!" : "We got some mismatches, as expected.";
echo "\n";
echo sprintf("Mismatches: %s\n", print_r(json_decode(FFI::string($ffi->pactffi_mock_server_mismatches($port)), true), true));
}

$ffi->pactffi_cleanup_mock_server($port);
$ffi->pactffi_cleanup_plugins($pact);
5 changes: 4 additions & 1 deletion php/src/provider.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@

$code = file_get_contents(__DIR__ . '/../../rust/pact_ffi/include/pact.h');
$ffi = FFI::cdef($code, __DIR__ . '/../../rust/target/debug/libpact_ffi.so');
// Macs use dylib extension, following will assume os's downloaded in users home dir ~/.pact/ffi/arch/libpact_ffi.<dylib|so>
// $code = file_get_contents(posix_getpwnam(get_current_user())['dir'] . '/.pact/ffi/pact.h');
// $ffi = FFI::cdef($code, posix_getpwnam(get_current_user())['dir'] . '/.pact/ffi/osxaarch64/libpact_ffi.dylib');

$ffi->pactffi_init('LOG_LEVEL');

Expand Down Expand Up @@ -40,7 +43,7 @@ function getCData(array $items): FFI\CData
$ffi->pactffi_verifier_set_verification_options($handle, false, 5000);
$ffi->pactffi_verifier_set_publish_options($handle, '1.0.0', null, getCData($tags), count($tags), 'some-branch');
$ffi->pactffi_verifier_set_consumer_filters($handle, getCData($consumers), count($consumers));
$ffi->pactffi_verifier_add_directory_source($handle, __DIR__ . '/../pact');
$ffi->pactffi_verifier_add_directory_source($handle, __DIR__ . '/../pacts');
$result = $ffi->pactffi_verifier_execute($handle);
$ffi->pactffi_verifier_shutdown($handle);

Expand Down
53 changes: 53 additions & 0 deletions proto/area_calculator.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
syntax = "proto3";

package area_calculator;

option php_generic_services = true;
option go_package = "io.pact/area_calculator";

service Calculator {
rpc calculateOne (ShapeMessage) returns (AreaResponse) {}
rpc calculateMulti (AreaRequest) returns (AreaResponse) {}
}

message ShapeMessage {
oneof shape {
Square square = 1;
Rectangle rectangle = 2;
Circle circle = 3;
Triangle triangle = 4;
Parallelogram parallelogram = 5;
}
}

message Square {
float edge_length = 1;
}

message Rectangle {
float length = 1;
float width = 2;
}

message Circle {
float radius = 1;
}

message Triangle {
float edge_a = 1;
float edge_b = 2;
float edge_c = 3;
}

message Parallelogram {
float base_length = 1;
float height = 2;
}

message AreaRequest {
repeated ShapeMessage shapes = 1;
}

message AreaResponse {
repeated float value = 1;
}

0 comments on commit 76c2ef0

Please sign in to comment.