Skip to content

Commit

Permalink
Merge pull request pact-foundation#659 from tienvx/wrap-ffi-call-mock…
Browse files Browse the repository at this point in the history
…-server-methods

refactor: Wrap ffi call > setup mock server methods
  • Loading branch information
tienvx authored Sep 27, 2024
2 parents 42d6aa8 + c86c937 commit 9e3c94d
Show file tree
Hide file tree
Showing 6 changed files with 190 additions and 45 deletions.
79 changes: 79 additions & 0 deletions helper/FFI/ClientTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
use PhpPact\Consumer\Driver\Exception\InteractionPendingNotSetException;
use PhpPact\Consumer\Driver\Exception\PactFileNotWrittenException;
use PhpPact\Consumer\Driver\Exception\PactNotModifiedException;
use PhpPact\Consumer\Exception\MockServerNotStartedException;
use PhpPact\Consumer\Exception\MockServerPactFileNotWrittenException;
use PhpPact\FFI\ClientInterface;
use PhpPact\Plugin\Exception\PluginNotLoadedException;
use PHPUnit\Framework\Constraint\Constraint;
Expand Down Expand Up @@ -350,4 +352,81 @@ protected function expectsUsingPlugin(int $pact, string $name, ?string $version,
});
}
}

protected function expectsCleanupMockServer(int $port, bool $result): void
{
$this->client
->expects($this->once())
->method('cleanupMockServer')
->with($port)
->willReturn($result);
}

protected function expectsMockServerMatched(int $port, bool $result): void
{
$this->client
->expects($this->once())
->method('mockServerMatched')
->with($port)
->willReturn($result);
}

protected function expectsMockServerMismatches(int $port, string $result, bool $matched): void
{
if (!$matched) {
$this->client
->expects($this->once())
->method('mockServerMismatches')
->with($port)
->willReturn($result);
} else {
$this->client
->expects($this->never())
->method('mockServerMismatches');
}
}

protected function expectsWritePactFile(int $port, string $directory, bool $overwrite, int $result, bool $matched): void
{
if ($matched) {
$this->client
->expects($this->once())
->method('writePactFile')
->with($port, $directory, $overwrite)
->willReturn($result);
if ($result) {
$this->expectException(MockServerPactFileNotWrittenException::class);
$this->expectExceptionMessage(match ($result) {
1 => 'A general panic was caught',
2 => 'The pact file was not able to be written',
3 => 'A mock server with the provided port was not found',
default => 'Unknown error',
});
}
} else {
$this->client
->expects($this->never())
->method('writePactFile');
}
}

