ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
StreamTestTBD.php
Go to the documentation of this file.
1<?php
2
20
21use PHPUnit\Framework\Attributes\BackupGlobals;
22use PHPUnit\Framework\Attributes\BackupStaticProperties;
23use PHPUnit\Framework\Attributes\PreserveGlobalState;
24use PHPUnit\Framework\Attributes\RunTestsInSeparateProcesses;
25use PHPUnit\Framework\Attributes\Test;
26use PHPUnit\Framework\Attributes\Small;
28use Mockery;
29use PHPUnit\Framework\TestCase;
30
35#[BackupGlobals(false)]
36#[BackupStaticProperties(false)]
37#[PreserveGlobalState(false)]
38#[RunTestsInSeparateProcesses]
39class StreamTest extends TestCase
40{
44 public static $functions;
45
46 private function createResource(string $content, string $mode)
47 {
48 //call the root fopen function \ required!
49 return \fopen("data://text/plain,$content", $mode);
50 }
51
52
53 protected function setUp(): void
54 {
55 parent::setUp();
56
57 self::$functions = Mockery::mock();
58 }
59
60
61 public function testDetachWhichShouldSucceed(): void
62 {
63 $content = 'awesome content stream';
64 $mode = 'r';
65 $resource = $this->createResource($content, $mode);
66
67 $subject = new Stream($resource);
68 $detachedResource = $subject->detach();
69
70 //check that the resource is valid.
71 $this->assertTrue(is_resource($detachedResource));
72 $this->assertSame($resource, $detachedResource);
73
74 //Can't test the subject because psr-7 defines that the stream is in an unusable after the detach operation.
75 }
76
77
79 {
80 $content = 'awesome content stream';
81 $mode = 'r';
82 $resource = $this->createResource($content, $mode);
83
84 $subject = new Stream($resource);
85
86 //check that the detached resource is valid.
87 $detachedResource = $subject->detach();
88 $this->assertTrue(is_resource($detachedResource));
89
90 //must be null because the stream was already detached.
91 $detachedResource = $subject->detach();
92 $this->assertNull($detachedResource);
93 }
94
95
97 {
98 $content = 'awesome content stream';
99 $correctSize = strlen($content);
100 $mode = 'r';
101 $resource = $this->createResource($content, $mode);
102
103 $subject = new Stream($resource);
104
105 $size = $subject->getSize();
106 $this->assertSame($correctSize, $size);
107 }
108
109
111 {
112 $content = 'awesome content stream';
113 $correctSize = 900;
114 $mode = 'r';
115 $resource = $this->createResource($content, $mode);
116 $options = new StreamOptions([], $correctSize);
117
118 $subject = new Stream($resource, $options);
119
120 $size = $subject->getSize();
121 $this->assertSame($correctSize, $size);
122 }
123
125 {
126 $content = 'awesome content stream';
127 $mode = 'r';
128 $resource = $this->createResource($content, $mode);
129
130 $subject = new Stream($resource);
131 $subject->detach();
132
133 $size = $subject->getSize();
134 $this->assertNull($size);
135 }
136
137 public function testCloseWhichShouldSucceed(): void
138 {
139 $content = 'awesome content stream';
140 $mode = 'r';
141 $resource = $this->createResource($content, $mode);
142
143 $subject = new Stream($resource);
144
145 $subject->close();
146 $this->assertFalse(is_resource($resource));
147 }
148
150 {
151 $content = 'awesome content stream';
152 $mode = 'r';
153 $resource = $this->createResource($content, $mode);
154
155 $subject = new Stream($resource);
156
157 $actualResource = $subject->detach();
158 $subject->close();
159
160 $this->assertTrue(is_resource($actualResource));
161 }
162
163 public function testTellWhichShouldSucceed(): void
164 {
165 $content = 'awesome content stream';
166 $mode = 'r';
167 $offset = 5;
168 $resource = $this->createResource($content, $mode);
169 fseek($resource, $offset);
170
171 $subject = new Stream($resource);
172
173 $actualPosition = $subject->tell();
174 $this->assertSame($offset, $actualPosition);
175 }
176
178 {
179 $content = 'awesome content stream';
180 $mode = 'r';
181 $resource = $this->createResource($content, $mode);
182
183 $subject = new Stream($resource);
184 $subject->detach();
185
186 $this->expectException(\RuntimeException::class);
187 $this->expectExceptionMessage('Stream is detached');
188
189 $subject->tell();
190 }
191
193 {
194 $content = 'awesome content stream';
195 $mode = 'r';
196 $resource = $this->createResource($content, $mode);
197
198 //load mock class
199 $functionMock = Mockery::mock('alias:' . PHPStreamFunctions::class);
200 $functionMock->shouldReceive('ftell')
201 ->once()
202 ->with($resource)
203 ->andReturn(false);
204
205 $functionMock->shouldReceive('fclose')
206 ->once()
207 ->with($resource);
208
209 $subject = new Stream($resource);
210
211 $this->expectException(\RuntimeException::class);
212 $this->expectExceptionMessage('Unable to determine stream position');
213
214 $subject->tell();
215 }
216
217 #[Test]
218
219 public function testEofWhichShouldSucceed(): void
220 {
221 $content = 'awesome content stream';
222 $mode = 'r';
223 $offset = strlen($content); // end of stream
224 $resource = $this->createResource($content, $mode);
225 fseek($resource, $offset); // seek to end of stream
226 fgets($resource, 2); // we need to hit the end of the stream or eof returns false. (https://bugs.php.net/bug.php?id=35136)
227
228 $subject = new Stream($resource);
229
230 $endOfFileReached = $subject->eof();
231 $this->assertTrue($endOfFileReached);
232 }
233
234 #[Test]
235
237 {
238 $content = 'awesome content stream';
239 $mode = 'r';
240 $resource = $this->createResource($content, $mode);
241
242 $subject = new Stream($resource);
243 $subject->detach();
244
245 $this->expectException(\RuntimeException::class);
246 $this->expectExceptionMessage('Stream is detached');
247
248 $subject->eof();
249 }
250
251
252 #[Test]
253
254 public function testSeekWhichShouldSucceed(): void
255 {
256 $content = 'awesome content stream';
257 $mode = 'r';
258 $offset = 5;
259 $resource = $this->createResource($content, $mode);
260
261 $subject = new Stream($resource);
262
263 $subject->seek($offset);
264 $this->assertSame($offset, ftell($resource));
265 }
266
267 #[Test]
268
270 {
271 $content = 'awesome content stream';
272 $mode = 'r';
273 $offset = 5;
274 $resource = $this->createResource($content, $mode);
275
276 $subject = new Stream($resource);
277 $subject->detach();
278
279 $this->expectException(\RuntimeException::class);
280 $this->expectExceptionMessage('Stream is detached');
281
282 $subject->seek($offset);
283 }
284
285 #[Test]
286
288 {
289 $content = 'awesome content stream';
290 $mode = 'r';
291 $offset = 5;
292 $resource = $this->createResource($content, $mode);
293
294 $subjectMock = Mockery::mock(Stream::class . '[isSeekable]', [$resource]);
295
296 $subjectMock
297 ->shouldReceive('isSeekable')
298 ->once()
299 ->andReturn(false);
300
301 $this->expectException(\RuntimeException::class);
302 $this->expectExceptionMessage('Stream is not seekable');
303
304 $subjectMock->seek($offset);
305 }
306
307 #[Test]
308
310 {
311 $content = 'awesome content stream';
312 $mode = 'r';
313 $offset = 5;
314 $whence = SEEK_SET;
315 $resource = $this->createResource($content, $mode);
316
317 $subject = new Stream($resource);
318
319 //load mock class
320 $functionMock = Mockery::mock('alias:' . PHPStreamFunctions::class);
321 $functionMock->shouldReceive('fseek')
322 ->once()
323 ->withArgs([$resource, $offset, $whence])
324 ->andReturn(-1);
325
326 $functionMock->shouldReceive('fclose')
327 ->once()
328 ->with($resource);
329
330 $this->expectException(\RuntimeException::class);
331 $this->expectExceptionMessage("Unable to seek to stream position \"$offset\" with whence \"$whence\"");
332
333 $subject->seek($offset);
334 }
335
336 #[Test]
337
338 public function testReadWhichShouldSucceed(): void
339 {
340 $content = 'awesome content stream';
341 $expectedResult = "awesome";
342 $mode = 'r';
343 $length = 7;
344 $resource = $this->createResource($content, $mode);
345
346 $subject = new Stream($resource);
347
348 $text = $subject->read($length);
349 $this->assertSame($expectedResult, $text);
350 }
351
352 #[Test]
353
355 {
356 $content = 'awesome content stream';
357 $expectedResult = "";
358 $mode = 'r';
359 $length = 0;
360 $resource = $this->createResource($content, $mode);
361
362 $subject = new Stream($resource);
363
364 $text = $subject->read($length);
365 $this->assertSame($expectedResult, $text);
366 }
367
368 #[Test]
369
371 {
372 $content = 'awesome content stream';
373 $mode = 'r';
374 $length = 7;
375 $resource = $this->createResource($content, $mode);
376
377 $subject = new Stream($resource);
378 $subject->detach();
379
380 $this->expectException(\RuntimeException::class);
381 $this->expectExceptionMessage('Stream is detached');
382
383 $subject->read($length);
384 }
385
386 #[Test]
387
389 {
390 $content = 'awesome content stream';
391 $mode = 'r';
392 $length = -2;
393 $resource = $this->createResource($content, $mode);
394
395 $subject = new Stream($resource);
396
397 $this->expectException(\RuntimeException::class);
398 $this->expectExceptionMessage('Length parameter must not be negative');
399
400 $subject->read($length);
401 }
402
403 #[Test]
404
406 {
407 $content = 'awesome content stream';
408 $mode = 'w';
409 $length = 3;
410 $resource = $this->createResource($content, $mode);
411
412 $subject = new Stream($resource);
413
414 $this->expectException(\RuntimeException::class);
415 $this->expectExceptionMessage('Can not read from non-readable stream');
416
417 $subject->read($length);
418 }
419
420 #[Test]
421
423 {
424 $content = 'awesome content stream';
425 $mode = 'r';
426 $length = 3;
427 $resource = $this->createResource($content, $mode);
428
429 $subject = new Stream($resource);
430
431 //load mock class
432 $functionMock = Mockery::mock('alias:' . PHPStreamFunctions::class);
433
434 $functionMock->shouldReceive('fread')
435 ->once()
436 ->withArgs([$resource, $length])
437 ->andReturn(false);
438
439 $functionMock->shouldReceive('fclose')
440 ->once()
441 ->with($resource);
442
443 $this->expectException(\RuntimeException::class);
444 $this->expectExceptionMessage('Unable to read from stream');
445
446 $subject->read($length);
447 }
448
449 #[Test]
450
451 public function testGetContentsWhichShouldSucceed(): void
452 {
453 $content = 'awesome content stream';
454 $mode = 'r';
455 $resource = $this->createResource($content, $mode);
456
457 $subject = new Stream($resource);
458
459 $text = $subject->getContents();
460 $this->assertSame($content, $text);
461 }
462
463 #[Test]
464
466 {
467 $content = 'awesome content stream';
468 $mode = 'r';
469 $resource = $this->createResource($content, $mode);
470
471 $subject = new Stream($resource);
472 $subject->detach();
473
474 $this->expectException(\RuntimeException::class);
475 $this->expectExceptionMessage('Stream is detached');
476
477 $subject->getContents();
478 }
479
480 #[Test]
481
483 {
484 $content = 'awesome content stream';
485 $mode = 'r';
486 $resource = $this->createResource($content, $mode);
487
488 $subject = new Stream($resource);
489
490 //load mock class
491 $functionMock = Mockery::mock('alias:' . PHPStreamFunctions::class);
492
493 $functionMock->shouldReceive('stream_get_contents')
494 ->once()
495 ->with($resource)
496 ->andReturn(false);
497
498 $functionMock->shouldReceive('fclose')
499 ->once()
500 ->with($resource);
501
502 $this->expectException(\RuntimeException::class);
503 $this->expectExceptionMessage('Unable to read stream contents');
504
505 $subject->getContents();
506 }
507
508 #[Test]
509
510 public function testToStringWhichShouldSucceed(): void
511 {
512 $content = 'awesome content stream';
513 $mode = 'r';
514 $resource = $this->createResource($content, $mode);
515
516 $subject = new Stream($resource);
517
518 $text = $subject->__toString();
519 $this->assertSame($content, $text);
520 }
521
522 #[Test]
523
525 {
526 $content = 'awesome content stream';
527 $expectedResult = '';
528 $mode = 'r';
529 $resource = $this->createResource($content, $mode);
530
531 $subject = Mockery::mock(Stream::class . '[rewind]', [$resource]);
532
533 $subject->shouldDeferMissing();
534 $subject->shouldReceive('rewind')
535 ->once()
536 ->andThrow(\RuntimeException::class);
537
538 $text = $subject->__toString();
539 $this->assertSame($expectedResult, $text);
540 }
541
542 #[Test]
543
544 public function testWriteWhichShouldSucceed(): void
545 {
546 $content = 'awesome content stream';
547 $newContent = '!';
548 $byteCount = strlen($newContent);
549 $mode = 'r+';
550 $resource = fopen('php://memory', $mode);
551 PHPStreamFunctions::fwrite($resource, $content);
552
553 $subject = new Stream($resource);
554 $currentSize = $subject->getSize();
555
556 $numberOfBytesWritten = $subject->write($newContent);
557 $newSize = $subject->getSize();
558
559 $this->assertSame($byteCount, $numberOfBytesWritten, 'The count of bytes passed to write must match the written bytes after the operation.');
560 $this->assertGreaterThan($currentSize, $newSize, 'The new size must be grater than the old size because we wrote to the stream.');
561 }
562
563 #[Test]
564
566 {
567 $content = 'awesome content stream';
568 $newContent = '!';
569 $mode = 'w';
570 $resource = $this->createResource($content, $mode);
571
572 $subject = new Stream($resource);
573 $subject->detach();
574
575 $this->expectException(\RuntimeException::class);
576 $this->expectExceptionMessage('Stream is detached');
577
578 $subject->write($newContent);
579 }
580
581 #[Test]
582
584 {
585 $content = 'awesome content stream';
586 $newContent = '!';
587 $mode = 'r';
588 $resource = $this->createResource($content, $mode);
589
590 $subject = new Stream($resource);
591
592 $this->expectException(\RuntimeException::class);
593 $this->expectExceptionMessage('Can not write to a non-writable stream');
594
595 $subject->write($newContent);
596 }
597
598 #[Test]
599
601 {
602 $content = 'awesome content stream';
603 $newContent = '!';
604 $mode = 'a+';
605 $resource = $this->createResource($content, $mode);
606
607 $subject = new Stream($resource);
608
609 //load mock class
610 $functionMock = Mockery::mock('alias:' . PHPStreamFunctions::class);
611
612 $functionMock->shouldReceive('fwrite')
613 ->once()
614 ->withArgs([$resource, $newContent])
615 ->andReturn(false);
616
617 $functionMock->shouldReceive('fclose')
618 ->once()
619 ->with($resource);
620
621 $this->expectException(\RuntimeException::class);
622 $this->expectExceptionMessage('Unable to write to stream');
623
624 $subject->write($newContent);
625 }
626}
The streaming options are used by the stream implementation.
createResource(string $content, string $mode)
The purpose of this class is to wrap all stream handling php functions.
static fwrite($handle, string $string, ?int $length=null)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
Definition: FileStream.php:19