Skip to content

Commit

Permalink
Add wait_until_ready config and check if phiremock server is actually…
Browse files Browse the repository at this point in the history
… running (#48)

* Add new config wait_until_ready and actually check if phiremock server is up and running

* Mention phiremock client as optional dependency in readme

* Refactor code, add readiness checker interface and implementations for Phiremock Client and basic curl

* Update README.md
  • Loading branch information
barell authored May 1, 2021
1 parent d2b12ce commit 7425ba9
Show file tree
Hide file tree
Showing 7 changed files with 259 additions and 13 deletions.
16 changes: 14 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ Optionally, you can install Phiremock Server in case you want to have it between
"mcustiel/phiremock-codeception-extension": "^2.0",
"mcustiel/phiremock-server": "^1.0",
"guzzlehttp/guzzle": "^6.0"
}
```

Phiremock server has been made an optional dependency in case you want to run it from a phar file, a global composer dependency or in a docker container, and not have it as a project dependency.
Expand All @@ -39,7 +40,8 @@ extensions:
bin_path: ../vendor/bin # defaults to codeception_dir/../vendor/bin
logs_path: /var/log/my_app/tests/logs # defaults to codeception's tests output dir
debug: true # defaults to false
start_delay: 1 # default to 0
wait_until_ready: true # defaults to false
wait_until_ready_timeout: 15 # defaults to 30
expectations_path: /my/expectations/path # defaults to tests/_expectations
server_factory: \My\FactoryClass # defaults to 'default'
extra_instances: [] # deaults to an empty array
Expand Down Expand Up @@ -77,6 +79,17 @@ Time to wait after Phiremock Server is started before running the tests (used to
**Default:** 0
#### wait_until_ready
This is more robust alternative to start_delay. It will check if Phiremock Server is actually running before running the tests.
Note: it depends on Phiremeock Client to be installed via composer (it is used to check the status of Phiremock Server).
**Default:** false
#### wait_until_ready_timeout
This will be used only if wait_until_ready is set to true. You can specify after how many seconds it will stop checking if Phiremock Server is running.
**Default:** 30
#### expectations_path
Specifies a directory to search for json files defining expectations to load by default.
Expand Down Expand Up @@ -116,7 +129,6 @@ extensions:
\Codeception\Extension\Phiremock:
listen: 127.0.0.1:18080
debug: true
start_delay: 1
expectations_path: /my/expectations/path-1
suites:
- acceptance
Expand Down
36 changes: 36 additions & 0 deletions src/Extension/Phiremock.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
use Codeception\Suite;
use Mcustiel\Phiremock\Codeception\Extension\Config;
use Mcustiel\Phiremock\Codeception\Extension\PhiremockProcessManager;
use Mcustiel\Phiremock\Codeception\Extension\ReadinessCheckerFactory;

class Phiremock extends CodeceptionExtension
{
Expand Down Expand Up @@ -68,6 +69,7 @@ public function startProcess(SuiteEvent $event): void
}
}
$this->executeDelay();
$this->waitUntilReady();
}

public function stopProcess(): void
Expand Down Expand Up @@ -108,4 +110,38 @@ private function setDefaultLogsPath(): void
$this->config['logs_path'] = Config::getDefaultLogsPath();
}
}

private function waitUntilReady(): void
{
if (!$this->extensionConfig->isWaitUntilReady()) {
return;
}

$this->writeln('Waiting until Phiremock is ready...');

$readinessChecker = ReadinessCheckerFactory::create(
$this->extensionConfig->getInterface(),
$this->extensionConfig->getPort(),
$this->extensionConfig->isSecure()
);

$start = \microtime(true);

while (true) {
if ($readinessChecker->isReady()) {
break;
}

\sleep(1);
$elapsed = (int) (\microtime(true) - $start);

if ($elapsed > $this->extensionConfig->getWaitUntilReadyTimeout()) {
throw new \RuntimeException(
\sprintf('Phiremock failed to start within %d seconds', $this->extensionConfig->getWaitUntilReadyTimeout())
);
}
}

$this->writeln('Phiremock is ready!');
}
}
48 changes: 37 additions & 11 deletions src/PhiremockExtension/Config.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,19 +36,23 @@ class Config
public const DEFAULT_SERVER_FACTORY = 'default';
public const DEFAULT_EXTRA_INSTANCES = [];
public const DEFAULT_SUITES = [];
public const DEFAULT_WAIT_UNTIL_READY = false;
public const DEFAULT_WAIT_UNTIL_READY_TIMEOUT = 30;

public const DEFAULT_CONFIG = [
'listen' => self::DEFAULT_INTERFACE . ':' . self::DEFAULT_PORT,
'debug' => self::DEFAULT_DEBUG_MODE,
'start_delay' => self::DEFAULT_DELAY,
'bin_path' => self::DEFAULT_PHIREMOCK_PATH,
'expectations_path' => self::DEFAULT_EXPECTATIONS_PATH,
'server_factory' => self::DEFAULT_SERVER_FACTORY,
'certificate' => self::DEFAULT_CERTIFICATE,
'certificate_key' => self::DEFAULT_CERTIFICATE_KEY,
'cert_passphrase' => self::DEFAULT_CERTIFICATE_PASSPHRASE,
'extra_instances' => self::DEFAULT_EXTRA_INSTANCES,
'suites' => self::DEFAULT_SUITES,
'listen' => self::DEFAULT_INTERFACE . ':' . self::DEFAULT_PORT,
'debug' => self::DEFAULT_DEBUG_MODE,
'start_delay' => self::DEFAULT_DELAY,
'bin_path' => self::DEFAULT_PHIREMOCK_PATH,
'expectations_path' => self::DEFAULT_EXPECTATIONS_PATH,
'server_factory' => self::DEFAULT_SERVER_FACTORY,
'certificate' => self::DEFAULT_CERTIFICATE,
'certificate_key' => self::DEFAULT_CERTIFICATE_KEY,
'cert_passphrase' => self::DEFAULT_CERTIFICATE_PASSPHRASE,
'extra_instances' => self::DEFAULT_EXTRA_INSTANCES,
'suites' => self::DEFAULT_SUITES,
'wait_until_ready' => self::DEFAULT_WAIT_UNTIL_READY,
'wait_until_ready_timeout' => self::DEFAULT_WAIT_UNTIL_READY_TIMEOUT
];

/** @var string */
Expand Down Expand Up @@ -79,6 +83,10 @@ class Config
private $suites;
/** @var callable */
private $output;
/** @var bool */
private $waitUntilReady;
/** @var int */
private $waitUntilReadyTimeout;

/** @throws ConfigurationException */
public function __construct(array $config, callable $output)
Expand All @@ -96,6 +104,8 @@ public function __construct(array $config, callable $output)
$this->certificatePassphrase = $config['cert_passphrase'];
$this->initExtraInstances($config);
$this->suites = $config['suites'];
$this->waitUntilReady = (bool) $config['wait_until_ready'];
$this->waitUntilReadyTimeout = (int) $config['wait_until_ready_timeout'];
}

public function getSuites(): array
Expand Down Expand Up @@ -168,6 +178,22 @@ public function getExtraInstances(): array
return $this->extraInstances;
}

public function isSecure(): bool
{
return $this->getCertificatePath() !== null
&& $this->getCertificateKeyPath() !== null;
}

public function isWaitUntilReady(): bool
{
return $this->waitUntilReady;
}

public function getWaitUntilReadyTimeout(): int
{
return $this->waitUntilReadyTimeout;
}

/** @throws ConfigurationException */
public static function getDefaultLogsPath(): string
{
Expand Down
49 changes: 49 additions & 0 deletions src/PhiremockExtension/ReadinessChecker/CurlChecker.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php
/**
* This file is part of codeception-phiremock-extension.
*
* phiremock-codeception-extension is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* phiremock-codeception-extension is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with phiremock-codeception-extension. If not, see <http://www.gnu.org/licenses/>.
*/

namespace Mcustiel\Phiremock\Codeception\Extension\ReadinessChecker;

use Mcustiel\Phiremock\Codeception\Extension\ReadinessCheckerInterface;

class CurlChecker implements ReadinessCheckerInterface
{
private $url;

public function __construct(string $url)
{
$this->url = rtrim($url, '/');
}

public function isReady(): bool
{
$ch = \curl_init();

\curl_setopt($ch, CURLOPT_URL,$this->url . '/__phiremock/reset');
\curl_setopt($ch, CURLOPT_POST, 1);
\curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$output = \curl_exec($ch);
\curl_close($ch);

if ($output === false) {
return false;
}

return true;
}
}
44 changes: 44 additions & 0 deletions src/PhiremockExtension/ReadinessChecker/PhiremockClientChecker.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php
/**
* This file is part of codeception-phiremock-extension.
*
* phiremock-codeception-extension is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* phiremock-codeception-extension is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with phiremock-codeception-extension. If not, see <http://www.gnu.org/licenses/>.
*/

namespace Mcustiel\Phiremock\Codeception\Extension\ReadinessChecker;

use GuzzleHttp\Exception\ConnectException;
use Mcustiel\Phiremock\Codeception\Extension\ReadinessCheckerInterface;
use Mcustiel\Phiremock\Client\Phiremock;
use Psr\Http\Client\ClientExceptionInterface;

class PhiremockClientChecker implements ReadinessCheckerInterface
{
private $client;

public function __construct(Phiremock $client)
{
$this->client = $client;
}

public function isReady(): bool
{
try {
$this->client->reset();
return true;
} catch (ConnectException $e) {}

return false;
}
}
55 changes: 55 additions & 0 deletions src/PhiremockExtension/ReadinessCheckerFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php
/**
* This file is part of codeception-phiremock-extension.
*
* phiremock-codeception-extension is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* phiremock-codeception-extension is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with phiremock-codeception-extension. If not, see <http://www.gnu.org/licenses/>.
*/

namespace Mcustiel\Phiremock\Codeception\Extension;

use Mcustiel\Phiremock\Client\Factory;
use Mcustiel\Phiremock\Client\Connection\Host;
use Mcustiel\Phiremock\Client\Connection\Port;
use Mcustiel\Phiremock\Client\Connection\Scheme;
use Mcustiel\Phiremock\Codeception\Extension\ReadinessChecker\CurlChecker;
use Mcustiel\Phiremock\Codeception\Extension\ReadinessChecker\PhiremockClientChecker;

class ReadinessCheckerFactory
{
public static function create(string $host, string $port, bool $isSecure): ReadinessCheckerInterface
{
if (class_exists(Factory::class)) {
$phiremockClient = Factory::createDefault()
->createPhiremockClient(
new Host($host),
new Port($port),
$isSecure ? Scheme::createHttps() : Scheme::createHttp()
);

return new PhiremockClientChecker(
$phiremockClient
);
} elseif (extension_loaded('curl')) {
$url = 'http' . ($isSecure ? 's' : '')
. '://' . $host
. ($port !== '' ? ':' . $port : '');

return new CurlChecker($url);
}

throw new \RuntimeException(
'Config wait_until_ready is enabled but no readiness checker can be run. Check if you have Phiremock Client installed or curl extension enabled.'
);
}
}
24 changes: 24 additions & 0 deletions src/PhiremockExtension/ReadinessCheckerInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php
/**
* This file is part of codeception-phiremock-extension.
*
* phiremock-codeception-extension is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* phiremock-codeception-extension is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with phiremock-codeception-extension. If not, see <http://www.gnu.org/licenses/>.
*/

namespace Mcustiel\Phiremock\Codeception\Extension;

interface ReadinessCheckerInterface
{
public function isReady(): bool;
}

0 comments on commit 7425ba9

Please sign in to comment.