4b04a942f8a009481c784ad57d00bfc79e837491
[m6w6/seekat] / tests / bootstrap.php
1 <?php
2
3 require_once __DIR__."/../vendor/autoload.php";
4
5 function headers() : array {
6 static $headers;
7
8 if (!isset($headers)) {
9 if (($token = getenv("GITHUB_TOKEN"))) {
10 $headers["Authorization"] = "token $token";
11 } elseif (function_exists("posix_isatty") && defined("STDIN") && posix_isatty(STDIN)) {
12 fprintf(STDOUT, "GITHUB_TOKEN is not set in the environment, enter Y to continue without: ");
13 fflush(STDOUT);
14 if (strncasecmp(fgets(STDIN), "Y", 1)) {
15 exit;
16 }
17 $headers = [];
18 } else {
19 throw new Exception("GITHUB_TOKEN is not set in the environment");
20 }
21 }
22
23 return $headers;
24 }
25
26 function logger() : \Monolog\Logger {
27 static $logger;
28
29 if (!isset($logger)) {
30 $logger = new \Monolog\Logger(
31 "test",
32 [
33 new \Monolog\Handler\FingersCrossedHandler(
34 new \Monolog\Handler\StreamHandler(STDERR),
35 \Monolog\Logger::EMERGENCY
36 )
37 ]
38 );
39 }
40
41 return $logger;
42 }
43
44 class BaseTest extends \PHPUnit\Framework\TestCase
45 {
46 function provideAPI() {
47 $headers = headers();
48 $logger = logger();
49
50 return [
51 "using ReactPHP" => [new \seekat\API(\seekat\API\Future\react(), $headers, logger: $logger)],
52 "using AmPHP" => [new \seekat\API(\seekat\API\Future\amp(), $headers, logger: $logger)],
53 ];
54 }
55 }
56
57 trait ConsumePromise
58 {
59 function consumePromise($p, &$errors, &$results) {
60 if (method_exists($p, "done")) {
61 $p->then(function($result) use(&$results) {
62 if (isset($result)) {
63 $results[] = $result;
64 }
65 }, function($error) use (&$errors) {
66 if (isset($error)) {
67 $errors[] = $error;
68 }
69 });
70 } else {
71 $p->onResolve(function($error, $result) use(&$errors, &$results) {
72 if (isset($error)) {
73 $errors[] = $error;
74 }
75 if (isset($result)) {
76 $results[] = $result;
77 }
78 });
79 }
80 }
81 }
82
83 trait AssertSuccess
84 {
85 function assertAllSuccess(array $apis, ...$args) {
86 foreach ($apis as $api) {
87 $this->consumePromise($api->get(...$args), $errors, $results);
88 }
89 $api->send();
90 $this->assertEmpty($errors, "errors");
91 $this->assertNotEmpty($results, "results");
92 return $results;
93 }
94
95 function assertSuccess(seekat\API $api, ...$args) {
96 $this->consumePromise($api->get(...$args), $errors, $results);
97 $api->send();
98 $this->assertEmpty($errors, "errors");
99 $this->assertNotEmpty($results, "results");
100 return $results[0];
101 }
102 }
103
104 trait AssertCancelled
105 {
106 function assertCancelled($promise) {
107 $this->consumePromise($promise, $errors, $results);
108
109 $this->assertEmpty($results);
110 $this->assertStringMatchesFormat("%SCancelled%S", \seekat\Exception\message($errors[0]));
111 }
112 }
113
114 trait AssertFailure
115 {
116 function assertFailure(seekat\API $api, ...$args) {
117 $this->consumePromise($api->get(...$args), $errors, $results);
118 $api->send();
119 $this->assertNotEmpty($errors, "errors");
120 $this->assertEmpty($results, "results");
121 return $errors[0];
122 }
123 }
124
125 class CombinedTestdoxPrinter extends PHPUnit\TextUI\DefaultResultPrinter
126 {
127 function isTestClass(PHPUnit\Framework\TestSuite $suite) {
128 $suiteName = $suite->getName();
129 return false === strpos($suiteName, "::")
130 && substr($suiteName, -4) === "Test";
131 }
132
133 function startTestSuite(PHPUnit\Framework\TestSuite $suite) : void {
134 if ($this->isTestClass($suite)) {
135 $this->column = 0;
136 }
137
138 parent::startTestSuite($suite);
139 }
140
141 function endTestSuite(PHPUnit\Framework\TestSuite $suite) : void {
142 /* print % progress */
143 if ($this->isTestClass($suite)) {
144 if ($this->numTestsRun != $this->numTests) {
145 $colWidth = $this->maxColumn - $this->column;
146 $this->column = $this->maxColumn - 1;
147
148 --$this->numTestsRun;
149 $this->writeProgress(str_repeat(" ", $colWidth));
150 } else {
151 $this->writeNewLine();
152 }
153 }
154
155 parent::endTestSuite($suite);
156 }
157 }
158
159 class TestdoxListener implements PHPUnit\Framework\TestListener
160 {
161 private $groups;
162 private $testdox;
163
164 function __construct() {
165 $this->testdox = new PHPUnit\Util\TestDox\TextResultPrinter("php://stdout", ["testdox"]);
166 $this->groups = new ReflectionProperty("\PHPUnit\Util\TestDox\ResultPrinter", "groups");
167 $this->groups->setAccessible(true);
168 }
169
170 function startTest(PHPUnit\Framework\Test $test) : void {
171 /* always show test class, even if no testdox test */
172 if ($test instanceof \PHPUnit\Framework\TestCase) {
173 if ($test->getGroups() == ["default"]) {
174 $this->groups->setValue($this->testdox, ["default"]);
175 }
176 }
177
178 $this->testdox->startTest($test);
179 $this->groups->setValue($this->testdox, ["testdox"]);
180 }
181
182 public function addError(\PHPUnit\Framework\Test $test, Throwable $t, float $time): void
183 {
184 $this->testdox->addError($test, $t, $time);
185 }
186
187 public function addWarning(\PHPUnit\Framework\Test $test, \PHPUnit\Framework\Warning $e, float $time): void
188 {
189 $this->testdox->addWarning($test, $e, $time);
190 }
191
192 public function addFailure(\PHPUnit\Framework\Test $test, \PHPUnit\Framework\AssertionFailedError $e, float $time): void
193 {
194 $this->testdox->addFailure($test, $e, $time);
195 }
196
197 public function addIncompleteTest(\PHPUnit\Framework\Test $test, Throwable $t, float $time): void
198 {
199 $this->testdox->addIncompleteTest($test, $t, $time);
200 }
201
202 public function addRiskyTest(\PHPUnit\Framework\Test $test, Throwable $t, float $time): void
203 {
204 $this->testdox->addRiskyTest($test, $t, $time);
205 }
206
207 public function addSkippedTest(\PHPUnit\Framework\Test $test, Throwable $t, float $time): void
208 {
209 $this->testdox->addSkippedTest($test, $t, $time);
210 }
211
212 public function startTestSuite(\PHPUnit\Framework\TestSuite $suite): void
213 {
214 $this->testdox->startTestSuite($suite);
215 }
216
217 public function endTestSuite(\PHPUnit\Framework\TestSuite $suite): void
218 {
219 $this->testdox->endTestSuite($suite);
220 }
221
222 public function endTest(\PHPUnit\Framework\Test $test, float $time): void
223 {
224 $this->testdox->endTest($test, $time);
225 }
226 }
227
228 class DebugLogListener implements \PHPUnit\Framework\TestListener
229 {
230 use \PHPUnit\Framework\TestListenerDefaultImplementation;
231
232 private $printLog = false;
233
234 function endTest(PHPUnit\Framework\Test $test, float $time) : void {
235 /* @var $handler \Monolog\Handler\FingersCrossedHandler */
236 $handler = logger()->getHandlers()[0];
237 if ($this->printLog) {
238 $this->printLog = false;
239 $handler->activate();
240 } else {
241 $handler->clear();
242 }
243 }
244
245 function addError(PHPUnit\Framework\Test $test, \Throwable $e, float $time) : void {
246 $this->printLog = true;
247 }
248
249 function addFailure(PHPUnit\Framework\Test $test, PHPUnit\Framework\AssertionFailedError $e, float $time) : void {
250 $this->printLog = true;
251 }
252
253 }