/
WebServerSubscriber.php
146 lines (119 loc) · 3.52 KB
/
WebServerSubscriber.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
<?php
/*
* This file is part of the FOSHttpCache package.
*
* (c) FriendsOfSymfony <http://friendsofsymfony.github.com/>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FOS\HttpCache\Test;
use PHPUnit\Event\Code\TestMethod;
use PHPUnit\Event\TestRunner\ExecutionStarted;
use PHPUnit\Event\TestRunner\ExecutionStartedSubscriber;
use PHPUnit\Event\TestSuite\TestSuite;
use PHPUnit\Metadata\Group;
class WebServerSubscriber implements ExecutionStartedSubscriber
{
/**
* PHP web server PID.
*/
private int $pid;
private bool $isTopLevel = true;
public function notify(ExecutionStarted $event): void
{
if (!$this->isTopLevel) {
return;
}
$this->isTopLevel = false;
if (isset($this->pid)
|| !$this->hasTestsWithGroup($event->testSuite(), 'webserver')
) {
return;
}
$this->pid = $pid = $this->startPhpWebServer();
register_shutdown_function(static function () use ($pid): void {
exec('kill '.$pid);
});
}
private function hasTestsWithGroup(TestSuite $testSuite, string $group): bool
{
foreach ($testSuite->tests() as $test) {
if (!$test->isTestMethod()) {
continue;
}
assert($test instanceof TestMethod);
foreach ($test->metadata()->isGroup() as $testGroup) {
assert($testGroup instanceof Group);
if ($testGroup->groupName() === $group) {
return true;
}
}
}
return false;
}
/**
* Start PHP built-in web server.
*
* @return int PID
*/
public function startPhpWebServer(): int
{
$command = sprintf(
'php -S %s:%d -t %s >/dev/null 2>&1 & echo $!',
'127.0.0.1',
$this->getPort(),
$this->getDocRoot()
);
exec($command, $output);
$this->waitFor($this->getHostName(), (int) $this->getPort(), 2000);
return $output[0];
}
public function getHostName(): string
{
if (!defined('WEB_SERVER_HOSTNAME')) {
throw new \Exception('Set WEB_SERVER_HOSTNAME in your phpunit.xml');
}
return WEB_SERVER_HOSTNAME;
}
public function getPort(): string
{
if (!defined('WEB_SERVER_PORT')) {
throw new \Exception('Set WEB_SERVER_PORT in your phpunit.xml');
}
return WEB_SERVER_PORT;
}
public function getDocRoot(): string
{
if (!defined('WEB_SERVER_DOCROOT')) {
throw new \Exception('Set WEB_SERVER_DOCROOT in your phpunit.xml');
}
return WEB_SERVER_DOCROOT;
}
/**
* Wait for caching proxy to be started up and reachable.
*
* @param int $timeout Timeout in milliseconds
*
* @throws \RuntimeException If proxy is not reachable within timeout
*/
public function waitFor(string $ip, int $port, int $timeout): void
{
echo "Starting webserver at $ip:$port";
for ($i = 0; $i < $timeout; ++$i) {
echo '.';
if (@fsockopen($ip, $port)) {
echo " done.\n\n";
return;
}
usleep(1000);
}
throw new \RuntimeException(
sprintf(
'Webserver cannot be reached at %s:%s',
$ip,
$port
)
);
}
}