Test Failed
Push — master ( 1b8cd6...6d13a4 )
by Mariano
09:42
created

Phiremock74p::getOutputCallable()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 2
c 1
b 0
f 0
dl 0
loc 4
rs 10
cc 1
nc 1
nop 0
1
<?php
2
/**
3
 * This file is part of phiremock-codeception-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 Codeception\Extension;
20
21
use Codeception\Event\SuiteEvent;
22
use Codeception\Exception\ConfigurationException;
23
use Codeception\Extension as CodeceptionExtension;
24
use Codeception\Suite;
25
use Mcustiel\Phiremock\Codeception\Extension\Config;
26
use Mcustiel\Phiremock\Codeception\Extension\PhiremockProcessManager;
27
use Mcustiel\Phiremock\Codeception\Extension\ReadinessCheckerFactory;
28
29
class Phiremock74p extends CodeceptionExtension
30
{
31
    /** @var array */
32
    public static array $events = [
33
        'suite.before' => 'startProcess',
34
        'suite.after'  => 'stopProcess',
35
    ];
36
37
    /** @var array */
38
    protected array $config = Config::DEFAULT_CONFIG;
39
40
    /** @var PhiremockProcessManager */
41
    private $process;
42
43
    /** @var Config */
44
    private $extensionConfig;
45
46
    /**  @throws ConfigurationException */
47
    public function __construct(
48
        array $config,
49
        array $options,
50
        PhiremockProcessManager $process = null
51
    ) {
52
        $this->setDefaultLogsPath();
53
        parent::__construct($config, $options);
54
        $this->extensionConfig = new Config($this->config, $this->getOutputCallable());
55
        $this->initProcess($process);
56
    }
57
58
    public function startProcess(SuiteEvent $event): void
59
    {
60
        $this->writeln('Starting default phiremock instance...');
61
        $suite = $event->getSuite();
62
        if ($this->mustRunForSuite($suite, $this->extensionConfig->getSuites())) {
63
            $this->process->start($this->extensionConfig);
64
        }
65
        foreach ($this->extensionConfig->getExtraInstances() as $configInstance) {
66
            if ($this->mustRunForSuite($suite, $configInstance->getSuites())) {
67
                $this->writeln('Starting extra phiremock instance...');
68
                $this->process->start($configInstance);
69
            }
70
        }
71
        $this->executeDelay();
72
        $this->waitUntilReady();
73
    }
74
75
    public function stopProcess(): void
76
    {
77
        $this->writeln('Stopping phiremock...');
78
        $this->process->stop();
79
    }
80
81
    public function getOutputCallable(): callable
82
    {
83
        return function (string $message) {
84
            $this->writeln($message);
85
        };
86
    }
87
88
    private function mustRunForSuite(Suite $suite, array $allowedSuites): bool
89
    {
90
        return empty($allowedSuites) || in_array($suite->getBaseName(), $allowedSuites, true);
91
    }
92
93
    private function executeDelay(): void
94
    {
95
        $delay = $this->extensionConfig->getDelay();
96
        if ($delay > 0) {
97
            sleep($delay);
98
        }
99
    }
100
101
    private function initProcess(?PhiremockProcessManager $process): void
102
    {
103
        $this->process = $process ?? new PhiremockProcessManager($this->getOutputCallable());
104
    }
105
106
    /** @throws ConfigurationException */
107
    private function setDefaultLogsPath(): void
108
    {
109
        if (!isset($this->config['logs_path'])) {
110
            $this->config['logs_path'] = Config::getDefaultLogsPath();
111
        }
112
    }
113
114
    private function waitUntilReady(): void
115
    {
116
        if (!$this->extensionConfig->waitUntilReady()) {
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
        $interval = $this->extensionConfig->getWaitUntilReadyIntervalMicros();
130
        $timeout = $this->extensionConfig->getWaitUntilReadyTimeout();
131
        while (true) {
132
            if ($readinessChecker->isReady()) {
133
                break;
134
            }
135
            \usleep($interval);
136
            $elapsed = (int) (\microtime(true) - $start);
137
138
            if ($elapsed > $timeout) {
139
                throw new \RuntimeException(
140
                    \sprintf('Phiremock failed to start within %d seconds', $this->extensionConfig->getWaitUntilReadyTimeout())
141
                );
142
            }
143
        }
144
        $this->writeln('Phiremock is ready!');
145
    }
146
}
147