protected function expectsCreateMockServerForTransport(int $pact, string $host, int $port, string $transport, ?string $transportConfig, int $result): void
{
$this->client
->expects($this->once())
->method('createMockServerForTransport')
->with($pact, $host, $port, $transport, $transportConfig)
->willReturn($result);
if ($result < 0) {
$this->expectException(MockServerNotStartedException::class);
$this->expectExceptionMessage(match ($result) {
-1 => 'An invalid handle was received. Handles should be created with `pactffi_new_pact`',
-2 => 'Transport_config is not valid JSON',
-3 => 'The mock server could not be started',
-4 => 'The method panicked',
-5 => 'The address is not valid',
default => 'Unknown error',
});
}
}
}
17 changes: 8 additions & 9 deletions src/PhpPact/Consumer/Service/MockServer.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@ public function __construct(

public function start(): void
{
$port = $this->client->call(
'pactffi_create_mock_server_for_transport',
$port = $this->client->createMockServerForTransport(
$this->pactDriver->getPact()->handle,
$this->config->getHost(),
$this->config->getPort(),
Expand Down Expand Up @@ -66,8 +65,7 @@ protected function getTransportConfig(): ?string

public function writePact(): void
{
$error = $this->client->call(
'pactffi_write_pact_file',
$error = $this->client->writePactFile(
$this->config->getPort(),
$this->config->getPactDir(),
$this->config->getPactFileWriteMode() === PactConfigInterface::MODE_OVERWRITE
Expand All @@ -79,19 +77,20 @@ public function writePact(): void

public function cleanUp(): void
{
$this->client->call('pactffi_cleanup_mock_server', $this->config->getPort());
$success = $this->client->cleanupMockServer($this->config->getPort());
if (!$success) {
trigger_error(sprintf("Can not clean up mock server: Mock server with the given port number '%s' does not exist, or the function panics", $this->config->getPort()), E_USER_WARNING);
}
$this->pactDriver->cleanUp();
}

private function isMatched(): bool
{
return $this->client->call('pactffi_mock_server_matched', $this->config->getPort());
return $this->client->mockServerMatched($this->config->getPort());
}

private function getMismatches(): string
{
$cData = $this->client->call('pactffi_mock_server_mismatches', $this->config->getPort());

return FFI::string($cData);
return $this->client->mockServerMismatches($this->config->getPort());
}
}
53 changes: 53 additions & 0 deletions src/PhpPact/FFI/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,59 @@ public function usingPlugin(int $pact, string $name, ?string $version): int
return $result;
}

public function cleanupMockServer(int $port): bool
{
$method = 'pactffi_cleanup_mock_server';
$result = $this->call($method, $port);
if (!is_bool($result)) {
throw new InvalidResultException(sprintf('Invalid result of "%s". Expected "boolean", but got "%s"', $method, get_debug_type($result)));
}
return $result;
}

public function mockServerMatched(int $port): bool
{
$method = 'pactffi_mock_server_matched';
$result = $this->call($method, $port);
if (!is_bool($result)) {
throw new InvalidResultException(sprintf('Invalid result of "%s". Expected "boolean", but got "%s"', $method, get_debug_type($result)));
}
return $result;
}

public function mockServerMismatches(int $port): string
{
$method = 'pactffi_mock_server_mismatches';
$result = $this->call($method, $port);
if ($result === null) {
return '';
}
if (!$result instanceof CData) {
throw new InvalidResultException(sprintf('Invalid result of "%s". Expected "%s", but got "%s"', $method, CData::class, get_debug_type($result)));
}
return FFI::string($result);
}

public function writePactFile(int $port, string $directory, bool $overwrite): int
{
$method = 'pactffi_write_pact_file';
$result = $this->call($method, $port, $directory, $overwrite);
if (!is_int($result)) {
throw new InvalidResultException(sprintf('Invalid result of "%s". Expected "integer", but got "%s"', $method, get_debug_type($result)));
}
return $result;
}

public function createMockServerForTransport(int $pact, string $host, int $port, string $transport, ?string $transportConfig): int
{
$method = 'pactffi_create_mock_server_for_transport';
$result = $this->call($method, $pact, $host, $port, $transport, $transportConfig);
if (!is_int($result)) {
throw new InvalidResultException(sprintf('Invalid result of "%s". Expected "integer", but got "%s"', $method, get_debug_type($result)));
}
return $result;
}

public function getInteractionPartRequest(): int
{
return $this->getEnum('InteractionPart_Request');
Expand Down
10 changes: 10 additions & 0 deletions src/PhpPact/FFI/ClientInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,16 @@ public function cleanupPlugins(int $pact): void;

public function usingPlugin(int $pact, string $name, ?string $version): int;

public function cleanupMockServer(int $port): bool;

public function mockServerMatched(int $port): bool;

public function mockServerMismatches(int $port): string;

public function writePactFile(int $port, string $directory, bool $overwrite): int;

public function createMockServerForTransport(int $pact, string $host, int $port, string $transport, ?string $transportConfig): int;

public function getInteractionPartRequest(): int;

public function getInteractionPartResponse(): int;
Expand Down
46 changes: 10 additions & 36 deletions tests/PhpPact/Consumer/Service/MockServerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@

namespace PhpPactTest\Consumer\Service;

use FFI;
use PhpPact\Config\PactConfigInterface;
use PhpPact\Consumer\Driver\Pact\PactDriverInterface;
use PhpPact\Consumer\Exception\MockServerNotStartedException;
use PhpPact\Consumer\Exception\MockServerPactFileNotWrittenException;
use PhpPact\Consumer\Model\Pact\Pact;
use PhpPact\Consumer\Service\MockServer;
Expand Down Expand Up @@ -56,21 +54,7 @@ public function testStart(int $returnedPort, bool $secure): void
->expects($this->once())
->method('getPact')
->willReturn(new Pact($this->pactHandle));
$calls = [
['pactffi_create_mock_server_for_transport', $this->pactHandle, $this->host, $this->port, $this->getTransport($secure), null, $returnedPort],
];
$this->assertClientCalls($calls);
if ($returnedPort < 0) {
$this->expectException(MockServerNotStartedException::class);
$this->expectExceptionMessage(match ($returnedPort) {
-1 => 'An invalid handle was received. Handles should be created with `pactffi_new_pact`',
-2 => 'Transport_config is not valid JSON',
-3 => 'The mock server could not be started',
-4 => 'The method panicked',
-5 => 'The address is not valid',
default => 'Unknown error',
});
}
$this->expectsCreateMockServerForTransport($this->pactHandle, $this->host, $this->port, $this->getTransport($secure), null, $returnedPort);
$this->mockServer->start();
$this->assertSame($returnedPort, $this->config->getPort());
}
Expand All @@ -81,16 +65,10 @@ public function testVerify(bool $matched): void
{
$this->config->setPort($this->port);
$this->config->setPactDir($this->pactDir);
$calls = $matched ? [
['pactffi_mock_server_matched', $this->port, $matched],
['pactffi_write_pact_file', $this->port, $this->pactDir, false, 0],
['pactffi_cleanup_mock_server', $this->port, null],
] : [
['pactffi_mock_server_matched', $this->port, $matched],
['pactffi_mock_server_mismatches', $this->port, FFI::new('char[1]')],
['pactffi_cleanup_mock_server', $this->port, null],
];
$this->assertClientCalls($calls);
$this->expectsMockServerMatched($this->port, $matched);
$this->expectsWritePactFile($this->port, $this->pactDir, false, 0, $matched);
$this->expectsMockServerMismatches($this->port, '', $matched);
$this->expectsCleanupMockServer($this->port, true);
$this->pactDriver
->expects($this->once())
->method('cleanUp');
Expand All @@ -114,10 +92,7 @@ public function testWritePact(int $error, string $writeMode): void
$this->config->setPort($this->port);
$this->config->setPactDir($this->pactDir);
$this->config->setPactFileWriteMode($writeMode);
$calls = [
['pactffi_write_pact_file', $this->port, $this->pactDir, $writeMode === PactConfigInterface::MODE_OVERWRITE, $error],
];
$this->assertClientCalls($calls);
$this->expectsWritePactFile($this->port, $this->pactDir, $writeMode === PactConfigInterface::MODE_OVERWRITE, $error, true);
if ($error) {
$this->expectException(MockServerPactFileNotWrittenException::class);
$this->expectExceptionMessage(match ($error) {
Expand All @@ -130,13 +105,12 @@ public function testWritePact(int $error, string $writeMode): void
$this->mockServer->writePact();
}

public function testCleanUp(): void
#[TestWith([true])]
#[TestWith([false])]
public function testCleanUp(bool $success): void
{
$this->config->setPort($this->port);
$calls = [
['pactffi_cleanup_mock_server', $this->port, null],
];
$this->assertClientCalls($calls);
$this->expectsCleanupMockServer($this->port, $success);
$this->pactDriver
->expects($this->once())
->method('cleanUp');
Expand Down
30 changes: 30 additions & 0 deletions tests/PhpPact/FFI/ClientTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,36 @@ public function testUsingPlugin(): void
$this->assertSame(2, $result);
}

public function testCleanupMockServer(): void
{
$result = $this->client->cleanupMockServer(1234);
$this->assertFalse($result);
}

public function testMockServerMatched(): void
{
$result = $this->client->mockServerMatched(1234);
$this->assertFalse($result);
}

public function testMockServerMismatches(): void
{
$result = $this->client->mockServerMismatches(1234);
$this->assertSame('', $result);
}

public function testWritePactFile(): void
{
$result = $this->client->writePactFile(1234, 'test', true);
$this->assertSame(3, $result);
}

public function testCreateMockServerForTransport(): void
{
$result = $this->client->createMockServerForTransport(1, 'localhost', 1234, 'http', null);
$this->assertSame(-1, $result);
}

public function testGetInteractionPartRequest(): void
{
$this->assertSame(0, $this->client->getInteractionPartRequest());
Expand Down

0 comments on commit 9e3c94d

Please sign in to comment.