Skip to content

Commit 7425ba9

Browse files
authored
Add wait_until_ready config and check if phiremock server is actually 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
1 parent d2b12ce commit 7425ba9

File tree

7 files changed

+259
-13
lines changed

7 files changed

+259
-13
lines changed

README.md

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ Optionally, you can install Phiremock Server in case you want to have it between
2323
"mcustiel/phiremock-codeception-extension": "^2.0",
2424
"mcustiel/phiremock-server": "^1.0",
2525
"guzzlehttp/guzzle": "^6.0"
26+
}
2627
```
2728

2829
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.
@@ -39,7 +40,8 @@ extensions:
3940
bin_path: ../vendor/bin # defaults to codeception_dir/../vendor/bin
4041
logs_path: /var/log/my_app/tests/logs # defaults to codeception's tests output dir
4142
debug: true # defaults to false
42-
start_delay: 1 # default to 0
43+
wait_until_ready: true # defaults to false
44+
wait_until_ready_timeout: 15 # defaults to 30
4345
expectations_path: /my/expectations/path # defaults to tests/_expectations
4446
server_factory: \My\FactoryClass # defaults to 'default'
4547
extra_instances: [] # deaults to an empty array
@@ -77,6 +79,17 @@ Time to wait after Phiremock Server is started before running the tests (used to
7779
7880
**Default:** 0
7981
82+
#### wait_until_ready
83+
This is more robust alternative to start_delay. It will check if Phiremock Server is actually running before running the tests.
84+
Note: it depends on Phiremeock Client to be installed via composer (it is used to check the status of Phiremock Server).
85+
86+
**Default:** false
87+
88+
#### wait_until_ready_timeout
89+
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.
90+
91+
**Default:** 30
92+
8093
#### expectations_path
8194
Specifies a directory to search for json files defining expectations to load by default.
8295
@@ -116,7 +129,6 @@ extensions:
116129
\Codeception\Extension\Phiremock:
117130
listen: 127.0.0.1:18080
118131
debug: true
119-
start_delay: 1
120132
expectations_path: /my/expectations/path-1
121133
suites:
122134
- acceptance

src/Extension/Phiremock.php

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
use Codeception\Suite;
2525
use Mcustiel\Phiremock\Codeception\Extension\Config;
2626
use Mcustiel\Phiremock\Codeception\Extension\PhiremockProcessManager;
27+
use Mcustiel\Phiremock\Codeception\Extension\ReadinessCheckerFactory;
2728

2829
class Phiremock extends CodeceptionExtension
2930
{
@@ -68,6 +69,7 @@ public function startProcess(SuiteEvent $event): void
6869
}
6970
}
7071
$this->executeDelay();
72+
$this->waitUntilReady();
7173
}
7274

7375
public function stopProcess(): void
@@ -108,4 +110,38 @@ private function setDefaultLogsPath(): void
108110
$this->config['logs_path'] = Config::getDefaultLogsPath();
109111
}
110112
}
113+
114+
private function waitUntilReady(): void
115+
{
116+
if (!$this->extensionConfig->isWaitUntilReady()) {
117+
return;
118+
}
119+
120+
$this->writeln('Waiting until Phiremock is ready...');
121+
122+
$readinessChecker = ReadinessCheckerFactory::create(
123+
$this->extensionConfig->getInterface(),
124+
$this->extensionConfig->getPort(),
125+
$this->extensionConfig->isSecure()
126+
);
127+
128+
$start = \microtime(true);
129+
130+
while (true) {
131+
if ($readinessChecker->isReady()) {
132+
break;
133+
}
134+
135+
\sleep(1);
136+
$elapsed = (int) (\microtime(true) - $start);
137+
138+
if ($elapsed > $this->extensionConfig->getWaitUntilReadyTimeout()) {
139+
throw new \RuntimeException(
140+
\sprintf('Phiremock failed to start within %d seconds', $this->extensionConfig->getWaitUntilReadyTimeout())
141+
);
142+
}
143+
}
144+
145+
$this->writeln('Phiremock is ready!');
146+
}
111147
}

src/PhiremockExtension/Config.php

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -36,19 +36,23 @@ class Config
3636
public const DEFAULT_SERVER_FACTORY = 'default';
3737
public const DEFAULT_EXTRA_INSTANCES = [];
3838
public const DEFAULT_SUITES = [];
39+
public const DEFAULT_WAIT_UNTIL_READY = false;
40+
public const DEFAULT_WAIT_UNTIL_READY_TIMEOUT = 30;
3941

4042
public const DEFAULT_CONFIG = [
41-
'listen' => self::DEFAULT_INTERFACE . ':' . self::DEFAULT_PORT,
42-
'debug' => self::DEFAULT_DEBUG_MODE,
43-
'start_delay' => self::DEFAULT_DELAY,
44-
'bin_path' => self::DEFAULT_PHIREMOCK_PATH,
45-
'expectations_path' => self::DEFAULT_EXPECTATIONS_PATH,
46-
'server_factory' => self::DEFAULT_SERVER_FACTORY,
47-
'certificate' => self::DEFAULT_CERTIFICATE,
48-
'certificate_key' => self::DEFAULT_CERTIFICATE_KEY,
49-
'cert_passphrase' => self::DEFAULT_CERTIFICATE_PASSPHRASE,
50-
'extra_instances' => self::DEFAULT_EXTRA_INSTANCES,
51-
'suites' => self::DEFAULT_SUITES,
43+
'listen' => self::DEFAULT_INTERFACE . ':' . self::DEFAULT_PORT,
44+
'debug' => self::DEFAULT_DEBUG_MODE,
45+
'start_delay' => self::DEFAULT_DELAY,
46+
'bin_path' => self::DEFAULT_PHIREMOCK_PATH,
47+
'expectations_path' => self::DEFAULT_EXPECTATIONS_PATH,
48+
'server_factory' => self::DEFAULT_SERVER_FACTORY,
49+
'certificate' => self::DEFAULT_CERTIFICATE,
50+
'certificate_key' => self::DEFAULT_CERTIFICATE_KEY,
51+
'cert_passphrase' => self::DEFAULT_CERTIFICATE_PASSPHRASE,
52+
'extra_instances' => self::DEFAULT_EXTRA_INSTANCES,
53+
'suites' => self::DEFAULT_SUITES,
54+
'wait_until_ready' => self::DEFAULT_WAIT_UNTIL_READY,
55+
'wait_until_ready_timeout' => self::DEFAULT_WAIT_UNTIL_READY_TIMEOUT
5256
];
5357

5458
/** @var string */
@@ -79,6 +83,10 @@ class Config
7983
private $suites;
8084
/** @var callable */
8185
private $output;
86+
/** @var bool */
87+
private $waitUntilReady;
88+
/** @var int */
89+
private $waitUntilReadyTimeout;
8290

8391
/** @throws ConfigurationException */
8492
public function __construct(array $config, callable $output)
@@ -96,6 +104,8 @@ public function __construct(array $config, callable $output)
96104
$this->certificatePassphrase = $config['cert_passphrase'];
97105
$this->initExtraInstances($config);
98106
$this->suites = $config['suites'];
107+
$this->waitUntilReady = (bool) $config['wait_until_ready'];
108+
$this->waitUntilReadyTimeout = (int) $config['wait_until_ready_timeout'];
99109
}
100110

101111
public function getSuites(): array
@@ -168,6 +178,22 @@ public function getExtraInstances(): array
168178
return $this->extraInstances;
169179
}
170180

181+
public function isSecure(): bool
182+
{
183+
return $this->getCertificatePath() !== null
184+
&& $this->getCertificateKeyPath() !== null;
185+
}
186+
187+
public function isWaitUntilReady(): bool
188+
{
189+
return $this->waitUntilReady;
190+
}
191+
192+
public function getWaitUntilReadyTimeout(): int
193+
{
194+
return $this->waitUntilReadyTimeout;
195+
}
196+
171197
/** @throws ConfigurationException */
172198
public static function getDefaultLogsPath(): string
173199
{
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
/**
3+
* This file is part of codeception-phiremock-extension.
4+
*
5+
* phiremock-codeception-extension is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU Lesser General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* phiremock-codeception-extension is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with phiremock-codeception-extension. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
19+
namespace Mcustiel\Phiremock\Codeception\Extension\ReadinessChecker;
20+
21+
use Mcustiel\Phiremock\Codeception\Extension\ReadinessCheckerInterface;
22+
23+
class CurlChecker implements ReadinessCheckerInterface
24+
{
25+
private $url;
26+
27+
public function __construct(string $url)
28+
{
29+
$this->url = rtrim($url, '/');
30+
}
31+
32+
public function isReady(): bool
33+
{
34+
$ch = \curl_init();
35+
36+
\curl_setopt($ch, CURLOPT_URL,$this->url . '/__phiremock/reset');
37+
\curl_setopt($ch, CURLOPT_POST, 1);
38+
\curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
39+
40+
$output = \curl_exec($ch);
41+
\curl_close($ch);
42+
43+
if ($output === false) {
44+
return false;
45+
}
46+
47+
return true;
48+
}
49+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php
2+
/**
3+
* This file is part of codeception-phiremock-extension.
4+
*
5+
* phiremock-codeception-extension is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU Lesser General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* phiremock-codeception-extension is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with phiremock-codeception-extension. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
19+
namespace Mcustiel\Phiremock\Codeception\Extension\ReadinessChecker;
20+
21+
use GuzzleHttp\Exception\ConnectException;
22+
use Mcustiel\Phiremock\Codeception\Extension\ReadinessCheckerInterface;
23+
use Mcustiel\Phiremock\Client\Phiremock;
24+
use Psr\Http\Client\ClientExceptionInterface;
25+
26+
class PhiremockClientChecker implements ReadinessCheckerInterface
27+
{
28+
private $client;
29+
30+
public function __construct(Phiremock $client)
31+
{
32+
$this->client = $client;
33+
}
34+
35+
public function isReady(): bool
36+
{
37+
try {
38+
$this->client->reset();
39+
return true;
40+
} catch (ConnectException $e) {}
41+
42+
return false;
43+
}
44+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
<?php
2+
/**
3+
* This file is part of codeception-phiremock-extension.
4+
*
5+
* phiremock-codeception-extension is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU Lesser General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* phiremock-codeception-extension is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with phiremock-codeception-extension. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
19+
namespace Mcustiel\Phiremock\Codeception\Extension;
20+
21+
use Mcustiel\Phiremock\Client\Factory;
22+
use Mcustiel\Phiremock\Client\Connection\Host;
23+
use Mcustiel\Phiremock\Client\Connection\Port;
24+
use Mcustiel\Phiremock\Client\Connection\Scheme;
25+
use Mcustiel\Phiremock\Codeception\Extension\ReadinessChecker\CurlChecker;
26+
use Mcustiel\Phiremock\Codeception\Extension\ReadinessChecker\PhiremockClientChecker;
27+
28+
class ReadinessCheckerFactory
29+
{
30+
public static function create(string $host, string $port, bool $isSecure): ReadinessCheckerInterface
31+
{
32+
if (class_exists(Factory::class)) {
33+
$phiremockClient = Factory::createDefault()
34+
->createPhiremockClient(
35+
new Host($host),
36+
new Port($port),
37+
$isSecure ? Scheme::createHttps() : Scheme::createHttp()
38+
);
39+
40+
return new PhiremockClientChecker(
41+
$phiremockClient
42+
);
43+
} elseif (extension_loaded('curl')) {
44+
$url = 'http' . ($isSecure ? 's' : '')
45+
. '://' . $host
46+
. ($port !== '' ? ':' . $port : '');
47+
48+
return new CurlChecker($url);
49+
}
50+
51+
throw new \RuntimeException(
52+
'Config wait_until_ready is enabled but no readiness checker can be run. Check if you have Phiremock Client installed or curl extension enabled.'
53+
);
54+
}
55+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
/**
3+
* This file is part of codeception-phiremock-extension.
4+
*
5+
* phiremock-codeception-extension is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU Lesser General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* phiremock-codeception-extension is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with phiremock-codeception-extension. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
19+
namespace Mcustiel\Phiremock\Codeception\Extension;
20+
21+
interface ReadinessCheckerInterface
22+
{
23+
public function isReady(): bool;
24+
}

0 commit comments

Comments
 (0)