PluginProbe
StockPack – Stock photos and AI images from Unsplash, Adobe Stock, Freepik and more / 2.4.2
StockPack – Stock photos and AI images from Unsplash, Adobe Stock, Freepik and more v2.4.2
3.7.2 3.7.1 3.7.0 3.6.0 3.6.1 3.5.2 trunk 2.0 2.1 2.2 2.3 2.4 2.4.1 2.4.2 2.4.3 2.5.0 2.5.1 2.5.2 2.5.3 2.5.4 2.5.5 2.5.6 2.5.7 2.6.0 2.6.1 All 73 releases
stockpack / vendor / guzzlehttp / guzzle / tests / Handler / StreamHandlerTest.php

StreamHandlerTest.php in StockPack – Stock photos and AI images from Unsplash, Adobe Stock, Freepik and more 2.4.2, at vendor/guzzlehttp/guzzle/tests/Handler/StreamHandlerTest.php

689 lines 23.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace GuzzleHttp\Test\Handler;
3
4 use GuzzleHttp\Exception\ConnectException;
5 use GuzzleHttp\Handler\StreamHandler;
6 use GuzzleHttp\Psr7;
7 use GuzzleHttp\Psr7\FnStream;
8 use GuzzleHttp\Psr7\Request;
9 use GuzzleHttp\Psr7\Response;
10 use GuzzleHttp\RequestOptions;
11 use GuzzleHttp\Tests\Server;
12 use GuzzleHttp\TransferStats;
13 use PHPUnit\Framework\TestCase;
14 use Psr\Http\Message\ResponseInterface;
15
16 /**
17 * @covers \GuzzleHttp\Handler\StreamHandler
18 */
19 class StreamHandlerTest extends TestCase
20 {
21 private function queueRes()
22 {
23 Server::flush();
24 Server::enqueue([
25 new Response(200, [
26 'Foo' => 'Bar',
27 'Content-Length' => 8,
28 ], 'hi there')
29 ]);
30 }
31
32 public function testReturnsResponseForSuccessfulRequest()
33 {
34 $this->queueRes();
35 $handler = new StreamHandler();
36 $response = $handler(
37 new Request('GET', Server::$url, ['Foo' => 'Bar']),
38 []
39 )->wait();
40 self::assertSame(200, $response->getStatusCode());
41 self::assertSame('OK', $response->getReasonPhrase());
42 self::assertSame('Bar', $response->getHeaderLine('Foo'));
43 self::assertSame('8', $response->getHeaderLine('Content-Length'));
44 self::assertSame('hi there', (string) $response->getBody());
45 $sent = Server::received()[0];
46 self::assertSame('GET', $sent->getMethod());
47 self::assertSame('/', $sent->getUri()->getPath());
48 self::assertSame('127.0.0.1:8126', $sent->getHeaderLine('Host'));
49 self::assertSame('Bar', $sent->getHeaderLine('foo'));
50 }
51
52 /**
53 * @expectedException \GuzzleHttp\Exception\RequestException
54 */
55 public function testAddsErrorToResponse()
56 {
57 $handler = new StreamHandler();
58 $handler(
59 new Request('GET', 'http://localhost:123'),
60 ['timeout' => 0.01]
61 )->wait();
62 }
63
64 public function testStreamAttributeKeepsStreamOpen()
65 {
66 $this->queueRes();
67 $handler = new StreamHandler();
68 $request = new Request(
69 'PUT',
70 Server::$url . 'foo?baz=bar',
71 ['Foo' => 'Bar'],
72 'test'
73 );
74 $response = $handler($request, ['stream' => true])->wait();
75 self::assertSame(200, $response->getStatusCode());
76 self::assertSame('OK', $response->getReasonPhrase());
77 self::assertSame('8', $response->getHeaderLine('Content-Length'));
78 $body = $response->getBody();
79 $stream = $body->detach();
80 self::assertInternalType('resource', $stream);
81 self::assertSame('http', stream_get_meta_data($stream)['wrapper_type']);
82 self::assertSame('hi there', stream_get_contents($stream));
83 fclose($stream);
84 $sent = Server::received()[0];
85 self::assertSame('PUT', $sent->getMethod());
86 self::assertSame('http://127.0.0.1:8126/foo?baz=bar', (string) $sent->getUri());
87 self::assertSame('Bar', $sent->getHeaderLine('Foo'));
88 self::assertSame('test', (string) $sent->getBody());
89 }
90
91 public function testDrainsResponseIntoTempStream()
92 {
93 $this->queueRes();
94 $handler = new StreamHandler();
95 $request = new Request('GET', Server::$url);
96 $response = $handler($request, [])->wait();
97 $body = $response->getBody();
98 $stream = $body->detach();
99 self::assertSame('php://temp', stream_get_meta_data($stream)['uri']);
100 self::assertSame('hi', fread($stream, 2));
101 fclose($stream);
102 }
103
104 public function testDrainsResponseIntoSaveToBody()
105 {
106 $r = fopen('php://temp', 'r+');
107 $this->queueRes();
108 $handler = new StreamHandler();
109 $request = new Request('GET', Server::$url);
110 $response = $handler($request, ['sink' => $r])->wait();
111 $body = $response->getBody()->detach();
112 self::assertSame('php://temp', stream_get_meta_data($body)['uri']);
113 self::assertSame('hi', fread($body, 2));
114 self::assertSame(' there', stream_get_contents($r));
115 fclose($r);
116 }
117
118 public function testDrainsResponseIntoSaveToBodyAtPath()
119 {
120 $tmpfname = tempnam('/tmp', 'save_to_path');
121 $this->queueRes();
122 $handler = new StreamHandler();
123 $request = new Request('GET', Server::$url);
124 $response = $handler($request, ['sink' => $tmpfname])->wait();
125 $body = $response->getBody();
126 self::assertSame($tmpfname, $body->getMetadata('uri'));
127 self::assertSame('hi', $body->read(2));
128 $body->close();
129 unlink($tmpfname);
130 }
131
132 public function testDrainsResponseIntoSaveToBodyAtNonExistentPath()
133 {
134 $tmpfname = tempnam('/tmp', 'save_to_path');
135 unlink($tmpfname);
136 $this->queueRes();
137 $handler = new StreamHandler();
138 $request = new Request('GET', Server::$url);
139 $response = $handler($request, ['sink' => $tmpfname])->wait();
140 $body = $response->getBody();
141 self::assertSame($tmpfname, $body->getMetadata('uri'));
142 self::assertSame('hi', $body->read(2));
143 $body->close();
144 unlink($tmpfname);
145 }
146
147 public function testDrainsResponseAndReadsOnlyContentLengthBytes()
148 {
149 Server::flush();
150 Server::enqueue([
151 new Response(200, [
152 'Foo' => 'Bar',
153 'Content-Length' => 8,
154 ], 'hi there... This has way too much data!')
155 ]);
156 $handler = new StreamHandler();
157 $request = new Request('GET', Server::$url);
158 $response = $handler($request, [])->wait();
159 $body = $response->getBody();
160 $stream = $body->detach();
161 self::assertSame('hi there', stream_get_contents($stream));
162 fclose($stream);
163 }
164
165 public function testDoesNotDrainWhenHeadRequest()
166 {
167 Server::flush();
168 // Say the content-length is 8, but return no response.
169 Server::enqueue([
170 new Response(200, [
171 'Foo' => 'Bar',
172 'Content-Length' => 8,
173 ], '')
174 ]);
175 $handler = new StreamHandler();
176 $request = new Request('HEAD', Server::$url);
177 $response = $handler($request, [])->wait();
178 $body = $response->getBody();
179 $stream = $body->detach();
180 self::assertSame('', stream_get_contents($stream));
181 fclose($stream);
182 }
183
184 public function testAutomaticallyDecompressGzip()
185 {
186 Server::flush();
187 $content = gzencode('test');
188 Server::enqueue([
189 new Response(200, [
190 'Content-Encoding' => 'gzip',
191 'Content-Length' => strlen($content),
192 ], $content)
193 ]);
194 $handler = new StreamHandler();
195 $request = new Request('GET', Server::$url);
196 $response = $handler($request, ['decode_content' => true])->wait();
197 self::assertSame('test', (string) $response->getBody());
198 self::assertFalse($response->hasHeader('content-encoding'));
199 self::assertTrue(!$response->hasHeader('content-length') || $response->getHeaderLine('content-length') == $response->getBody()->getSize());
200 }
201
202 public function testReportsOriginalSizeAndContentEncodingAfterDecoding()
203 {
204 Server::flush();
205 $content = gzencode('test');
206 Server::enqueue([
207 new Response(200, [
208 'Content-Encoding' => 'gzip',
209 'Content-Length' => strlen($content),
210 ], $content)
211 ]);
212 $handler = new StreamHandler();
213 $request = new Request('GET', Server::$url);
214 $response = $handler($request, ['decode_content' => true])->wait();
215
216 self::assertSame(
217 'gzip',
218 $response->getHeaderLine('x-encoded-content-encoding')
219 );
220 self::assertSame(
221 strlen($content),
222 (int) $response->getHeaderLine('x-encoded-content-length')
223 );
224 }
225
226 public function testDoesNotForceGzipDecode()
227 {
228 Server::flush();
229 $content = gzencode('test');
230 Server::enqueue([
231 new Response(200, [
232 'Content-Encoding' => 'gzip',
233 'Content-Length' => strlen($content),
234 ], $content)
235 ]);
236 $handler = new StreamHandler();
237 $request = new Request('GET', Server::$url);
238 $response = $handler($request, ['decode_content' => false])->wait();
239 self::assertSame($content, (string) $response->getBody());
240 self::assertSame('gzip', $response->getHeaderLine('content-encoding'));
241 self::assertEquals(strlen($content), $response->getHeaderLine('content-length'));
242 }
243
244 public function testProtocolVersion()
245 {
246 $this->queueRes();
247 $handler = new StreamHandler();
248 $request = new Request('GET', Server::$url, [], null, '1.0');
249 $handler($request, []);
250 self::assertSame('1.0', Server::received()[0]->getProtocolVersion());
251 }
252
253 protected function getSendResult(array $opts)
254 {
255 $this->queueRes();
256 $handler = new StreamHandler();
257 $opts['stream'] = true;
258 $request = new Request('GET', Server::$url);
259 return $handler($request, $opts)->wait();
260 }
261
262 /**
263 * @expectedException \GuzzleHttp\Exception\ConnectException
264 * @expectedExceptionMessage Connection refused
265 */
266 public function testAddsProxy()
267 {
268 $this->getSendResult(['proxy' => '127.0.0.1:8125']);
269 }
270
271 public function testAddsProxyByProtocol()
272 {
273 $url = str_replace('http', 'tcp', Server::$url);
274 // Workaround until #1823 is fixed properly
275 $url = rtrim($url, '/');
276 $res = $this->getSendResult(['proxy' => ['http' => $url]]);
277 $opts = stream_context_get_options($res->getBody()->detach());
278 self::assertSame($url, $opts['http']['proxy']);
279 }
280
281 public function testAddsProxyButHonorsNoProxy()
282 {
283 $url = str_replace('http', 'tcp', Server::$url);
284 $res = $this->getSendResult(['proxy' => [
285 'http' => $url,
286 'no' => ['*']
287 ]]);
288 $opts = stream_context_get_options($res->getBody()->detach());
289 self::assertArrayNotHasKey('proxy', $opts['http']);
290 }
291
292 public function testAddsTimeout()
293 {
294 $res = $this->getSendResult(['stream' => true, 'timeout' => 200]);
295 $opts = stream_context_get_options($res->getBody()->detach());
296 self::assertEquals(200, $opts['http']['timeout']);
297 }
298
299 /**
300 * @expectedException \GuzzleHttp\Exception\RequestException
301 * @expectedExceptionMessage SSL CA bundle not found: /does/not/exist
302 */
303 public function testVerifiesVerifyIsValidIfPath()
304 {
305 $this->getSendResult(['verify' => '/does/not/exist']);
306 }
307
308 public function testVerifyCanBeDisabled()
309 {
310 $handler = $this->getSendResult(['verify' => false]);
311 self::assertInstanceOf('GuzzleHttp\Psr7\Response', $handler);
312 }
313
314 /**
315 * @expectedException \GuzzleHttp\Exception\RequestException
316 * @expectedExceptionMessage SSL certificate not found: /does/not/exist
317 */
318 public function testVerifiesCertIfValidPath()
319 {
320 $this->getSendResult(['cert' => '/does/not/exist']);
321 }
322
323 public function testVerifyCanBeSetToPath()
324 {
325 $path = $path = \GuzzleHttp\default_ca_bundle();
326 $res = $this->getSendResult(['verify' => $path]);
327 $opts = stream_context_get_options($res->getBody()->detach());
328 self::assertTrue($opts['ssl']['verify_peer']);
329 self::assertTrue($opts['ssl']['verify_peer_name']);
330 self::assertSame($path, $opts['ssl']['cafile']);
331 self::assertFileExists($opts['ssl']['cafile']);
332 }
333
334 public function testUsesSystemDefaultBundle()
335 {
336 $path = $path = \GuzzleHttp\default_ca_bundle();
337 $res = $this->getSendResult(['verify' => true]);
338 $opts = stream_context_get_options($res->getBody()->detach());
339 if (PHP_VERSION_ID < 50600) {
340 self::assertSame($path, $opts['ssl']['cafile']);
341 } else {
342 self::assertArrayNotHasKey('cafile', $opts['ssl']);
343 }
344 }
345
346 /**
347 * @expectedException \InvalidArgumentException
348 * @expectedExceptionMessage Invalid verify request option
349 */
350 public function testEnsuresVerifyOptionIsValid()
351 {
352 $this->getSendResult(['verify' => 10]);
353 }
354
355 public function testCanSetPasswordWhenSettingCert()
356 {
357 $path = __FILE__;
358 $res = $this->getSendResult(['cert' => [$path, 'foo']]);
359 $opts = stream_context_get_options($res->getBody()->detach());
360 self::assertSame($path, $opts['ssl']['local_cert']);
361 self::assertSame('foo', $opts['ssl']['passphrase']);
362 }
363
364 public function testDebugAttributeWritesToStream()
365 {
366 $this->queueRes();
367 $f = fopen('php://temp', 'w+');
368 $this->getSendResult(['debug' => $f]);
369 fseek($f, 0);
370 $contents = stream_get_contents($f);
371 self::assertContains('<GET http://127.0.0.1:8126/> [CONNECT]', $contents);
372 self::assertContains('<GET http://127.0.0.1:8126/> [FILE_SIZE_IS]', $contents);
373 self::assertContains('<GET http://127.0.0.1:8126/> [PROGRESS]', $contents);
374 }
375
376 public function testDebugAttributeWritesStreamInfoToBuffer()
377 {
378 $called = false;
379 $this->queueRes();
380 $buffer = fopen('php://temp', 'r+');
381 $this->getSendResult([
382 'progress' => function () use (&$called) {
383 $called = true;
384 },
385 'debug' => $buffer,
386 ]);
387 fseek($buffer, 0);
388 $contents = stream_get_contents($buffer);
389 self::assertContains('<GET http://127.0.0.1:8126/> [CONNECT]', $contents);
390 self::assertContains('<GET http://127.0.0.1:8126/> [FILE_SIZE_IS] message: "Content-Length: 8"', $contents);
391 self::assertContains('<GET http://127.0.0.1:8126/> [PROGRESS] bytes_max: "8"', $contents);
392 self::assertTrue($called);
393 }
394
395 public function testEmitsProgressInformation()
396 {
397 $called = [];
398 $this->queueRes();
399 $this->getSendResult([
400 'progress' => function () use (&$called) {
401 $called[] = func_get_args();
402 },
403 ]);
404 self::assertNotEmpty($called);
405 self::assertEquals(8, $called[0][0]);
406 self::assertEquals(0, $called[0][1]);
407 }
408
409 public function testEmitsProgressInformationAndDebugInformation()
410 {
411 $called = [];
412 $this->queueRes();
413 $buffer = fopen('php://memory', 'w+');
414 $this->getSendResult([
415 'debug' => $buffer,
416 'progress' => function () use (&$called) {
417 $called[] = func_get_args();
418 },
419 ]);
420 self::assertNotEmpty($called);
421 self::assertEquals(8, $called[0][0]);
422 self::assertEquals(0, $called[0][1]);
423 rewind($buffer);
424 self::assertNotEmpty(stream_get_contents($buffer));
425 fclose($buffer);
426 }
427
428 public function testPerformsShallowMergeOfCustomContextOptions()
429 {
430 $res = $this->getSendResult([
431 'stream_context' => [
432 'http' => [
433 'request_fulluri' => true,
434 'method' => 'HEAD',
435 ],
436 'socket' => [
437 'bindto' => '127.0.0.1:0',
438 ],
439 'ssl' => [
440 'verify_peer' => false,
441 ],
442 ],
443 ]);
444 $opts = stream_context_get_options($res->getBody()->detach());
445 self::assertSame('HEAD', $opts['http']['method']);
446 self::assertTrue($opts['http']['request_fulluri']);
447 self::assertSame('127.0.0.1:0', $opts['socket']['bindto']);
448 self::assertFalse($opts['ssl']['verify_peer']);
449 }
450
451 /**
452 * @expectedException \InvalidArgumentException
453 * @expectedExceptionMessage stream_context must be an array
454 */
455 public function testEnsuresThatStreamContextIsAnArray()
456 {
457 $this->getSendResult(['stream_context' => 'foo']);
458 }
459
460 public function testDoesNotAddContentTypeByDefault()
461 {
462 $this->queueRes();
463 $handler = new StreamHandler();
464 $request = new Request('PUT', Server::$url, ['Content-Length' => 3], 'foo');
465 $handler($request, []);
466 $req = Server::received()[0];
467 self::assertEquals('', $req->getHeaderLine('Content-Type'));
468 self::assertEquals(3, $req->getHeaderLine('Content-Length'));
469 }
470
471 public function testAddsContentLengthByDefault()
472 {
473 $this->queueRes();
474 $handler = new StreamHandler();
475 $request = new Request('PUT', Server::$url, [], 'foo');
476 $handler($request, []);
477 $req = Server::received()[0];
478 self::assertEquals(3, $req->getHeaderLine('Content-Length'));
479 }
480
481 public function testAddsContentLengthEvenWhenEmpty()
482 {
483 $this->queueRes();
484 $handler = new StreamHandler();
485 $request = new Request('PUT', Server::$url, [], '');
486 $handler($request, []);
487 $req = Server::received()[0];
488 self::assertEquals(0, $req->getHeaderLine('Content-Length'));
489 }
490
491 public function testSupports100Continue()
492 {
493 Server::flush();
494 $response = new Response(200, ['Test' => 'Hello', 'Content-Length' => '4'], 'test');
495 Server::enqueue([$response]);
496 $request = new Request('PUT', Server::$url, ['Expect' => '100-Continue'], 'test');
497 $handler = new StreamHandler();
498 $response = $handler($request, [])->wait();
499 self::assertSame(200, $response->getStatusCode());
500 self::assertSame('Hello', $response->getHeaderLine('Test'));
501 self::assertSame('4', $response->getHeaderLine('Content-Length'));
502 self::assertSame('test', (string) $response->getBody());
503 }
504
505 public function testDoesSleep()
506 {
507 $response = new response(200);
508 Server::enqueue([$response]);
509 $a = new StreamHandler();
510 $request = new Request('GET', Server::$url);
511 $s = \GuzzleHttp\_current_time();
512 $a($request, ['delay' => 0.1])->wait();
513 self::assertGreaterThan(0.0001, \GuzzleHttp\_current_time() - $s);
514 }
515
516 /**
517 * @expectedException \InvalidArgumentException
518 */
519 public function testEnsuresOnHeadersIsCallable()
520 {
521 $req = new Request('GET', Server::$url);
522 $handler = new StreamHandler();
523 $handler($req, ['on_headers' => 'error!']);
524 }
525
526 /**
527 * @expectedException \GuzzleHttp\Exception\RequestException
528 * @expectedExceptionMessage An error was encountered during the on_headers event
529 * @expectedExceptionMessage test
530 */
531 public function testRejectsPromiseWhenOnHeadersFails()
532 {
533 Server::flush();
534 Server::enqueue([
535 new Response(200, ['X-Foo' => 'bar'], 'abc 123')
536 ]);
537 $req = new Request('GET', Server::$url);
538 $handler = new StreamHandler();
539 $promise = $handler($req, [
540 'on_headers' => function () {
541 throw new \Exception('test');
542 }
543 ]);
544 $promise->wait();
545 }
546
547 public function testSuccessfullyCallsOnHeadersBeforeWritingToSink()
548 {
549 Server::flush();
550 Server::enqueue([
551 new Response(200, ['X-Foo' => 'bar'], 'abc 123')
552 ]);
553 $req = new Request('GET', Server::$url);
554 $got = null;
555
556 $stream = Psr7\stream_for();
557 $stream = FnStream::decorate($stream, [
558 'write' => function ($data) use ($stream, &$got) {
559 self::assertNotNull($got);
560 return $stream->write($data);
561 }
562 ]);
563
564 $handler = new StreamHandler();
565 $promise = $handler($req, [
566 'sink' => $stream,
567 'on_headers' => function (ResponseInterface $res) use (&$got) {
568 $got = $res;
569 self::assertSame('bar', $res->getHeaderLine('X-Foo'));
570 }
571 ]);
572
573 $response = $promise->wait();
574 self::assertSame(200, $response->getStatusCode());
575 self::assertSame('bar', $response->getHeaderLine('X-Foo'));
576 self::assertSame('abc 123', (string) $response->getBody());
577 }
578
579 public function testInvokesOnStatsOnSuccess()
580 {
581 Server::flush();
582 Server::enqueue([new Psr7\Response(200)]);
583 $req = new Psr7\Request('GET', Server::$url);
584 $gotStats = null;
585 $handler = new StreamHandler();
586 $promise = $handler($req, [
587 'on_stats' => function (TransferStats $stats) use (&$gotStats) {
588 $gotStats = $stats;
589 }
590 ]);
591 $response = $promise->wait();
592 self::assertSame(200, $response->getStatusCode());
593 self::assertSame(200, $gotStats->getResponse()->getStatusCode());
594 self::assertSame(
595 Server::$url,
596 (string) $gotStats->getEffectiveUri()
597 );
598 self::assertSame(
599 Server::$url,
600 (string) $gotStats->getRequest()->getUri()
601 );
602 self::assertGreaterThan(0, $gotStats->getTransferTime());
603 }
604
605 public function testInvokesOnStatsOnError()
606 {
607 $req = new Psr7\Request('GET', 'http://127.0.0.1:123');
608 $gotStats = null;
609 $handler = new StreamHandler();
610 $promise = $handler($req, [
611 'connect_timeout' => 0.001,
612 'timeout' => 0.001,
613 'on_stats' => function (TransferStats $stats) use (&$gotStats) {
614 $gotStats = $stats;
615 }
616 ]);
617 $promise->wait(false);
618 self::assertFalse($gotStats->hasResponse());
619 self::assertSame(
620 'http://127.0.0.1:123',
621 (string) $gotStats->getEffectiveUri()
622 );
623 self::assertSame(
624 'http://127.0.0.1:123',
625 (string) $gotStats->getRequest()->getUri()
626 );
627 self::assertInternalType('float', $gotStats->getTransferTime());
628 self::assertInstanceOf(
629 ConnectException::class,
630 $gotStats->getHandlerErrorData()
631 );
632 }
633
634 public function testStreamIgnoresZeroTimeout()
635 {
636 Server::flush();
637 Server::enqueue([new Psr7\Response(200)]);
638 $req = new Psr7\Request('GET', Server::$url);
639 $gotStats = null;
640 $handler = new StreamHandler();
641 $promise = $handler($req, [
642 'connect_timeout' => 10,
643 'timeout' => 0
644 ]);
645 $response = $promise->wait();
646 self::assertSame(200, $response->getStatusCode());
647 }
648
649 public function testDrainsResponseAndReadsAllContentWhenContentLengthIsZero()
650 {
651 Server::flush();
652 Server::enqueue([
653 new Response(200, [
654 'Foo' => 'Bar',
655 'Content-Length' => '0',
656 ], 'hi there... This has a lot of data!')
657 ]);
658 $handler = new StreamHandler();
659 $request = new Request('GET', Server::$url);
660 $response = $handler($request, [])->wait();
661 $body = $response->getBody();
662 $stream = $body->detach();
663 self::assertSame('hi there... This has a lot of data!', stream_get_contents($stream));
664 fclose($stream);
665 }
666
667 public function testHonorsReadTimeout()
668 {
669 Server::flush();
670 $handler = new StreamHandler();
671 $response = $handler(
672 new Request('GET', Server::$url . 'guzzle-server/read-timeout'),
673 [
674 RequestOptions::READ_TIMEOUT => 1,
675 RequestOptions::STREAM => true,
676 ]
677 )->wait();
678 self::assertSame(200, $response->getStatusCode());
679 self::assertSame('OK', $response->getReasonPhrase());
680 $body = $response->getBody()->detach();
681 $line = fgets($body);
682 self::assertSame("sleeping 60 seconds ...\n", $line);
683 $line = fgets($body);
684 self::assertFalse($line);
685 self::assertTrue(stream_get_meta_data($body)['timed_out']);
686 self::assertFalse(feof($body));
687 }
688 }
689