diff --git a/README.md b/README.md index 34602cf62..ae3a883a0 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ Table of contents - [Start API](#start-api) - [Provider Verification](#provider-verification) - [Verify From Pact Broker](#verify-from-pact-broker) - - [Verify All from Pact Broker](#verify-all-from-pact-broker) + - [Verify Files in Directory](#verify-files-in-directory) - [Verify Files by Path](#verify-files-by-path) - [Tips](#tips) - [Starting API Asynchronously](#starting-api-asynchronously) @@ -229,51 +229,57 @@ $config = new VerifierConfig(); $config ->setProviderName('someProvider') // Providers name to fetch. ->setProviderVersion('1.0.0') // Providers version. - ->setProviderBranch('main') // Providers git branch name. - ->setProviderBaseUrl(new Uri('http://localhost:58000')) // URL of the Provider. - ->setBrokerUri(new Uri('http://localhost')) // URL of the Pact Broker to publish results. - ->setPublishResults(true) // Flag the verifier service to publish the results to the Pact Broker. - ->setProcessTimeout(60) // Set process timeout (optional) - default 60 - ->setProcessIdleTimeout(10) // Set process idle timeout (optional) - default 10 - ->setEnablePending(true) // Flag to enable pending pacts feature (check pact docs for further info) - ->setIncludeWipPactSince('2020-01-30') //Start date of WIP Pacts (check pact docs for further info) - ->setRequestFilter( - function (RequestInterface $r) { - return $r->withHeader('MY_SPECIAL_HEADER', 'my special value'); - } - ); -// Verify that the Consumer 'someConsumer' that is tagged with 'master' is valid. + ->setProviderTags('prod' ,'dev') + ->setProviderBranch('main') + ->setScheme('http') + ->setHost('localhost') + ->setPort(58000) + ->setBasePath('/') + ->setStateChangeUrl(new Uri('http://localhost:58000/change-state')) + ->setBuildUrl(new Uri('http://build.domain.com')) + ->setFilterConsumerNames('someConsumer', 'otherConsumer') + ->setFilterDescription('Send POST to create') + ->setFilterNoState(true) + ->setFilterState('state') + ->setPublishResults(true) + ->setDisableSslVerification(true) + ->setStateChangeAsBody(false) + ->setStateChangeTeardown(true) + ->setRequestTimeout(500); + $verifier = new Verifier($config); -$verifier->verify('someConsumer', 'master'); // The tag is option. If no tag is set it will just grab the latest. -// This will not be reached if the PACT verifier throws an error, otherwise it was successful. -$this->assertTrue(true, 'Pact Verification has failed.'); +$selectors = (new ConsumerVersionSelectors()) + ->addSelector('{"tag":"foo","latest":true}') + ->addSelector('{"tag":"bar","latest":true}'); + +$broker = new Broker(); +$broker + ->setUrl(new Uri('http://localhost')) + ->setUsername('user') + ->setPassword('pass') + ->setToken('token') + ->setEnablePending(true) + ->setIncludeWipPactSince('2020-01-30') + ->setProviderTags(['prod']) + ->setProviderBranch('main') + ->setConsumerVersionSelectors($selectors) + ->setConsumerVersionTags(['dev']); + +$verifier->addBroker($broker); + +$this->assertTrue($verifier->verify()); ``` -##### Verify All from Pact Broker +##### Verify Files in Directory -This will grab every Pact file associated with the given provider. +This allows local Pact file testing. ```php -public function testPactVerifyAll() +public function testPactVerifyFilesInDirectory() { - $config = new VerifierConfig(); - $config - ->setProviderName('someProvider') // Providers name to fetch. - ->setProviderVersion('1.0.0') // Providers version. - ->setProviderBranch('main') // Providers git branch name. - ->setProviderBaseUrl(new Uri('http://localhost:58000')) // URL of the Provider. - ->setBrokerUri(new Uri('http://localhost')) // URL of the Pact Broker to publish results. - ->setPublishResults(true) // Flag the verifier service to publish the results to the Pact Broker. - ->setEnablePending(true) // Flag to enable pending pacts feature (check pact docs for further info) - ->setIncludeWipPactSince('2020-01-30') //Start date of WIP Pacts (check pact docs for further info) - - // Verify that all consumers of 'someProvider' are valid. - $verifier = new Verifier($config); - $verifier->verifyAll(); - - // This will not be reached if the PACT verifier throws an error, otherwise it was successful. - $this->assertTrue(true, 'Pact Verification has failed.'); + $verifier->addDirectory('C:\SomePath'); + $this->assertTrue($verifier->verify()); } ``` @@ -282,25 +288,10 @@ public function testPactVerifyAll() This allows local Pact file testing. ```php -public function testPactVerifyAll() +public function testPactVerifyFiles() { - $config = new VerifierConfig(); - $config - ->setProviderName('someProvider') // Providers name to fetch. - ->setProviderVersion('1.0.0') // Providers version. - ->setProviderBranch('main') // Providers git branch name. - ->setProviderBaseUrl(new Uri('http://localhost:58000')) // URL of the Provider. - ->setBrokerUri(new Uri('http://localhost')) // URL of the Pact Broker to publish results. - ->setPublishResults(true); // Flag the verifier service to publish the results to the Pact Broker. - ->setEnablePending(true) // Flag to enable pending pacts feature (check pact docs for further info) - ->setIncludeWipPactSince('2020-01-30') //Start date of WIP Pacts (check pact docs for further info) - - // Verify that the files in the array are valid. - $verifier = new Verifier($config); - $verifier->verifyFiles(['C:\SomePath\consumer-provider.json']); - - // This will not be reached if the PACT verifier throws an error, otherwise it was successful. - $this->assertTrue(true, 'Pact Verification has failed.'); + $verifier->addFile('C:\SomePath\consumer-provider.json'); + $this->assertTrue($verifier->verify()); } ``` @@ -332,7 +323,6 @@ There is a separate repository with an end to end example for both the 2.X and 3 - [2.2.1 tag](https://github.com/mattermack/pact-php-example/tree/2.2.1) for 2.X examples ## Message support -This feature is preliminary as the Pact community as a whole is flushing this out. The goal is not to test the transmission of an object over a bus but instead vet the contents of the message. While examples included focus on a Rabbit MQ, the exact message queue is irrelevant. Initial comparisons require a certain object type to be created by the Publisher/Producer and the Consumer of the message. This includes a metadata set where you @@ -377,42 +367,17 @@ $this->assertTrue($builder->verify()); ### Provider Side Message Validation -This may evolve as we work through this implementation. The provider relies heavily on callbacks. -Some of the complexity lies in a consumer and provider having many messages and states between the each other in a single pact. - -For each message, one needs to provide a single provider state. The name of this provider state must be the key to run -a particular message callback on the provider side. See example\tests\MessageProvider - -1. Create your callbacks and states wrapped in a callable object - 1. The array key is a provider state / given() on the consumer side - 1. It is helpful to wrap the whole thing in a lambda if you need to customize paramaters to be passed in -1. Choose your verification method -1. If nothing explodes, #winning - -```php +Handle these requests on provider's proxy: - $callbacks = array(); +1. POST /change-state + 1. Set up your database to meet the expectations of the request + 2. Reset the database to its original state. +2. POST / + 1. Return message's content in body + 2. Return message's metadata in header `PACT-MESSAGE-METADATA` +3. Proxy to provider app on other requests - // a hello message is a provider state / given() on the consumer side - $callbacks["a hello message"] = function() { - $content = new \stdClass(); - $content->text ="Hello Mary"; - - $metadata = array(); - $metadata['queue'] = "myKey"; - - $provider = (new ExampleMessageProvider()) - ->setContents($content) - ->setMetadata($metadata); - - return $provider->Build(); - }; - - $verifier = (new MessageVerifier($config)) - ->setCallbacks($callbacks) - ->verifyFiles([__DIR__ . '/../../output/test_consumer-test_provider.json']); - -``` +[Click here](/example/src/Provider/public/proxy.php) to see the full sample file. ## Usage for the optional `pact-stub-service` diff --git a/UPGRADE-9.0.md b/UPGRADE-9.0.md index 0285dbe75..5c11ae096 100644 --- a/UPGRADE-9.0.md +++ b/UPGRADE-9.0.md @@ -6,3 +6,45 @@ UPGRADE FROM 8.x to 9.0 * PACT_CORS * PACT_MOCK_SERVER_HEALTH_CHECK_TIMEOUT * PACT_MOCK_SERVER_HEALTH_CHECK_RETRY_SEC + +* Verifier + * Different pacts sources can be configured via `addXxx` methods + + Example Usage: + ```php + $config = new VerifierConfig(); + $config + ->setPort(8000) + ->setProviderName('someProvider') + ->setProviderVersion('1.0.0'); + + $url = new Url(); + $url + ->setUrl(new Uri('http://localhost')) + ->setProviderName('someProvider') + ->setUsername('user') + ->setPassword('pass') + ->setToken('token'); + + $selectors = (new ConsumerVersionSelectors()) + ->addSelector('{"tag":"foo","latest":true}') + ->addSelector('{"tag":"bar","latest":true}'); + + $broker = new Broker(); + $broker + ->setUrl(new Uri('http://localhost')) + ->setProviderName('someProvider') + ->setUsername('user') + ->setPassword('pass') + ->setToken('token') + ->setConsumerVersionSelectors($selectors); + + $verifier = new Verifier($config); + $verifier + ->addFile('C:\SomePath\consumer-provider.json'); + ->addDirectory('C:\OtherPath'); + ->addUrl($url); + ->addBroker($broker); + + $this->assertTrue($verifier->verify()); + ``` diff --git a/composer.json b/composer.json index 3deedf5e7..6e17aa512 100644 --- a/composer.json +++ b/composer.json @@ -40,7 +40,6 @@ }, "require-dev": { "roave/security-advisories": "dev-latest", - "mockery/mockery": "^1.4.2", "slim/slim": "^4.6", "slim/psr7": "^1.2.0", "friendsofphp/php-cs-fixer": "^3.0", @@ -66,11 +65,14 @@ "MessageProvider\\": [ "example/src/MessageProvider", "example/tests/MessageProvider" + ], + "Provider\\": [ + "example/src/Provider" ] } }, "scripts": { - "start-provider": "php -S localhost:58000 -t example/src/Provider/public/", + "start-provider": "php -S localhost:58000 -t example/src/Provider/public/ example/src/Provider/public/proxy.php", "static-code-analysis": "phpstan", "lint": "php-cs-fixer fix --dry-run", "fix": "php-cs-fixer fix", diff --git a/example/README.md b/example/README.md index bb79b88ea..ab66a43b3 100644 --- a/example/README.md +++ b/example/README.md @@ -16,10 +16,6 @@ All examples could be run within tests. ## Consumer Tests for Message Processing vendor/bin/phpunit -c example/phpunit.message.consumer.xml - -## Provider Verification Tests for Message Processing - - vendor/bin/phpunit -c example/phpunit.message.provider.xml ## All tests together diff --git a/example/pacts/someconsumer-someprovider.json b/example/pacts/someconsumer-someprovider.json index c502e5ba4..f9a78bce9 100644 --- a/example/pacts/someconsumer-someprovider.json +++ b/example/pacts/someconsumer-someprovider.json @@ -47,7 +47,7 @@ "matchingRules": { "$.body.message": { "match": "regex", - "regex": "(Hello, )[A-Za-z]" + "regex": "(Hello, )[A-Za-z]+" } } }, diff --git a/example/pacts/test_consumer-test_provider.json b/example/pacts/test_consumer-test_provider.json index a015e9ae1..ae5e2dab4 100644 --- a/example/pacts/test_consumer-test_provider.json +++ b/example/pacts/test_consumer-test_provider.json @@ -47,7 +47,7 @@ ], "metadata": { "pactSpecification": { - "version": "2.0.0" + "version": "3.0.0" } } } diff --git a/example/phpunit.all.xml b/example/phpunit.all.xml index 02a047d51..3cc67cbf3 100644 --- a/example/phpunit.all.xml +++ b/example/phpunit.all.xml @@ -13,9 +13,6 @@ ./tests/MessageConsumer - - ./tests/MessageProvider - diff --git a/example/phpunit.message.provider.xml b/example/phpunit.message.provider.xml deleted file mode 100644 index 2844c97d4..000000000 --- a/example/phpunit.message.provider.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - ./tests/MessageProvider - - - diff --git a/example/src/Consumer/publish_json_example.php b/example/src/Consumer/publish_json_example.php deleted file mode 100644 index 9e91327b5..000000000 --- a/example/src/Consumer/publish_json_example.php +++ /dev/null @@ -1,16 +0,0 @@ - 'someConsumer', - 'provider' => 'someProvider' -]); - -$httpService->publishJson('1.0.0', $json); diff --git a/example/src/MessageProvider/ExampleMessageProvider.php b/example/src/MessageProvider/ExampleMessageProvider.php index d038e8f22..49276a56f 100644 --- a/example/src/MessageProvider/ExampleMessageProvider.php +++ b/example/src/MessageProvider/ExampleMessageProvider.php @@ -5,14 +5,14 @@ class ExampleMessageProvider { /** @var array */ - private $metadata; + private array $metadata; /** * @var mixed */ - private $contents; + private mixed $contents; - public function __construct($metadata = []) + public function __construct(array $metadata = []) { $this->metadata = $metadata; } @@ -40,7 +40,7 @@ public function setMetadata(array $metadata): self /** * @return mixed */ - public function getContents() + public function getContents(): mixed { return $this->contents; } @@ -50,7 +50,7 @@ public function getContents() * * @return ExampleMessageProvider */ - public function setContents($contents) + public function setContents(mixed $contents): self { $this->contents = $contents; @@ -62,7 +62,7 @@ public function setContents($contents) * * @return string */ - public function Build() + public function Build(): string { $obj = new \stdClass(); $obj->metadata = $this->metadata; diff --git a/example/src/Provider/ExampleProvider.php b/example/src/Provider/ExampleProvider.php new file mode 100644 index 000000000..66a079815 --- /dev/null +++ b/example/src/Provider/ExampleProvider.php @@ -0,0 +1,95 @@ +messages = [ + 'an alligator named Mary exists' => [ + 'metadata' => [ + 'queue' => 'wind cries', + 'routing_key' => 'wind cries', + ], + 'contents' => [ + 'text' => 'Hello Mary', + ] + ], + 'footprints dressed in red' => [ + 'metadata' => [ + 'queue' => 'And the clowns have all gone to bed', + 'routing_key' => 'And the clowns have all gone to bed', + ], + 'contents' => [ + 'song' => 'And the wind whispers Mary', + ] + ], + ]; + } + + /** + * @param string $name + * + * @return string + */ + public function sayHello(string $name): string + { + return "Hello, {$name}"; + } + + /** + * @param string $name + * + * @return string + */ + public function sayGoodbye(string $name): string + { + return "Goodbye, {$name}"; + } + + /** + * @param string $description + * @param array $providerStates + * + * @return ExampleMessageProvider|null + */ + public function dispatchMessage(string $description, array $providerStates): ?ExampleMessageProvider + { + if (!isset($this->messages[$description])) { + return null; + } + + return (new ExampleMessageProvider()) + ->setMetadata($this->messages[$description]['metadata']) + ->setContents($this->messages[$description]['contents']); + } + + /** + * @param string $action + * @param string $state + * @param array $params + * + * @return ExampleMessageProvider + */ + public function changeSate(string $action, string $state, array $params): void + { + $this->currentState = [ + 'action' => $action, + 'state' => $state, + 'params' => $params, + ]; + } +} diff --git a/example/src/Provider/public/index.php b/example/src/Provider/public/index.php index 2a5406ed3..42de647d0 100644 --- a/example/src/Provider/public/index.php +++ b/example/src/Provider/public/index.php @@ -1,5 +1,6 @@ get('/hello/{name}', function (Request $request, Response $response) { +$provider = new ExampleProvider(); + +$app->get('/hello/{name}', function (Request $request, Response $response) use ($provider) { $name = $request->getAttribute('name'); - $response->getBody()->write(\json_encode(['message' => "Hello, {$name}"])); + $response->getBody()->write(\json_encode(['message' => $provider->sayHello($name)])); return $response->withHeader('Content-Type', 'application/json'); }); -$app->get('/goodbye/{name}', function (Request $request, Response $response) { +$app->get('/goodbye/{name}', function (Request $request, Response $response) use ($provider) { $name = $request->getAttribute('name'); - $response->getBody()->write(\json_encode(['message' => "Goodbye, {$name}"])); + $response->getBody()->write(\json_encode(['message' => $provider->sayGoodbye($name)])); return $response->withHeader('Content-Type', 'application/json'); }); diff --git a/example/src/Provider/public/proxy.php b/example/src/Provider/public/proxy.php new file mode 100644 index 000000000..8be81bb65 --- /dev/null +++ b/example/src/Provider/public/proxy.php @@ -0,0 +1,41 @@ +addBodyParsingMiddleware(); + +$provider = new ExampleProvider(); + +$app->post('/pact-messages', function (Request $request, Response $response) use ($provider) { + $body = $request->getParsedBody(); + $message = $provider->dispatchMessage($body['description'], $body['providerStates']); + if ($message) { + $response->getBody()->write(\json_encode($message->getContents())); + + return $response + ->withHeader('Content-Type', 'application/json') + ->withHeader('Pact-Message-Metadata', \base64_encode(\json_encode($message->getMetadata()))); + } + + return $response; +}); + +$app->post('/pact-change-state', function (Request $request, Response $response) use ($provider) { + $body = $request->getParsedBody(); + $provider->changeSate($body['action'], $body['state'], $body['params']); + + return $response; +}); + +try { + $app->run(); +} catch (HttpNotFoundException $exception) { + return false; +} diff --git a/example/tests/MessageProvider/ExampleMessageProviderTest.php b/example/tests/MessageProvider/ExampleMessageProviderTest.php deleted file mode 100644 index 21906049f..000000000 --- a/example/tests/MessageProvider/ExampleMessageProviderTest.php +++ /dev/null @@ -1,61 +0,0 @@ -text ='Hello Mary'; - - $metadata = []; - $metadata['queue'] = 'myKey'; - - $provider = (new ExampleMessageProvider()) - ->setContents($content) - ->setMetadata($metadata); - - return $provider->Build(); - }; - - $callbacks['footprints dressed in red'] = function () { - $content = new \stdClass(); - $content->song ='And the wind whispers Mary'; - - $metadata = []; - $metadata['queue'] = 'myKey'; - - $provider = (new ExampleMessageProvider()) - ->setContents($content) - ->setMetadata($metadata); - - return $provider->Build(); - }; - - $config = new VerifierConfig(); - $config - ->setProviderName('someProvider') // Providers name to fetch. - ->setPublishResults(false); // Flag the verifier service to publish the results to the Pact Broker. - - // Verify that the Consumer 'someConsumer' that is tagged with 'master' is valid. - $verifier = (new MessageVerifier($config)) - ->setCallbacks($callbacks) - ->verifyFiles([__DIR__ . '/../../pacts/test_consumer-test_provider.json']); - - // This will not be reached if the PACT verifier throws an error, otherwise it was successful. - $this->assertTrue(true, 'Expects to reach true by running verification'); - } -} diff --git a/example/tests/Provider/PactVerifyTest.php b/example/tests/Provider/PactVerifyTest.php index f1927caa2..98b0724e6 100644 --- a/example/tests/Provider/PactVerifyTest.php +++ b/example/tests/Provider/PactVerifyTest.php @@ -3,6 +3,7 @@ namespace Provider; use GuzzleHttp\Psr7\Uri; +use PhpPact\Standalone\ProviderVerifier\Model\Config\ProviderTransport; use PhpPact\Standalone\ProviderVerifier\Model\VerifierConfig; use PhpPact\Standalone\ProviderVerifier\Verifier; use PhpPact\Standalone\Runner\ProcessRunner; @@ -15,7 +16,7 @@ class PactVerifyTest extends TestCase { /** @var ProcessRunner */ - private $processRunner; + private ProcessRunner $processRunner; /** * Run the PHP build-in web server. @@ -24,9 +25,10 @@ protected function setUp(): void { $publicPath = __DIR__ . '/../../src/Provider/public/'; - $this->processRunner = new ProcessRunner('php', ['-S', 'localhost:7202', '-t', $publicPath]); + $this->processRunner = new ProcessRunner('php', ['-S', 'localhost:7202', '-t', $publicPath, $publicPath . 'proxy.php']); $this->processRunner->run(); + \sleep(1); // wait for server to start } /** @@ -43,18 +45,29 @@ protected function tearDown(): void public function testPactVerifyConsumer() { $config = new VerifierConfig(); - $config - ->setProviderName('someProvider') // Providers name to fetch. - ->setProviderVersion('1.0.0') // Providers version. - ->setProviderBranch('main') // Providers git branch - ->setProviderBaseUrl(new Uri('http://localhost:7202')) // URL of the Provider. - ; // Flag the verifier service to publish the results to the Pact Broker. + $config->getProviderInfo() + ->setName('someProvider') // Providers name to fetch. + ->setHost('localhost') + ->setPort(7202); + $config->getProviderState() + ->setStateChangeUrl(new Uri('http://localhost:7202/pact-change-state')) + ; + $config->addProviderTransport( + (new ProviderTransport()) + ->setProtocol(ProviderTransport::MESSAGE_PROTOCOL) + ->setPort(7202) + ->setPath('/pact-messages') + ->setScheme('http') + ); + if ($level = \getenv('PACT_LOGLEVEL')) { + $config->setLogLevel($level); + } // Verify that the Consumer 'someConsumer' that is tagged with 'master' is valid. $verifier = new Verifier($config); - $verifier->verifyFiles([__DIR__ . '/../../pacts/someconsumer-someprovider.json']); + $verifier->addFile(__DIR__ . '/../../pacts/someconsumer-someprovider.json'); + $verifier->addFile(__DIR__ . '/../../pacts/test_consumer-test_provider.json'); - // This will not be reached if the PACT verifier throws an error, otherwise it was successful. - $this->assertTrue(true, 'Pact Verification has failed.'); + $this->assertTrue($verifier->verify()); } } diff --git a/src/PhpPact/Broker/Service/BrokerHttpClient.php b/src/PhpPact/Broker/Service/BrokerHttpClient.php deleted file mode 100644 index 53be68e7f..000000000 --- a/src/PhpPact/Broker/Service/BrokerHttpClient.php +++ /dev/null @@ -1,109 +0,0 @@ - - */ - private array $headers; - - /** - * {@inheritdoc} - */ - public function __construct(ClientInterface $httpClient, UriInterface $baseUri, array $headers = []) - { - $this->httpClient = $httpClient; - $this->baseUri = $baseUri; - $this->headers = $headers; - - if (!\array_key_exists('Content-Type', $headers)) { - $this->headers['Content-Type'] = 'application/json'; - } - } - - /** - * {@inheritdoc} - */ - public function publishJson(string $version, string $json): void - { - $array = \json_decode($json, true, 512, JSON_THROW_ON_ERROR); - $consumer = $array['consumer']['name']; - $provider = $array['provider']['name']; - - $uri = $this->baseUri->withPath("/pacts/provider/{$provider}/consumer/{$consumer}/version/{$version}"); - - $this->httpClient->put($uri, [ - 'headers' => $this->headers, - 'body' => $json, - ]); - } - - /** - * {@inheritdoc} - */ - public function tag(string $consumer, string $version, string $tag): void - { - $uri = $this->baseUri->withPath("/pacticipants/{$consumer}/versions/{$version}/tags/{$tag}"); - $this->httpClient->put($uri, [ - 'headers' => $this->headers, - ]); - } - - /** - * {@inheritdoc} - */ - public function getAllConsumerUrls(string $provider, string $version = 'latest'): array - { - if ($version !== 'latest') { - @\trigger_error(\sprintf('The second argument "version" in "%s()" method makes no sense and will be removed in any upcoming major version', __METHOD__), E_USER_DEPRECATED); - } - - $uri = $this->baseUri->withPath("/pacts/provider/{$provider}/latest"); - - $response = $this->httpClient->get($uri, [ - 'headers' => $this->headers, - ]); - - $json = \json_decode($response->getBody()->getContents(), true, 512, JSON_THROW_ON_ERROR); - - $urls = []; - foreach ($json['_links']['pacts'] as $pact) { - $urls[] = $pact['href']; - } - - return $urls; - } - - /** - * {@inheritdoc} - */ - public function getAllConsumerUrlsForTag(string $provider, string $tag): array - { - $uri = $this->baseUri->withPath("/pacts/provider/{$provider}/latest/{$tag}"); - - $response = $this->httpClient->get($uri, [ - 'headers' => $this->headers, - ]); - - $json = \json_decode($response->getBody()->getContents(), true, 512, JSON_THROW_ON_ERROR); - - $urls = []; - foreach ($json['_links']['pacts'] as $pact) { - $urls[] = $pact['href']; - } - - return $urls; - } -} diff --git a/src/PhpPact/Broker/Service/BrokerHttpClientInterface.php b/src/PhpPact/Broker/Service/BrokerHttpClientInterface.php deleted file mode 100644 index e4baa16ac..000000000 --- a/src/PhpPact/Broker/Service/BrokerHttpClientInterface.php +++ /dev/null @@ -1,49 +0,0 @@ - $headers additional headers - */ - public function __construct(ClientInterface $client, UriInterface $baseUri, array $headers); - - /** - * Publish JSON. - * - * @param string $version Consumer version - * @param string $json PACT File JSON - */ - public function publishJson(string $version, string $json): void; - - /** - * Tag a consumer version with a tag. - */ - public function tag(string $consumer, string $version, string $tag): void; - - /** - * Get all Pact urls for the consumer. - * - * @param string $provider provider name - * @param string $version version of the provider - * - * @return array - */ - public function getAllConsumerUrls(string $provider, string $version = 'latest'): array; - - /** - * Get all Pact URLs for a specific tag. - * - * @return array - */ - public function getAllConsumerUrlsForTag(string $provider, string $tag): array; -} diff --git a/src/PhpPact/Provider/MessageVerifier.php b/src/PhpPact/Provider/MessageVerifier.php deleted file mode 100644 index 7c5a71130..000000000 --- a/src/PhpPact/Provider/MessageVerifier.php +++ /dev/null @@ -1,208 +0,0 @@ - */ - protected array $callbacks = []; - - /** - * Default host name for the proxy server - */ - protected string $defaultProxyHost = 'localhost'; - - /** - * Default port for the proxy server to listen on - */ - protected int $defaultProxyPort = 7201; - - /** - * floor(provider-verification timeout / this value) = default verificationDelaySec - */ - protected int $defaultDelayFactor = 3; - - /** - * Set the number of seconds to delay the verification test to allow the proxy server to be stood up - * - * By default, it is a third of the provider-verification timeout - */ - protected float $verificationDelaySec; - - private ?LoggerInterface $logger = null; - - public function __construct(VerifierConfigInterface $config) - { - parent::__construct($config); - - $this->callbacks = []; - - $baseUrl = $this->config->getProviderBaseUrl(); - if ($baseUrl === null) { - $config->setProviderBaseUrl(new Uri("http://{$this->defaultProxyHost}:{$this->defaultProxyPort}")); - } - - // default verification delay - $this->setVerificationDelaySec(\floor($config->getProcessIdleTimeout() / $this->defaultDelayFactor)); - } - - /** - * @param array $callbacks - */ - public function setCallbacks(array $callbacks): self - { - $this->callbacks = $callbacks; - - return $this; - } - - /** - * Add an individual call back - * - * @throws \Exception - */ - public function addCallback(string $key, callable $callback): self - { - if (isset($this->callbacks[$key])) { - throw new \Exception("Callback with key ($key) already exists"); - } - - $this->callbacks[$key] = $callback; - - return $this; - } - - public function setVerificationDelaySec(float $verificationDelaySec): self - { - $this->verificationDelaySec = $verificationDelaySec; - - return $this; - } - - public function setLogger(LoggerInterface $logger): self - { - $this->logger = $logger; - - return $this; - } - - /** - * @throws \Exception - */ - protected function verifyAction(array $arguments): void - { - if (\count($this->callbacks) < 1) { - throw new \Exception('Callback needs to bet set when using message pacts'); - } - - $callbacks = $this->callbacks; - $uri = $this->config->getProviderBaseUrl(); - - $arguments = \array_merge([Scripts::getProviderVerifier()], $arguments); - - /** - * @throws \Amp\Socket\SocketException - * @throws \Error - * @throws \TypeError - * - * @return \Generator - */ - $lambdaLoop = function () use ($callbacks, $arguments, $uri) { - // spin up a server - $url = "{$uri->getHost()}:{$uri->getPort()}"; - $servers = [ - Socket\Server::listen($url) - ]; - - $logger = $this->getLogger(); - - $server = new Server($servers, new CallableRequestHandler(function (Request $request) use ($callbacks) { - if (\count($callbacks) === 1) { - $callback = \array_pop($callbacks); - } else { - $payload = new Payload($request->getBody()); - $requestBody = yield $payload->buffer(); - $requestBody = \json_decode($requestBody); - $description = $requestBody->description; - - $callback = false; - - if (isset($this->callbacks[$description])) { - $callback = $this->callbacks[$description]; - } - - if ($callback === false) { - throw new \Exception("Pacts with multiple states need to have callbacks key'ed by the description"); - } - } - - //@todo pass $providerStates to the call back - $out = \call_user_func($callback); - - // return response should only happen if the \call_user_fun() - return new Response(Status::OK, [ - 'content-type' => 'application/json;', - ], $out); - }), $logger); - - yield $server->start(); - - // delay long enough for the server to be stood up - $delay = (int) ($this->verificationDelaySec * 1000); - - // call the provider-verification cmd - Loop::delay($delay, function () use ($arguments) { - $cmd = \implode(' ', $arguments); - $process = new Process($cmd); - yield $process->start(); - - $payload = new Payload($process->getStdout()); - print yield $payload->buffer(); - - $code = yield $process->join(); - - // if the provider verification cmd returns a non-zero number, the test failed - if ($code !== 0) { - $this->getLogger()->warning(yield $process->getStderr()->read()); - - throw new \Exception("Pact failed to validate. Exit code: {$code}"); - } - - Loop::stop(); - }); - }; - - Loop::run($lambdaLoop); - } - - private function getLogger(): LoggerInterface - { - if (null === $this->logger) { - $logHandler = new StreamHandler(new ResourceOutputStream(\STDOUT)); - $logHandler->setFormatter(new ConsoleFormatter(null, null, true)); - $this->logger = new Logger('server'); - $this->logger->pushHandler($logHandler); - } - - return $this->logger; - } -} diff --git a/src/PhpPact/Standalone/Exception/CDataNotCreatedException.php b/src/PhpPact/Standalone/Exception/CDataNotCreatedException.php new file mode 100644 index 000000000..62f7579b6 --- /dev/null +++ b/src/PhpPact/Standalone/Exception/CDataNotCreatedException.php @@ -0,0 +1,9 @@ +items; + } + + public function getSize(): int + { + return $this->size; + } + + /** + * @param array $values + */ + public static function createFrom(array $values): ?self + { + $size = count($values); + if ($size === 0) { + return null; + } + + $items = FFI::new("char*[{$size}]"); + if ($items === null) { + return throw new CDataNotCreatedException(); + } + foreach ($values as $index => $value) { + $length = \strlen($value); + $itemSize = $length + 1; + $item = FFI::new("char[{$itemSize}]", false); + FFI::memcpy($item, $value, $length); + $items[$index] = $item; // @phpstan-ignore-line + } + + return new self($items, $size); + } + + public function __destruct() + { + for ($i=0; $i < $this->size; $i++) { + FFI::free($this->items[$i]); // @phpstan-ignore-line + } + } +} diff --git a/src/PhpPact/Standalone/ProviderVerifier/Model/Config/CallingApp.php b/src/PhpPact/Standalone/ProviderVerifier/Model/Config/CallingApp.php new file mode 100644 index 000000000..2b7630fa3 --- /dev/null +++ b/src/PhpPact/Standalone/ProviderVerifier/Model/Config/CallingApp.php @@ -0,0 +1,33 @@ +name; + } + + public function setName(?string $name): CallingAppInterface + { + $this->name = $name; + + return $this; + } + + public function getVersion(): ?string + { + return $this->version; + } + + public function setVersion(?string $version): CallingAppInterface + { + $this->version = $version; + + return $this; + } +} diff --git a/src/PhpPact/Standalone/ProviderVerifier/Model/Config/CallingAppInterface.php b/src/PhpPact/Standalone/ProviderVerifier/Model/Config/CallingAppInterface.php new file mode 100644 index 000000000..bae0ec057 --- /dev/null +++ b/src/PhpPact/Standalone/ProviderVerifier/Model/Config/CallingAppInterface.php @@ -0,0 +1,14 @@ + + */ + private array $filterConsumerNames = []; + + public function setFilterConsumerNames(array $filterConsumerNames): self + { + $this->filterConsumerNames = []; + foreach ($filterConsumerNames as $filterConsumerName) { + $this->addFilterConsumerName($filterConsumerName); + } + + return $this; + } + + public function addFilterConsumerName(string $filterConsumerName): self + { + $this->filterConsumerNames[] = $filterConsumerName; + + return $this; + } + + public function getFilterConsumerNames(): array + { + return $this->filterConsumerNames; + } +} diff --git a/src/PhpPact/Standalone/ProviderVerifier/Model/Config/ConsumerFiltersInterface.php b/src/PhpPact/Standalone/ProviderVerifier/Model/Config/ConsumerFiltersInterface.php new file mode 100644 index 000000000..91402e7b1 --- /dev/null +++ b/src/PhpPact/Standalone/ProviderVerifier/Model/Config/ConsumerFiltersInterface.php @@ -0,0 +1,18 @@ + $filterConsumerNames + */ + public function setFilterConsumerNames(array $filterConsumerNames): self; + + public function addFilterConsumerName(string $filterConsumerName): self; + + /** + * @return array + */ + public function getFilterConsumerNames(): array; +} diff --git a/src/PhpPact/Standalone/ProviderVerifier/Model/Config/FilterInfo.php b/src/PhpPact/Standalone/ProviderVerifier/Model/Config/FilterInfo.php new file mode 100644 index 000000000..1f5cdce6a --- /dev/null +++ b/src/PhpPact/Standalone/ProviderVerifier/Model/Config/FilterInfo.php @@ -0,0 +1,46 @@ +filterDescription; + } + + public function setFilterDescription(?string $filterDescription): self + { + $this->filterDescription = $filterDescription; + + return $this; + } + + public function getFilterNoState(): bool + { + return $this->filterNoState; + } + + public function setFilterNoState(bool $filterNoState): self + { + $this->filterNoState = $filterNoState; + + return $this; + } + + public function getFilterState(): ?string + { + return $this->filterState; + } + + public function setFilterState(?string $filterState): self + { + $this->filterState = $filterState; + + return $this; + } +} diff --git a/src/PhpPact/Standalone/ProviderVerifier/Model/Config/FilterInfoInterface.php b/src/PhpPact/Standalone/ProviderVerifier/Model/Config/FilterInfoInterface.php new file mode 100644 index 000000000..51420ae87 --- /dev/null +++ b/src/PhpPact/Standalone/ProviderVerifier/Model/Config/FilterInfoInterface.php @@ -0,0 +1,18 @@ +pluginDir; + } + + public function setPluginDir(?string $pluginDir): self + { + $this->pluginDir = $pluginDir; + + return $this; + } +} diff --git a/src/PhpPact/Standalone/ProviderVerifier/Model/Config/ProviderInfo.php b/src/PhpPact/Standalone/ProviderVerifier/Model/Config/ProviderInfo.php new file mode 100644 index 000000000..375af81c8 --- /dev/null +++ b/src/PhpPact/Standalone/ProviderVerifier/Model/Config/ProviderInfo.php @@ -0,0 +1,72 @@ +name; + } + + public function setName(string $name): self + { + $this->name = $name; + + return $this; + } + + public function getHost(): ?string + { + return $this->host; + } + + public function setHost(string $host): self + { + $this->host = $host; + + return $this; + } + + public function getScheme(): ?string + { + return $this->scheme; + } + + public function setScheme(?string $scheme): self + { + $this->scheme = $scheme; + + return $this; + } + + public function getPort(): ?int + { + return $this->port; + } + + public function setPort(?int $port): self + { + $this->port = $port; + + return $this; + } + + public function getPath(): ?string + { + return $this->path; + } + + public function setPath(?string $path): self + { + $this->path = $path; + + return $this; + } +} diff --git a/src/PhpPact/Standalone/ProviderVerifier/Model/Config/ProviderInfoInterface.php b/src/PhpPact/Standalone/ProviderVerifier/Model/Config/ProviderInfoInterface.php new file mode 100644 index 000000000..d76d297ad --- /dev/null +++ b/src/PhpPact/Standalone/ProviderVerifier/Model/Config/ProviderInfoInterface.php @@ -0,0 +1,26 @@ +stateChangeUrl; + } + + public function setStateChangeUrl(?UriInterface $stateChangeUrl): self + { + $this->stateChangeUrl = $stateChangeUrl; + + return $this; + } + + public function setStateChangeAsBody(bool $stateChangeAsBody): self + { + $this->stateChangeAsBody = $stateChangeAsBody; + + return $this; + } + + public function isStateChangeAsBody(): bool + { + return $this->stateChangeAsBody; + } + + public function setStateChangeTeardown(bool $stateChangeTeardown): self + { + $this->stateChangeTeardown = $stateChangeTeardown; + + return $this; + } + + public function isStateChangeTeardown(): bool + { + return $this->stateChangeTeardown; + } +} diff --git a/src/PhpPact/Standalone/ProviderVerifier/Model/Config/ProviderStateInterface.php b/src/PhpPact/Standalone/ProviderVerifier/Model/Config/ProviderStateInterface.php new file mode 100644 index 000000000..a51f86193 --- /dev/null +++ b/src/PhpPact/Standalone/ProviderVerifier/Model/Config/ProviderStateInterface.php @@ -0,0 +1,20 @@ +protocol; + } + + public function setProtocol(?string $protocol): self + { + $this->protocol = $protocol; + + return $this; + } + + public function getScheme(): ?string + { + return $this->scheme; + } + + public function setScheme(?string $scheme): self + { + $this->scheme = $scheme; + + return $this; + } + + public function getPort(): ?int + { + return $this->port; + } + + public function setPort(?int $port): self + { + $this->port = $port; + + return $this; + } + + public function getPath(): ?string + { + return $this->path; + } + + public function setPath(?string $path): self + { + $this->path = $path; + + return $this; + } +} diff --git a/src/PhpPact/Standalone/ProviderVerifier/Model/Config/ProviderTransportInterface.php b/src/PhpPact/Standalone/ProviderVerifier/Model/Config/ProviderTransportInterface.php new file mode 100644 index 000000000..ad269b167 --- /dev/null +++ b/src/PhpPact/Standalone/ProviderVerifier/Model/Config/ProviderTransportInterface.php @@ -0,0 +1,28 @@ + + */ + private array $providerTags = []; + private string $providerVersion; + private ?UriInterface $buildUrl = null; + private ?string $providerBranch = null; + + public function getProviderTags(): array + { + return $this->providerTags; + } + + public function setProviderTags(array $providerTags): self + { + $this->providerTags = []; + foreach ($providerTags as $providerTag) { + $this->addProviderTag($providerTag); + } + + return $this; + } + + public function addProviderTag(string $providerTag): self + { + $this->providerTags[] = $providerTag; + + return $this; + } + + public function getProviderVersion(): string + { + return $this->providerVersion; + } + + public function setProviderVersion(string $providerVersion): self + { + $this->providerVersion = $providerVersion; + + return $this; + } + + public function getBuildUrl(): ?UriInterface + { + return $this->buildUrl; + } + + public function setBuildUrl(?UriInterface $buildUrl): self + { + $this->buildUrl = $buildUrl; + + return $this; + } + + public function getProviderBranch(): ?string + { + return $this->providerBranch; + } + + public function setProviderBranch(?string $providerBranch): self + { + $this->providerBranch = $providerBranch; + + return $this; + } +} diff --git a/src/PhpPact/Standalone/ProviderVerifier/Model/Config/PublishOptionsInterface.php b/src/PhpPact/Standalone/ProviderVerifier/Model/Config/PublishOptionsInterface.php new file mode 100644 index 000000000..00429e899 --- /dev/null +++ b/src/PhpPact/Standalone/ProviderVerifier/Model/Config/PublishOptionsInterface.php @@ -0,0 +1,32 @@ + + */ + public function getProviderTags(): array; + + /** + * @param array $providerTags + */ + public function setProviderTags(array $providerTags): self; + + public function addProviderTag(string $providerTag): self; + + public function getProviderVersion(): string; + + public function setProviderVersion(string $providerVersion): self; + + public function getBuildUrl(): ?UriInterface; + + public function setBuildUrl(UriInterface $buildUrl): self; + + public function getProviderBranch(): ?string; + + public function setProviderBranch(?string $providerBranch): self; +} diff --git a/src/PhpPact/Standalone/ProviderVerifier/Model/Config/VerificationOptions.php b/src/PhpPact/Standalone/ProviderVerifier/Model/Config/VerificationOptions.php new file mode 100644 index 000000000..5e6c25a8b --- /dev/null +++ b/src/PhpPact/Standalone/ProviderVerifier/Model/Config/VerificationOptions.php @@ -0,0 +1,33 @@ +disableSslVerification; + } + + public function setDisableSslVerification(bool $disableSslVerification): self + { + $this->disableSslVerification = $disableSslVerification; + + return $this; + } + + public function setRequestTimeout(int $requestTimeout): self + { + $this->requestTimeout = $requestTimeout; + + return $this; + } + + public function getRequestTimeout(): int + { + return $this->requestTimeout; + } +} diff --git a/src/PhpPact/Standalone/ProviderVerifier/Model/Config/VerificationOptionsInterface.php b/src/PhpPact/Standalone/ProviderVerifier/Model/Config/VerificationOptionsInterface.php new file mode 100644 index 000000000..093fbbf7d --- /dev/null +++ b/src/PhpPact/Standalone/ProviderVerifier/Model/Config/VerificationOptionsInterface.php @@ -0,0 +1,14 @@ +> */ - private array $selectors; + /** @var array */ + private array $selectors = []; /** * @param array $selectors @@ -30,37 +30,31 @@ public function addSelector(string $selector): self return $this; } - #[\ReturnTypeWillChange] - public function current() + public function current(): string { return $this->selectors[$this->position]; } - #[\ReturnTypeWillChange] - public function next() + public function next(): void { ++$this->position; } - #[\ReturnTypeWillChange] public function key(): int { return $this->position; } - #[\ReturnTypeWillChange] public function valid(): bool { return isset($this->selectors[$this->position]); } - #[\ReturnTypeWillChange] - public function rewind() + public function rewind(): void { $this->position = 0; } - #[\ReturnTypeWillChange] public function count(): int { return \count($this->selectors); diff --git a/src/PhpPact/Standalone/ProviderVerifier/Model/Source/Broker.php b/src/PhpPact/Standalone/ProviderVerifier/Model/Source/Broker.php new file mode 100644 index 000000000..8b1cc29dd --- /dev/null +++ b/src/PhpPact/Standalone/ProviderVerifier/Model/Source/Broker.php @@ -0,0 +1,118 @@ + + */ + private array $providerTags = []; + protected ?string $providerBranch = null; + protected ConsumerVersionSelectors $consumerVersionSelectors; + /** + * @var array + */ + private array $consumerVersionTags = []; + + public function __construct() + { + $this->consumerVersionSelectors = new ConsumerVersionSelectors(); + } + + public function isEnablePending(): bool + { + return $this->enablePending; + } + + public function setEnablePending(bool $enablePending): self + { + $this->enablePending = $enablePending; + + return $this; + } + + public function setIncludeWipPactSince(?string $date): self + { + $this->wipPactSince = $date; + + return $this; + } + + public function getIncludeWipPactSince(): ?string + { + return $this->wipPactSince; + } + + public function getProviderTags(): array + { + return $this->providerTags; + } + + public function setProviderTags(array $providerTags): self + { + $this->providerTags = []; + foreach ($providerTags as $providerTag) { + $this->addProviderTag($providerTag); + } + + return $this; + } + + public function addProviderTag(string $providerTag): self + { + $this->providerTags[] = $providerTag; + + return $this; + } + + public function getProviderBranch(): ?string + { + return $this->providerBranch; + } + + public function setProviderBranch(?string $providerBranch): self + { + $this->providerBranch = $providerBranch; + + return $this; + } + + public function getConsumerVersionSelectors(): ConsumerVersionSelectors + { + return $this->consumerVersionSelectors; + } + + public function setConsumerVersionSelectors(ConsumerVersionSelectors $selectors): self + { + $this->consumerVersionSelectors = $selectors; + + return $this; + } + + public function getConsumerVersionTags(): array + { + return $this->consumerVersionTags; + } + + public function setConsumerVersionTags(array $consumerVersionTags): self + { + $this->consumerVersionTags = []; + foreach ($consumerVersionTags as $consumerVersionTag) { + $this->addConsumerVersionTag($consumerVersionTag); + } + + return $this; + } + + public function addConsumerVersionTag(string $consumerVersionTag): self + { + $this->consumerVersionTags[] = $consumerVersionTag; + + return $this; + } +} diff --git a/src/PhpPact/Standalone/ProviderVerifier/Model/Source/BrokerInterface.php b/src/PhpPact/Standalone/ProviderVerifier/Model/Source/BrokerInterface.php new file mode 100644 index 000000000..45419b23e --- /dev/null +++ b/src/PhpPact/Standalone/ProviderVerifier/Model/Source/BrokerInterface.php @@ -0,0 +1,52 @@ + + */ + public function getProviderTags(): array; + + /** + * @param array $providerTags + */ + public function setProviderTags(array $providerTags): self; + + public function addProviderTag(string $providerTag): self; + + public function getProviderBranch(): ?string; + + public function setProviderBranch(?string $providerBranch): self; + + public function getConsumerVersionSelectors(): ConsumerVersionSelectors; + + public function setConsumerVersionSelectors(ConsumerVersionSelectors $selectors): self; + + /** + * @return array + */ + public function getConsumerVersionTags(): array; + + /** + * @param array $consumerVersionTags + */ + public function setConsumerVersionTags(array $consumerVersionTags): self; + + public function addConsumerVersionTag(string $consumerVersionTag): self; +} diff --git a/src/PhpPact/Standalone/ProviderVerifier/Model/Source/Url.php b/src/PhpPact/Standalone/ProviderVerifier/Model/Source/Url.php new file mode 100644 index 000000000..eb3dd1fb8 --- /dev/null +++ b/src/PhpPact/Standalone/ProviderVerifier/Model/Source/Url.php @@ -0,0 +1,61 @@ +url; + } + + public function setUrl(UriInterface $url): self + { + $this->url = $url; + + return $this; + } + + public function getToken(): ?string + { + return $this->token; + } + + public function setToken(?string $token): self + { + $this->token = $token; + + return $this; + } + + public function getUsername(): ?string + { + return $this->username; + } + + public function setUsername(string $username): self + { + $this->username = $username; + + return $this; + } + + public function getPassword(): ?string + { + return $this->password; + } + + public function setPassword(string $password): self + { + $this->password = $password; + + return $this; + } +} diff --git a/src/PhpPact/Standalone/ProviderVerifier/Model/Source/UrlInterface.php b/src/PhpPact/Standalone/ProviderVerifier/Model/Source/UrlInterface.php new file mode 100644 index 000000000..cfc8effa0 --- /dev/null +++ b/src/PhpPact/Standalone/ProviderVerifier/Model/Source/UrlInterface.php @@ -0,0 +1,24 @@ + - */ - private array $providerVersionTag = []; - - private bool $publishResults = false; - - private ?UriInterface $brokerUri = null; - - private ?string $brokerToken = null; - - private ?string $brokerUsername = null; - - private ?string $brokerPassword = null; + private CallingAppInterface $callingApp; + private ProviderInfoInterface $providerInfo; /** - * @var array + * @var array */ - private array $customProviderHeaders = []; - - private bool $verbose = false; - - private ?string $logDirectory = null; - - private ?string $format = null; - - private int $processTimeout = 60; - - private int $processIdleTimeout = 10; + private array $providerTransports = []; - private bool $enablePending = false; - - private ?string $wipPactSince = null; - - /** - * @var array - */ - private array $consumerVersionTag = []; - - private ConsumerVersionSelectors $consumerVersionSelectors; - - /** @var null|callable */ - private $requestFilter = null; + private FilterInfoInterface $filterInfo; + private ProviderStateInterface $providerState; + private VerificationOptionsInterface $verificationOptions; + private ?PublishOptionsInterface $publishOptions = null; + private ConsumerFiltersInterface $consumerFilters; public function __construct() { - $this->consumerVersionSelectors = new ConsumerVersionSelectors(); - } - - /** - * {@inheritdoc} - */ - public function getProviderBaseUrl(): ?UriInterface - { - return $this->providerBaseUrl; - } - - /** - * {@inheritdoc} - */ - public function setProviderBaseUrl(UriInterface $providerBaseUrl): VerifierConfigInterface - { - $this->providerBaseUrl = $providerBaseUrl; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function getProviderStatesSetupUrl(): ?string - { - return $this->providerStatesSetupUrl; - } - - /** - * {@inheritdoc} - */ - public function setProviderStatesSetupUrl(string $providerStatesSetupUrl): VerifierConfigInterface - { - $this->providerStatesSetupUrl = $providerStatesSetupUrl; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function getProviderName(): ?string - { - return $this->providerName; - } - - /** - * {@inheritdoc} - */ - public function setProviderName(string $providerName): VerifierConfigInterface - { - $this->providerName = $providerName; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function getProviderVersion(): ?string - { - return $this->providerVersion; - } - - /** - * {@inheritdoc} - */ - public function setProviderVersion(string $providerVersion): VerifierConfigInterface - { - $this->providerVersion = $providerVersion; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function getProviderVersionTag(): array - { - return $this->providerVersionTag; - } - - /** - * {@inheritdoc} - */ - public function setProviderVersionTag(string $providerVersionTag): VerifierConfigInterface - { - return $this->addProviderVersionTag($providerVersionTag); - } - - /** - * {@inheritdoc} - */ - public function getConsumerVersionTag(): array - { - return $this->consumerVersionTag; - } - - /** - * {@inheritdoc} - */ - public function addConsumerVersionTag(string $consumerVersionTag): VerifierConfigInterface - { - $this->consumerVersionTag[] = $consumerVersionTag; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function addProviderVersionTag(string $providerVersionTag): VerifierConfigInterface - { - $this->providerVersionTag[] = $providerVersionTag; - - return $this; - } - - public function setConsumerVersionTag(string $consumerVersionTag): VerifierConfigInterface - { - return $this->addConsumerVersionTag($consumerVersionTag); - } - - public function getConsumerVersionSelectors(): ConsumerVersionSelectors - { - return $this->consumerVersionSelectors; - } - - public function setConsumerVersionSelectors(ConsumerVersionSelectors $selectors): VerifierConfigInterface - { - $this->consumerVersionSelectors = $selectors; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function isPublishResults(): bool - { - return $this->publishResults; + $this->callingApp = new CallingApp(); + $this->providerInfo = new ProviderInfo(); + $this->filterInfo = new FilterInfo(); + $this->providerState = new ProviderState(); + $this->verificationOptions = new VerificationOptions(); + $this->consumerFilters = new ConsumerFilters(); } - /** - * {@inheritdoc} - */ - public function setPublishResults(bool $publishResults): VerifierConfigInterface + public function setCallingApp(CallingAppInterface $callingApp): self { - $this->publishResults = $publishResults; + $this->callingApp = $callingApp; return $this; } - /** - * {@inheritdoc} - */ - public function getBrokerUri(): ?UriInterface + public function getCallingApp(): CallingAppInterface { - return $this->brokerUri; + return $this->callingApp; } - /** - * {@inheritdoc} - */ - public function setBrokerUri(UriInterface $brokerUri): VerifierConfigInterface + public function setProviderInfo(ProviderInfoInterface $providerInfo): self { - $this->brokerUri = $brokerUri; + $this->providerInfo = $providerInfo; return $this; } - /** - * {@inheritdoc}} - */ - public function getBrokerToken(): ?string + public function getProviderInfo(): ProviderInfoInterface { - return $this->brokerToken; - } - - /** - * {@inheritdoc } - */ - public function setBrokerToken(?string $brokerToken): VerifierConfigInterface - { - $this->brokerToken = $brokerToken; - - return $this; + return $this->providerInfo; } /** * {@inheritdoc} */ - public function getBrokerUsername(): ?string + public function setProviderTransports(array $providerTransports): self { - return $this->brokerUsername; - } - - /** - * {@inheritdoc} - */ - public function setBrokerUsername(string $brokerUsername): VerifierConfigInterface - { - $this->brokerUsername = $brokerUsername; + $this->providerTransports = []; + foreach ($providerTransports as $providerTransport) { + $this->addProviderTransport($providerTransport); + } return $this; } - /** - * {@inheritdoc} - */ - public function getBrokerPassword(): ?string + public function addProviderTransport(ProviderTransportInterface $providerTransport): self { - return $this->brokerPassword; - } - - /** - * {@inheritdoc} - */ - public function setBrokerPassword(string $brokerPassword): self - { - $this->brokerPassword = $brokerPassword; + $this->providerTransports[] = $providerTransport; return $this; } @@ -294,169 +95,73 @@ public function setBrokerPassword(string $brokerPassword): self /** * {@inheritdoc} */ - public function getCustomProviderHeaders(): array - { - return $this->customProviderHeaders; - } - - /** - * {@inheritdoc} - */ - public function setCustomProviderHeaders(array $customProviderHeaders): VerifierConfigInterface + public function getProviderTransports(): array { - $this->customProviderHeaders = $customProviderHeaders; - - return $this; + return $this->providerTransports; } - public function addCustomProviderHeader(string $name, string $value): VerifierConfigInterface + public function setFilterInfo(FilterInfoInterface $filterInfo): self { - $this->customProviderHeaders[] = "$name: $value"; + $this->filterInfo = $filterInfo; return $this; } - /** - * {@inheritdoc} - */ - public function isVerbose(): bool + public function getFilterInfo(): FilterInfoInterface { - return $this->verbose; + return $this->filterInfo; } - /** - * {@inheritdoc} - */ - public function setVerbose(bool $verbose): VerifierConfigInterface + public function setProviderState(ProviderStateInterface $providerState): self { - $this->verbose = $verbose; + $this->providerState = $providerState; return $this; } - /** - * {@inheritdoc} - */ - public function getLogDirectory(): ?string + public function getProviderState(): ProviderStateInterface { - return $this->logDirectory; + return $this->providerState; } - /** - * {@inheritdoc} - */ - public function setLogDirectory(string $log): VerifierConfigInterface - { - $this->logDirectory = $log; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function getFormat(): ?string - { - return $this->format; - } - - /** - * {@inheritdoc} - */ - public function setFormat(string $format): VerifierConfigInterface + public function setPublishOptions(?PublishOptionsInterface $publishOptions): self { - $this->format = $format; + $this->publishOptions = $publishOptions; return $this; } - public function setProcessTimeout(int $timeout): VerifierConfigInterface - { - $this->processTimeout = $timeout; - - return $this; - } - - public function setProcessIdleTimeout(int $timeout): VerifierConfigInterface - { - $this->processIdleTimeout = $timeout; - - return $this; - } - - public function getProcessTimeout(): int - { - return $this->processTimeout; - } - - public function getProcessIdleTimeout(): int - { - return $this->processIdleTimeout; - } - - /** - * {@inheritdoc} - */ - public function isEnablePending(): bool + public function getPublishOptions(): ?PublishOptionsInterface { - return $this->enablePending; + return $this->publishOptions; } - /** - * {@inheritdoc} - */ - public function setEnablePending(bool $pending): VerifierConfigInterface + public function isPublishResults(): bool { - $this->enablePending = $pending; - - return $this; + return $this->publishOptions !== null; } - /** - * {@inheritdoc} - */ - public function setIncludeWipPactSince(string $date): VerifierConfigInterface + public function setConsumerFilters(ConsumerFiltersInterface $consumerFilters): self { - $this->wipPactSince = $date; + $this->consumerFilters = $consumerFilters; return $this; } - /** - * {@inheritdoc} - */ - public function getIncludeWipPactSince(): ?string - { - return $this->wipPactSince; - } - - public function getRequestFilter(): ?callable + public function getConsumerFilters(): ConsumerFiltersInterface { - return $this->requestFilter; + return $this->consumerFilters; } - public function setRequestFilter(callable $requestFilter): VerifierConfigInterface + public function setVerificationOptions(VerificationOptionsInterface $verificationOptions): self { - $this->requestFilter = $requestFilter; + $this->verificationOptions = $verificationOptions; return $this; } - /** - * {@inheritdoc} - */ - public function setProviderBranch(string $providerBranch): VerifierConfigInterface - { - $this->providerBranch = $providerBranch; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function getProviderBranch(): ?string + public function getVerificationOptions(): VerificationOptionsInterface { - return $this->providerBranch; + return $this->verificationOptions; } } diff --git a/src/PhpPact/Standalone/ProviderVerifier/Model/VerifierConfigInterface.php b/src/PhpPact/Standalone/ProviderVerifier/Model/VerifierConfigInterface.php index 9b748f9e9..6f13cb832 100644 --- a/src/PhpPact/Standalone/ProviderVerifier/Model/VerifierConfigInterface.php +++ b/src/PhpPact/Standalone/ProviderVerifier/Model/VerifierConfigInterface.php @@ -2,223 +2,64 @@ namespace PhpPact\Standalone\ProviderVerifier\Model; -use Psr\Http\Message\UriInterface; +use PhpPact\Standalone\ProviderVerifier\Model\Config\CallingAppInterface; +use PhpPact\Standalone\ProviderVerifier\Model\Config\ConsumerFiltersInterface; +use PhpPact\Standalone\ProviderVerifier\Model\Config\FilterInfoInterface; +use PhpPact\Standalone\ProviderVerifier\Model\Config\ProviderInfoInterface; +use PhpPact\Standalone\ProviderVerifier\Model\Config\ProviderStateInterface; +use PhpPact\Standalone\ProviderVerifier\Model\Config\ProviderTransportInterface; +use PhpPact\Standalone\ProviderVerifier\Model\Config\PublishOptionsInterface; +use PhpPact\Standalone\ProviderVerifier\Model\Config\VerificationOptionsInterface; -/** - * Configuration to use with the verifier server. - */ interface VerifierConfigInterface { - /** - * @return null|UriInterface providers base url - */ - public function getProviderBaseUrl(): ?UriInterface; + public function setCallingApp(CallingAppInterface $callingApp): self; - /** - * @param UriInterface $providerBaseUrl providers base url - */ - public function setProviderBaseUrl(UriInterface $providerBaseUrl): self; + public function getCallingApp(): CallingAppInterface; - /** - * @return null|string Base URL to setup the provider states at - */ - public function getProviderStatesSetupUrl(): ?string; + public function setProviderInfo(ProviderInfoInterface $providerInfo): self; - /** - * @param string $providerStatesSetupUrl Base URL to setup the provider states at - */ - public function setProviderStatesSetupUrl(string $providerStatesSetupUrl): self; + public function getProviderInfo(): ProviderInfoInterface; /** - * @return null|string name of the provider + * @param array $providerTransports */ - public function getProviderName(): ?string; + public function setProviderTransports(array $providerTransports): self; - /** - * @param string $providerName Name of the provider - */ - public function setProviderName(string $providerName): self; + public function addProviderTransport(ProviderTransportInterface $providerTransport): self; /** - * @return null|string providers version + * @return array */ - public function getProviderVersion(): ?string; + public function getProviderTransports(): array; - /** - * @param string $providerVersion providers version - */ - public function setProviderVersion(string $providerVersion): self; + public function setFilterInfo(FilterInfoInterface $filterInfo): self; - /** - * @param string $providerBranch providers branch name - */ - public function setProviderBranch(string $providerBranch): self; - - /** - * @return array providers version tag - */ - public function getProviderVersionTag(): array; - - /** - * @return null|string providers branch name - */ - public function getProviderBranch(): ?string; - - /** - * @param string $providerVersionTag providers version tag - */ - public function setProviderVersionTag(string $providerVersionTag): self; - - /** - * @return array consumers version tag - */ - public function getConsumerVersionTag(): array; + public function getFilterInfo(): FilterInfoInterface; - /** - * @param string $consumerVersionTag consumers version tag - */ - public function addConsumerVersionTag(string $consumerVersionTag): self; + public function setProviderState(ProviderStateInterface $providerState): self; - /** - * @param string $providerVersionTag provider version tag - */ - public function addProviderVersionTag(string $providerVersionTag): self; + public function getProviderState(): ProviderStateInterface; - public function getConsumerVersionSelectors(): ConsumerVersionSelectors; + public function setPublishOptions(?PublishOptionsInterface $publishOptions): self; - /** - * @param ConsumerVersionSelectors $selectors Consumer version selectors - */ - public function setConsumerVersionSelectors(ConsumerVersionSelectors $selectors): self; + public function getPublishOptions(): ?PublishOptionsInterface; - /** - * @return bool are results going to be published - */ public function isPublishResults(): bool; - /** - * @param bool $publishResults flag to publish results - */ - public function setPublishResults(bool $publishResults): self; - - /** - * @return null|UriInterface url to the pact broker - */ - public function getBrokerUri(): ?UriInterface; - - /** - * @param UriInterface $brokerUri uri to the pact broker - */ - public function setBrokerUri(UriInterface $brokerUri): self; - - /** - * @return null|string token for the pact broker - */ - public function getBrokerToken(): ?string; - - /** - * @param null|string $brokerToken token for the pact broker - */ - public function setBrokerToken(?string $brokerToken): self; - - /** - * @return null|string username for the pact broker if secured - */ - public function getBrokerUsername(): ?string; - - /** - * @param string $brokerUsername username for the pact broker if secured - */ - public function setBrokerUsername(string $brokerUsername): self; - - /** - * @return null|string password for the pact broker if secured - */ - public function getBrokerPassword(): ?string; - - /** - * @param string $brokerPassword password for the pact broker if secured - */ - public function setBrokerPassword(string $brokerPassword): self; - - /** - * @return array custom headers for the request to the provider such as authorization - */ - public function getCustomProviderHeaders(): array; - - /** - * @param array $customProviderHeaders custom headers for the requests to the provider such as authorization - */ - public function setCustomProviderHeaders(array $customProviderHeaders): self; - - public function addCustomProviderHeader(string $name, string $value): self; - - /** - * @return bool is verbosity level increased - */ - public function isVerbose(): bool; - - /** - * @param bool $verbose increase verbosity level - */ - public function setVerbose(bool $verbose): self; - - /** - * @return null|string set the directory for the pact.log file - */ - public function getLogDirectory(): ?string; - - /** - * @param string $log set the directory for the pact.log file - */ - public function setLogDirectory(string $log): self; + public function setConsumerFilters(ConsumerFiltersInterface $consumerFilters): self; - /** - * @return null|string RSpec formatter. Defaults to custom Pact formatter. json and RspecJunitFormatter may also be used - */ - public function getFormat(): ?string; + public function getConsumerFilters(): ConsumerFiltersInterface; - /** - * @param string $format RSpec formatter. Defaults to custom Pact formatter. json and RspecJunitFormatter may also be used - */ - public function setFormat(string $format): self; - - public function setProcessTimeout(int $timeout): self; + public function setVerificationOptions(VerificationOptionsInterface $verificationOptions): self; - public function setProcessIdleTimeout(int $timeout): self; + public function getVerificationOptions(): VerificationOptionsInterface; - public function getProcessTimeout(): int; + public function getLogLevel(): ?string; - public function getProcessIdleTimeout(): int; + public function setLogLevel(string $logLevel): self; - /** - * @param bool $pending allow pacts which are in pending state to be verified without causing the overall task to fail - */ - public function setEnablePending(bool $pending): self; + public function getPluginDir(): ?string; - /** - * @return bool is enabled pending pacts - */ - public function isEnablePending(): bool; - - /** - * @param string $date Includes pact marked as WIP since this date. - * Accepted formats: Y-m-d (2020-01-30) or c (ISO 8601 date 2004-02-12T15:19:21+00:00) - */ - public function setIncludeWipPactSince(string $date): self; - - /** - * @return null|string get start date of included WIP Pacts - */ - public function getIncludeWipPactSince(); - - /** - * @return null|callable - */ - public function getRequestFilter(): ?callable; - - /** - * @param callable $requestFilter - */ - public function setRequestFilter(callable $requestFilter): self; + public function setPluginDir(?string $pluginDir): self; } diff --git a/src/PhpPact/Standalone/ProviderVerifier/ProcessRunnerFactory.php b/src/PhpPact/Standalone/ProviderVerifier/ProcessRunnerFactory.php deleted file mode 100644 index 257e44a6c..000000000 --- a/src/PhpPact/Standalone/ProviderVerifier/ProcessRunnerFactory.php +++ /dev/null @@ -1,30 +0,0 @@ -providerVerifier = $providerVerifier ?: Scripts::getProviderVerifier(); - } - - /** - * @param array $arguments - */ - public function createRunner(array $arguments, LoggerInterface $logger = null): ProcessRunner - { - $processRunner = new ProcessRunner($this->providerVerifier, $arguments); - if ($logger) { - $processRunner->setLogger($logger); - } - - return $processRunner; - } -} diff --git a/src/PhpPact/Standalone/ProviderVerifier/Verifier.php b/src/PhpPact/Standalone/ProviderVerifier/Verifier.php index 2bc678b3c..ba36ae4d9 100644 --- a/src/PhpPact/Standalone/ProviderVerifier/Verifier.php +++ b/src/PhpPact/Standalone/ProviderVerifier/Verifier.php @@ -2,264 +2,222 @@ namespace PhpPact\Standalone\ProviderVerifier; -use GuzzleHttp\HandlerStack; -use GuzzleHttp\Middleware; -use PhpPact\Broker\Service\BrokerHttpClient; -use PhpPact\Broker\Service\BrokerHttpClientInterface; -use PhpPact\Http\GuzzleClient; +use FFI\CData; +use PhpPact\Consumer\Service\FFI; +use PhpPact\Standalone\ProviderVerifier\Model\ArrayData; +use PhpPact\Standalone\ProviderVerifier\Model\Source\BrokerInterface; +use PhpPact\Standalone\ProviderVerifier\Model\Source\UrlInterface; use PhpPact\Standalone\ProviderVerifier\Model\VerifierConfigInterface; -/** - * Wrapper for the Ruby Standalone Verifier service. - */ class Verifier { - protected int $processTimeout = 60; + protected FFI $ffi; + protected CData $handle; - protected int $processIdleTimeout = 10; - - protected VerifierConfigInterface $config; - - protected ?BrokerHttpClientInterface $brokerHttpClient = null; - - protected ?VerifierProcess $verifierProcess = null; - - public function __construct( - VerifierConfigInterface $config, - VerifierProcess $verifierProcess = null, - BrokerHttpClient $brokerHttpClient = null - ) { - $this->config = $config; - $this->verifierProcess = $verifierProcess ?: new VerifierProcess(); - $this->processTimeout = $config->getProcessTimeout(); - $this->processIdleTimeout = $config->getProcessIdleTimeout(); - - if ($brokerHttpClient) { - $this->brokerHttpClient = $brokerHttpClient; - } + public function __construct(VerifierConfigInterface $config) + { + $this->ffi = new FFI(); + $this + ->newHandle($config) + ->setProviderInfo($config) + ->setProviderTransports($config) + ->setFilterInfo($config) + ->setProviderState($config) + ->setVerificationOptions($config) + ->setPublishOptions($config) + ->setConsumerFilters($config) + ->setLogLevel($config) + ->setPluginDir($config); } - /** - * @throws \Exception - * - * @return array parameters to be passed into the process - */ - public function getArguments(): array + private function newHandle(VerifierConfigInterface $config): self { - $parameters = []; - - if ($this->config->getProviderName() !== null) { - $parameters[] = "--provider='{$this->config->getProviderName()}'"; - } - - if ($this->config->getProviderBaseUrl() !== null) { - $parameters[] = "--provider-base-url={$this->config->getProviderBaseUrl()}"; - } - - if ($this->config->getProviderVersion() !== null) { - $parameters[] = "--provider-app-version={$this->config->getProviderVersion()}"; - } - - if ($this->config->getProviderBranch() !== null) { - $parameters[] = "--provider-version-branch={$this->config->getProviderBranch()}"; - } - - if (\count($this->config->getConsumerVersionTag()) > 0) { - foreach ($this->config->getConsumerVersionTag() as $tag) { - $parameters[] = "--consumer-version-tag={$tag}"; - } - } + $this->handle = $this->ffi->call( + 'pactffi_verifier_new_for_application', + $config->getCallingApp()->getName(), + $config->getCallingApp()->getVersion() + ); - if (\count($this->config->getConsumerVersionSelectors()) > 0) { - foreach ($this->config->getConsumerVersionSelectors() as $selector) { - $parameters[] = "--consumer-version-selector='{$selector}'"; - } - } + return $this; + } - if (\count($this->config->getProviderVersionTag()) > 0) { - foreach ($this->config->getProviderVersionTag() as $tag) { - $parameters[] = "--provider-version-tag={$tag}"; - } - } + private function setProviderInfo(VerifierConfigInterface $config): self + { + $this->ffi->call( + 'pactffi_verifier_set_provider_info', + $this->handle, + $config->getProviderInfo()->getName(), + $config->getProviderInfo()->getScheme(), + $config->getProviderInfo()->getHost(), + $config->getProviderInfo()->getPort(), + $config->getProviderInfo()->getPath() + ); - if ($this->config->getProviderStatesSetupUrl() !== null) { - $parameters[] = "--provider-states-setup-url={$this->config->getProviderStatesSetupUrl()}"; - } + return $this; + } - if ($this->config->isPublishResults() === true) { - $parameters[] = '--publish-verification-results'; + private function setProviderTransports(VerifierConfigInterface $config): self + { + foreach ($config->getProviderTransports() as $transport) { + $this->ffi->call( + 'pactffi_verifier_add_provider_transport', + $this->handle, + $transport->getProtocol(), + $transport->getPort(), + $transport->getPath(), + $transport->getScheme() + ); } - if ($this->config->getBrokerToken() !== null) { - $parameters[] = "--broker-token={$this->config->getBrokerToken()}"; - } + return $this; + } - if ($this->config->getBrokerUsername() !== null) { - $parameters[] = "--broker-username={$this->config->getBrokerUsername()}"; - } + private function setFilterInfo(VerifierConfigInterface $config): self + { + $this->ffi->call( + 'pactffi_verifier_set_provider_state', + $this->handle, + $config->getProviderState()->getStateChangeUrl() ? (string) $config->getProviderState()->getStateChangeUrl() : null, + $config->getProviderState()->isStateChangeTeardown(), + $config->getProviderState()->isStateChangeAsBody() + ); - if ($this->config->getBrokerPassword() !== null) { - $parameters[] = "--broker-password={$this->config->getBrokerPassword()}"; - } + return $this; + } - if (count($this->config->getCustomProviderHeaders()) > 0) { - foreach ($this->config->getCustomProviderHeaders() as $customProviderHeader) { - $parameters[] = "--custom-provider-header=\"{$customProviderHeader}\""; - } - } + private function setProviderState(VerifierConfigInterface $config): self + { + $this->ffi->call( + 'pactffi_verifier_set_filter_info', + $this->handle, + $config->getFilterInfo()->getFilterDescription(), + $config->getFilterInfo()->getFilterState(), + $config->getFilterInfo()->getFilterNoState() + ); - if ($this->config->isVerbose() === true) { - $parameters[] = '--verbose=VERBOSE'; - } + return $this; + } - if ($this->config->getLogDirectory() !== null) { - $parameters[] = "--log-dir={$this->config->getLogDirectory()}"; - } + private function setVerificationOptions(VerifierConfigInterface $config): self + { + $this->ffi->call( + 'pactffi_verifier_set_verification_options', + $this->handle, + $config->getVerificationOptions()->isDisableSslVerification(), + $config->getVerificationOptions()->getRequestTimeout() + ); - if ($this->config->getFormat() !== null) { - $parameters[] = "--format={$this->config->getFormat()}"; - } + return $this; + } - if ($this->config->isEnablePending() === true) { - $parameters[] = '--enable-pending'; + private function setPublishOptions(VerifierConfigInterface $config): self + { + if ($config->isPublishResults()) { + $providerTags = ArrayData::createFrom($config->getPublishOptions()->getProviderTags()); + $this->ffi->call( + 'pactffi_verifier_set_publish_options', + $this->handle, + $config->getPublishOptions()->getProviderVersion(), + $config->getPublishOptions()->getBuildUrl(), + $providerTags?->getItems(), + $providerTags?->getSize(), + $config->getPublishOptions()->getProviderBranch() + ); } - if ($this->config->getIncludeWipPactSince() !== null) { - $parameters[] = "--include-wip-pacts-since={$this->config->getIncludeWipPactSince()}"; - } + return $this; + } - if ($this->config->getBrokerUri() !== null) { - $parameters[] = "--pact-broker-base-url={$this->config->getBrokerUri()->__toString()}"; - } + private function setConsumerFilters(VerifierConfigInterface $config): self + { + $filterConsumerNames = ArrayData::createFrom($config->getConsumerFilters()->getFilterConsumerNames()); + $this->ffi->call( + 'pactffi_verifier_set_consumer_filters', + $this->handle, + $filterConsumerNames?->getItems(), + $filterConsumerNames?->getSize() + ); - return $parameters; + return $this; } - /** - * Make the request to the PACT Verifier Service to run a Pact file tests from the Pact Broker. - * - * @param string $consumerName name of the consumer to be compared against - * @param null|string $tag optional tag of the consumer such as a branch name - * @param null|string $consumerVersion optional specific version of the consumer; this is overridden by tag - * @throws \Exception - */ - public function verify(string $consumerName, string $tag = null, string $consumerVersion = null): self + private function setLogLevel(VerifierConfigInterface $config): self { - $path = "/pacts/provider/{$this->config->getProviderName()}/consumer/{$consumerName}/"; - - if ($tag) { - $path .= "latest/{$tag}/"; - } elseif ($consumerVersion) { - $path .= "version/{$consumerVersion}/"; - } else { - $path .= 'latest/'; + if ($logLevel = $config->getLogLevel()) { + $this->ffi->call('pactffi_init_with_log_level', $logLevel); } - $uri = $this->config->getBrokerUri()->withPath($path); - - $arguments = \array_merge([$uri->__toString()], $this->getArguments()); - - $this->verifyAction($arguments); - return $this; } - /** - * Provides a way to validate local Pact JSON files. - * - * @param array $files paths to pact json files - * @throws \Exception - */ - public function verifyFiles(array $files): self + private function setPluginDir(VerifierConfigInterface $config): self { - $arguments = \array_merge($files, $this->getArguments()); - - $this->verifyAction($arguments); + if ($pluginDir = $config->getPluginDir()) { + \putenv("PACT_PLUGIN_DIR={$pluginDir}"); + } return $this; } - /** - * Verify all Pacts from the Pact Broker are valid for the Provider. - * @throws \Exception - */ - public function verifyAll(): void + public function addFile(string $file): self { - $arguments = $this->getBrokerHttpClient()->getAllConsumerUrls($this->config->getProviderName()); + $this->ffi->call('pactffi_verifier_add_file_source', $this->handle, $file); - $arguments = \array_merge($arguments, $this->getArguments()); - - $this->verifyAction($arguments); + return $this; } - /** - * Verify all PACTs for a given tag. - * @throws \Exception - */ - public function verifyAllForTag(string $tag): void + public function addDirectory(string $directory): self { - $arguments = $this->getBrokerHttpClient()->getAllConsumerUrlsForTag($this->config->getProviderName(), $tag); + $this->ffi->call('pactffi_verifier_add_directory_source', $this->handle, $directory); - $arguments = \array_merge($arguments, $this->getArguments()); - - $this->verifyAction($arguments); + return $this; } - /** - * Verify all PACTs that match the VerifierConfig - * @throws \Exception - */ - public function verifyFromConfig(): void + public function addUrl(UrlInterface $url): self { - $this->verifyAction($this->getArguments()); - } + $this->ffi->call( + 'pactffi_verifier_url_source', + $this->handle, + (string) $url->getUrl(), + $url->getUsername(), + $url->getPassword(), + $url->getToken() + ); - /** - * @return array - */ - public function getTimeoutValues(): array - { - return ['process_timeout' => $this->processTimeout, 'process_idle_timeout' => $this->processIdleTimeout]; + return $this; } - /** - * Trigger execution of the Pact Verifier Service. - * - * @param array $arguments - * @throws \Exception - */ - protected function verifyAction(array $arguments): void + public function addBroker(BrokerInterface $broker): self { - $this->verifierProcess->run($arguments, $this->processTimeout, $this->processIdleTimeout); + $providerTags = ArrayData::createFrom($broker->getProviderTags()); + $consumerVersionSelectors = ArrayData::createFrom(iterator_to_array($broker->getConsumerVersionSelectors())); + $consumerVersionTags = ArrayData::createFrom($broker->getConsumerVersionTags()); + $this->ffi->call( + 'pactffi_verifier_broker_source_with_selectors', + $this->handle, + (string) $broker->getUrl(), + $broker->getUsername(), + $broker->getPassword(), + $broker->getToken(), + $broker->isEnablePending(), + $broker->getIncludeWipPactSince(), + $providerTags?->getItems(), + $providerTags?->getSize(), + $broker->getProviderBranch(), + $consumerVersionSelectors?->getItems(), + $consumerVersionSelectors?->getSize(), + $consumerVersionTags?->getItems(), + $consumerVersionTags?->getSize() + ); + + return $this; } - protected function getBrokerHttpClient(): BrokerHttpClientInterface + public function verify(): bool { - if (!$this->brokerHttpClient) { - $user = $this->config->getBrokerUsername(); - $password = $this->config->getBrokerPassword(); - $token = $this->config->getBrokerToken(); - $reqFilter = $this->config->getRequestFilter(); - - $config = []; - if (\strlen($token) > 0) { - $config = ['headers' => ['Authorization' => 'Bearer ' . $token]]; - } elseif ($user && $password) { - $config = ['auth' => [$user, $password]]; - } - if (\is_callable($reqFilter)) { - $stack = HandlerStack::create(); - $stack->push(Middleware::mapRequest($reqFilter), 'requestFilter'); - $config['handler'] = $stack; - } - if (($sslVerify = \getenv('PACT_BROKER_SSL_VERIFY'))) { - $client['verify'] = $sslVerify !== 'no'; - } - $client = new GuzzleClient($config); - - $this->brokerHttpClient = new BrokerHttpClient($client, $this->config->getBrokerUri()); - } + $error = $this->ffi->call('pactffi_verifier_execute', $this->handle); + $this->ffi->call('pactffi_verifier_shutdown', $this->handle); - return $this->brokerHttpClient; + return !$error; } } diff --git a/src/PhpPact/Standalone/ProviderVerifier/VerifierProcess.php b/src/PhpPact/Standalone/ProviderVerifier/VerifierProcess.php deleted file mode 100644 index 6201c53f8..000000000 --- a/src/PhpPact/Standalone/ProviderVerifier/VerifierProcess.php +++ /dev/null @@ -1,57 +0,0 @@ -processRunnerFactory = $processRunnerFactory ?: new ProcessRunnerFactory(); - } - - public function setLogger(LoggerInterface $logger): self - { - $this->logger = $logger; - - return $this; - } - - /** - * @param array $arguments - * @throws \Exception - */ - public function run(array $arguments, ?int $processTimeout = null, ?int $processIdleTimeout = null): void - { - $logger = $this->getLogger(); - $processRunner = $this->processRunnerFactory->createRunner( - $arguments, - $logger - ); - - $logger->info("Verifying PACT with script:\n{$processRunner->getCommand()}\n\n"); - - $processRunner->runBlocking(); - } - - private function getLogger(): LoggerInterface - { - if (null === $this->logger) { - $logHandler = new StreamHandler(new ResourceOutputStream(\STDOUT)); - $logHandler->setFormatter(new ConsoleFormatter(null, null, true)); - $this->logger = new Logger('console'); - $this->logger->pushHandler($logHandler); - } - - return $this->logger; - } -} diff --git a/tests/PhpPact/Broker/Service/BrokerHttpClientTest.php b/tests/PhpPact/Broker/Service/BrokerHttpClientTest.php deleted file mode 100644 index 7c510e794..000000000 --- a/tests/PhpPact/Broker/Service/BrokerHttpClientTest.php +++ /dev/null @@ -1,53 +0,0 @@ - [ - 'pacts' => [ - ['href' => 'pact-url-1'], - ['href' => 'pact-url-2'], - ], - ], - ] - ); - - $streamMock = $this->createMock(StreamInterface::class); - $streamMock->expects($this->once()) - ->method('getContents') - ->will($this->returnValue($expectedContents)); - - $responseMock = $this->createMock(ResponseInterface::class); - $responseMock->expects($this->once()) - ->method('getBody') - ->will($this->returnValue($streamMock)); - - $httpClientMock = $this->createMock(ClientInterface::class); - $httpClientMock->expects($this->once()) - ->method('get') - ->will($this->returnValue($responseMock)); - - $uriMock = $this->createMock(UriInterface::class); - $uriMock->expects($this->once()) - ->method('withPath') - ->with($this->equalTo($expectedPath)) - ->will($this->returnValue($uriMock)); - - $broker = new BrokerHttpClient($httpClientMock, $uriMock); - $broker->getAllConsumerUrls($provider); - } -} diff --git a/tests/PhpPact/Standalone/ProviderVerifier/Model/ArrayDataTest.php b/tests/PhpPact/Standalone/ProviderVerifier/Model/ArrayDataTest.php new file mode 100644 index 000000000..734bade3b --- /dev/null +++ b/tests/PhpPact/Standalone/ProviderVerifier/Model/ArrayDataTest.php @@ -0,0 +1,21 @@ +assertSame(count($branches), $arrayData->getSize()); + foreach ($branches as $index => $branch) { + $this->assertSame($branch, FFI::string($arrayData->getItems()[$index])); + } + } +} diff --git a/tests/PhpPact/Standalone/ProviderVerifier/Model/Source/BrokerTest.php b/tests/PhpPact/Standalone/ProviderVerifier/Model/Source/BrokerTest.php new file mode 100644 index 000000000..23106df10 --- /dev/null +++ b/tests/PhpPact/Standalone/ProviderVerifier/Model/Source/BrokerTest.php @@ -0,0 +1,37 @@ +addSelector('{"tag":"foo","latest":true}') + ->addSelector('{"tag":"bar","latest":true}'); + $consumerVersionTags = ['dev']; + + $subject = (new Broker()) + ->setEnablePending($enablePending) + ->setIncludeWipPactSince($wipPactSince) + ->setProviderTags($providerTags) + ->setProviderBranch($providerBranch) + ->setConsumerVersionSelectors($consumerVersionSelectors) + ->setConsumerVersionTags($consumerVersionTags); + + static::assertSame($enablePending, $subject->isEnablePending()); + static::assertSame($wipPactSince, $subject->getIncludeWipPactSince()); + static::assertSame($providerTags, $subject->getProviderTags()); + static::assertSame($providerBranch, $subject->getProviderBranch()); + static::assertSame($consumerVersionSelectors, $subject->getConsumerVersionSelectors()); + static::assertSame($consumerVersionTags, $subject->getConsumerVersionTags()); + } +} diff --git a/tests/PhpPact/Standalone/ProviderVerifier/Model/Source/UrlTest.php b/tests/PhpPact/Standalone/ProviderVerifier/Model/Source/UrlTest.php new file mode 100644 index 000000000..20716b8a7 --- /dev/null +++ b/tests/PhpPact/Standalone/ProviderVerifier/Model/Source/UrlTest.php @@ -0,0 +1,29 @@ +setUrl($url) + ->setToken($token) + ->setUsername($username) + ->setPassword($password); + + static::assertSame($url, $subject->getUrl()); + static::assertSame($token, $subject->getToken()); + static::assertSame($username, $subject->getUsername()); + static::assertSame($password, $subject->getPassword()); + } +} diff --git a/tests/PhpPact/Standalone/ProviderVerifier/Model/VerifierConfigTest.php b/tests/PhpPact/Standalone/ProviderVerifier/Model/VerifierConfigTest.php new file mode 100644 index 000000000..48446b0a0 --- /dev/null +++ b/tests/PhpPact/Standalone/ProviderVerifier/Model/VerifierConfigTest.php @@ -0,0 +1,88 @@ +getProviderInfo() + ->setName($providerName) + ->setScheme($scheme) + ->setHost($host) + ->setPort($port) + ->setPath($basePath); + $subject->getFilterInfo() + ->setFilterDescription($filterDescription) + ->setFilterNoState($filterNoState) + ->setFilterState($filterState); + $subject->getProviderState() + ->setStateChangeUrl($stateChangeUrl) + ->setStateChangeAsBody($stateChangeAsBody) + ->setStateChangeTeardown($stateChangeTeardown); + $subject->getVerificationOptions() + ->setRequestTimeout($requestTimeout) + ->setDisableSslVerification($disableSslVerification); + $publishOptions = new PublishOptions(); + $publishOptions + ->setProviderTags($providerTags) + ->setProviderVersion($providerVersion) + ->setBuildUrl($buildUrl) + ->setProviderBranch($providerBranch); + $subject->setPublishOptions($publishOptions); + $subject->getConsumerFilters() + ->setFilterConsumerNames($filterConsumerNames); + + $providerInfo = $subject->getProviderInfo(); + static::assertSame($providerName, $providerInfo->getName()); + static::assertSame($scheme, $providerInfo->getScheme()); + static::assertSame($host, $providerInfo->getHost()); + static::assertSame($port, $providerInfo->getPort()); + static::assertSame($basePath, $providerInfo->getPath()); + $filterInfo = $subject->getFilterInfo(); + static::assertSame($filterDescription, $filterInfo->getFilterDescription()); + static::assertSame($filterNoState, $filterInfo->getFilterNoState()); + static::assertSame($filterState, $filterInfo->getFilterState()); + $providerState = $subject->getProviderState(); + static::assertSame($stateChangeUrl, $providerState->getStateChangeUrl()); + static::assertSame($stateChangeAsBody, $providerState->isStateChangeAsBody()); + static::assertSame($stateChangeTeardown, $providerState->isStateChangeTeardown()); + $verificationOptions = $subject->getVerificationOptions(); + static::assertSame($requestTimeout, $verificationOptions->getRequestTimeout()); + static::assertSame($disableSslVerification, $verificationOptions->isDisableSslVerification()); + static::assertSame($publishResults, $subject->isPublishResults()); + $publishOptions = $subject->getPublishOptions(); + static::assertSame($providerTags, $publishOptions->getProviderTags()); + static::assertSame($providerVersion, $publishOptions->getProviderVersion()); + static::assertSame($buildUrl, $publishOptions->getBuildUrl()); + static::assertSame($providerBranch, $publishOptions->getProviderBranch()); + $consumerFilters = $subject->getConsumerFilters(); + static::assertSame($filterConsumerNames, $consumerFilters->getFilterConsumerNames()); + } +} diff --git a/tests/PhpPact/Standalone/ProviderVerifier/VerifierProcessTest.php b/tests/PhpPact/Standalone/ProviderVerifier/VerifierProcessTest.php deleted file mode 100644 index 724499392..000000000 --- a/tests/PhpPact/Standalone/ProviderVerifier/VerifierProcessTest.php +++ /dev/null @@ -1,77 +0,0 @@ - 'bar']; - - $logger = $this->createMock(LoggerInterface::class); - - $processRunner = $this->createMock(ProcessRunner::class); - - $processRunnerFactory = $this->createMock(ProcessRunnerFactory::class); - $processRunnerFactory->expects($this->once()) - ->method('createRunner') - ->with($this->equalTo($arguments), $this->equalTo($logger)) - ->will($this->returnValue($processRunner)); - - $process = new VerifierProcess($processRunnerFactory); - $process->setLogger($logger); - $process->run($arguments, 42, 23); - } - - public function testRunWithDefaultLogger() - { - $arguments = ['foo' => 'bar']; - - $processRunner = $this->createMock(ProcessRunner::class); - - $processRunnerFactory = $this->createMock(ProcessRunnerFactory::class); - $processRunnerFactory->expects($this->once()) - ->method('createRunner') - ->with($this->equalTo($arguments)) - ->will($this->returnValue($processRunner)); - - $process = new VerifierProcess($processRunnerFactory); - $process->run($arguments, 42, 23); - } - - public function testRunForwardsException() - { - $this->expectExceptionMessage('foo'); - $this->expectException(\RuntimeException::class); - - $arguments = ['foo' => 'bar']; - - $expectedException = new \RuntimeException('foo'); - - $processRunner = $this->createMock(ProcessRunner::class); - $processRunner->expects($this->once()) - ->method('runBlocking') - ->will( - $this->returnCallback( - function () use ($expectedException) { - throw $expectedException; - } - ) - ); - - $processRunnerFactory = $this->createMock(ProcessRunnerFactory::class); - $processRunnerFactory->expects($this->once()) - ->method('createRunner') - ->with($this->equalTo($arguments)) - ->will($this->returnValue($processRunner)); - - $process = new VerifierProcess($processRunnerFactory); - $process->run($arguments, 42, 23); - } -} diff --git a/tests/PhpPact/Standalone/ProviderVerifier/VerifierTest.php b/tests/PhpPact/Standalone/ProviderVerifier/VerifierTest.php index 8a5d896ab..718748d67 100644 --- a/tests/PhpPact/Standalone/ProviderVerifier/VerifierTest.php +++ b/tests/PhpPact/Standalone/ProviderVerifier/VerifierTest.php @@ -2,235 +2,53 @@ namespace PhpPactTest\Standalone\ProviderVerifier; -use GuzzleHttp\Psr7\Uri; -use Monolog\Handler\TestHandler; -use Monolog\Logger; -use PhpPact\Broker\Service\BrokerHttpClient; -use PhpPact\Broker\Service\BrokerHttpClientInterface; -use PhpPact\Standalone\ProviderVerifier\Model\ConsumerVersionSelectors; use PhpPact\Standalone\ProviderVerifier\Model\VerifierConfig; -use PhpPact\Standalone\ProviderVerifier\ProcessRunnerFactory; use PhpPact\Standalone\ProviderVerifier\Verifier; -use PhpPact\Standalone\ProviderVerifier\VerifierProcess; +use PhpPact\Standalone\Runner\ProcessRunner; use PHPUnit\Framework\TestCase; -use Psr\Http\Message\RequestInterface; class VerifierTest extends TestCase { - public function testGetArguments() - { - $consumerVersionSelectors = (new ConsumerVersionSelectors()) - ->addSelector('{"tag":"foo","latest":true}') - ->addSelector('{"tag":"bar","latest":true}'); - - $config = new VerifierConfig(); - $config - ->setProviderName('some provider with whitespace') - ->setProviderVersion('1.0.0') - ->setProviderBranch('main') - ->addProviderVersionTag('prod') - ->addProviderVersionTag('dev') - ->addConsumerVersionTag('dev') - ->setProviderBaseUrl(new Uri('http://myprovider:1234')) - ->setProviderStatesSetupUrl(new Uri('http://someurl:1234')) - ->setPublishResults(true) - ->setBrokerToken('someToken') - ->setBrokerUsername('someusername') - ->setBrokerPassword('somepassword') - ->setBrokerUri(new Uri('https://example.broker/')) - ->addCustomProviderHeader('key1', 'value1') - ->addCustomProviderHeader('key2', 'value2') - ->setVerbose(true) - ->setLogDirectory('my/log/directory') - ->setFormat('someformat') - ->setProcessTimeout(30) - ->setProcessIdleTimeout(5) - ->setEnablePending(true) - ->setIncludeWipPactSince('2020-01-30') - ->setRequestFilter( - function (RequestInterface $r) { - return $r->withHeader('MY_SPECIAL_HEADER', 'my special value'); - } - ) - ->setConsumerVersionSelectors($consumerVersionSelectors); - - /** @var BrokerHttpClientInterface $brokerHttpService */ - $server = new Verifier($config); - $arguments = $server->getArguments(); - - $this->assertContains('--provider-base-url=http://myprovider:1234', $arguments); - $this->assertContains('--provider-states-setup-url=http://someurl:1234', $arguments); - $this->assertContains('--publish-verification-results', $arguments); - $this->assertContains('--broker-token=someToken', $arguments); - $this->assertContains('--broker-username=someusername', $arguments); - $this->assertContains('--broker-password=somepassword', $arguments); - $this->assertContains('--custom-provider-header="key1: value1"', $arguments); - $this->assertContains('--custom-provider-header="key2: value2"', $arguments); - $this->assertContains('--verbose=VERBOSE', $arguments); - $this->assertContains('--log-dir=my/log/directory', $arguments); - $this->assertContains('--format=someformat', $arguments); - $this->assertContains('--provider-version-tag=prod', $arguments); - $this->assertContains('--provider-version-tag=dev', $arguments); - $this->assertContains('--provider-version-branch=main', $arguments); - $this->assertContains('--consumer-version-tag=dev', $arguments); - $this->assertSame(['process_timeout' => 30, 'process_idle_timeout' => 5], $server->getTimeoutValues()); - $this->assertContains('--enable-pending', $arguments); - $this->assertContains('--include-wip-pacts-since=2020-01-30', $arguments); - $this->assertContains('--consumer-version-selector=\'{"tag":"foo","latest":true}\'', $this->stripSpaces($arguments)); - $this->assertContains('--consumer-version-selector=\'{"tag":"bar","latest":true}\'', $this->stripSpaces($arguments)); - $this->assertContains('--provider=\'some provider with whitespace\'', $arguments); - $this->assertContains('--pact-broker-base-url=https://example.broker/', $arguments); - } - - /** - * Strip spaces for Windows CMD - */ - private function stripSpaces($arr) - { - $newArr = []; - foreach ($arr as $str) { - $newArr[] = str_ireplace(' ', '', $str); - } - return $newArr; - } - - public function testGetArgumentsEmptyConfig() - { - $this->assertEmpty((new Verifier(new VerifierConfig()))->getArguments()); - } + /** @var ProcessRunner */ + private ProcessRunner $processRunner; /** - * @dataProvider dataProviderForBrokerPathTest - * - * @param string $consumerName - * @param string $providerName - * @param null|string $tag - * @param null|string $version - * @param string $path + * Run the PHP build-in web server. */ - public function testBuildValidPathToPactBroker($consumerName, $providerName, $tag, $version, $path) + protected function setUp(): void { - $expectedUrltoBroker = 'http://mock/' . $path; - - /** @var Uri $uriMock */ - $uriMock = $this->createMock(Uri::class); - $uriMock->expects($this->once()) - ->method('withPath') - ->with($path) - ->willReturn($uriMock); - - $uriMock->expects($this->any()) - ->method('__toString') - ->willReturn($expectedUrltoBroker); - - $verifierProcessMock = $this->createMock(VerifierProcess::class); - $verifierProcessMock->expects($this->once()) - ->method('run') - ->with( - $this->callback(function ($args) use ($expectedUrltoBroker) { - return \in_array($expectedUrltoBroker, $args); - }) - ); - - $config = new VerifierConfig(); - $config->setProviderName($providerName) - ->setProviderBaseUrl(new Uri('http://myprovider:1234')) - ->setProviderStatesSetupUrl(new Uri('http://someurl:1234')) - ->setBrokerUri($uriMock) - ->setVerbose(true); + $publicPath = __DIR__ . '/../../../_public/'; - $verifier = new Verifier($config, $verifierProcessMock); + $this->processRunner = new ProcessRunner('php', ['-S', 'localhost:7202', '-t', $publicPath]); - $verifier->verify($consumerName, $tag, $version); - } - - public function dataProviderForBrokerPathTest() - { - $consumerName = 'someProviderName'; - $providerName = 'someProviderName'; - $tag = '1.0.0'; - $version = '11111'; - - return [ - [$consumerName, $providerName, null, $version, "/pacts/provider/$providerName/consumer/$consumerName/version/$version/"], - [$consumerName, $providerName, $tag, null, "/pacts/provider/$providerName/consumer/$consumerName/latest/$tag/"], - [$consumerName, $providerName, $tag, $version, "/pacts/provider/$providerName/consumer/$consumerName/latest/$tag/"], - [$consumerName, $providerName, null, null, "/pacts/provider/$providerName/consumer/$consumerName/latest/"], - ]; + $this->processRunner->run(); + \sleep(1); // wait for server to start } /** - * @dataProvider provideDataForVerifyAll - * - * @param string $providerName - * @param string $providerVersion - * @param bool $forceLatest - * @param mixed $expectedProviderVersion + * Stop the web server process once complete. */ - public function testIfDataForVerifyAllIsConvertedCorrectly($providerName, $providerVersion) + protected function tearDown(): void { - $expectedUrl1 = 'expectedUrl1'; - $expectedUrl2 = 'expectedUrl2'; - $expectedPactUrls = [$expectedUrl1, $expectedUrl2]; - - $verifierProcessMock = $this->createMock(VerifierProcess::class); - $verifierProcessMock->expects($this->once()) - ->method('run') - ->with( - $this->callback(function ($args) use ($expectedUrl1, $expectedUrl2) { - return \in_array($expectedUrl1, $args) && \in_array($expectedUrl2, $args); - }) - ); - - $brokerHttpClient = $this->createMock(BrokerHttpClient::class); - - $brokerHttpClient->expects($this->once()) - ->method('getAllConsumerUrls') - ->with($this->equalTo($providerName)) - ->willReturn($expectedPactUrls); - - $config = new VerifierConfig(); - $config->setProviderName($providerName); - $config->setProviderVersion($providerVersion); - - $verifier = new Verifier($config, $verifierProcessMock, $brokerHttpClient); - $verifier->verifyAll(); + $this->processRunner->stop(); } - public function provideDataForVerifyAll() + public function testVerify(): void { - return [ - ['someProvider', '1.0.0'], - ['someProvider', '1.2.3'], - ]; - } - - public function testRunShouldLogOutputIfCmdFails() - { - if ('\\' !== \DIRECTORY_SEPARATOR) { - $cmd = __DIR__ . \DIRECTORY_SEPARATOR . 'verifier.sh'; - } else { - $cmd = 'cmd /c' . __DIR__ . \DIRECTORY_SEPARATOR . 'verifier.bat'; - } - - $process = new VerifierProcess(new ProcessRunnerFactory($cmd)); - - $logger = new Logger('console', [$handler = new TestHandler()]); - $process->setLogger($logger); - - try { - $exception = null; - $process->run([], 60, 10); - } catch (\Exception $e) { - $exception = $e; + $config = new VerifierConfig(); + $config->getProviderInfo() + ->setName('someProvider') + ->setHost('localhost') + ->setPort(7202) + ->setScheme('http') + ->setPath('/'); + if ($level = \getenv('PACT_LOGLEVEL')) { + $config->setLogLevel($level); } - $logMessages = $handler->getRecords(); - - $this->assertGreaterThan(2, \count($logMessages)); - $this->assertStringContainsString('first line', $logMessages[\count($logMessages) - 2]['message']); - $this->assertStringContainsString('second line', $logMessages[\count($logMessages) - 1]['message']); + $verifier = new Verifier($config); + $verifier->addDirectory(__DIR__ . '/../../../_resources'); - $this->assertNotNull($exception); + $this->assertTrue($verifier->verify()); } } diff --git a/tests/PhpPact/Standalone/ProviderVerifier/verifier.bat b/tests/PhpPact/Standalone/ProviderVerifier/verifier.bat deleted file mode 100755 index 4cdede33b..000000000 --- a/tests/PhpPact/Standalone/ProviderVerifier/verifier.bat +++ /dev/null @@ -1,8 +0,0 @@ -@ECHO OFF - -REM this script simulates a command (like pact-verifier) which prints several lines to stdout and stderr - -ECHO "first line" -ECHO "second line" 1>&2 - -exit 42 \ No newline at end of file diff --git a/tests/PhpPact/Standalone/ProviderVerifier/verifier.sh b/tests/PhpPact/Standalone/ProviderVerifier/verifier.sh deleted file mode 100755 index c196300aa..000000000 --- a/tests/PhpPact/Standalone/ProviderVerifier/verifier.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env bash - -# this script simulates a command (like pact-verifier) which prints several lines to stdout and stderr - -echoerr() { echo "$@" 1>&2; } - -echo "first line" -echoerr "second line" - -exit 42 \ No newline at end of file diff --git a/tests/_public/index.php b/tests/_public/index.php new file mode 100644 index 000000000..cc71ddccc --- /dev/null +++ b/tests/_public/index.php @@ -0,0 +1,10 @@ + [ + [ + 'name' => 'g', + ], + ], +]);