ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
FlySystemFileAccessTestTBD.php
Go to the documentation of this file.
1<?php
2
20
22use Mockery\LegacyMockInterface;
23use PHPUnit\Framework\Attributes\Test;
24use PHPUnit\Framework\Attributes\Small;
28use League\Flysystem\Filesystem;
29use League\Flysystem\FilesystemAdapter;
30use League\Flysystem\FilesystemOperator;
31use Mockery;
32use Mockery\Adapter\Phpunit\MockeryPHPUnitIntegration;
33use Mockery\MockInterface;
34use PHPUnit\Framework\TestCase;
35use League\Flysystem\AdapterInterface;
36use League\Flysystem\UnableToReadFile;
37use League\Flysystem\UnableToWriteFile;
38use League\Flysystem\UnableToRetrieveMetadata;
39use League\Flysystem\UnableToDeleteFile;
40use League\Flysystem\UnableToMoveFile;
41use League\Flysystem\UnableToCopyFile;
42use League\Flysystem\UnableToSetVisibility;
43
48class FlySystemFileAccessTest extends TestCase
49{
50 use MockeryPHPUnitIntegration;
51
53 private Filesystem|MockInterface $filesystemMock;
54
59 protected function setUp(): void
60 {
61 parent::setUp();
62
63 $this->filesystemMock = Mockery::mock(FilesystemOperator::class);
64 $adapterMock = Mockery::mock(FilesystemAdapter::class);
65 $this->subject = new FlySystemFileAccess($this->filesystemMock);
66 }
67
68 public function testReadWhichShouldSucceed(): void
69 {
70 $file_content = 'Test file content.';
71 $path = '/path/to/your/file';
72
73 $this->filesystemMock->shouldReceive('has')
74 ->once()
75 ->with(ltrim($path, '/'))
76 ->andReturn(true);
77
78 $this->filesystemMock->shouldReceive('read')
79 ->with(ltrim($path, '/'))
80 ->once()
81 ->andReturn($file_content);
82
83
84 $actualContent = $this->subject->read($path);
85 $this->assertSame($file_content, $actualContent);
86 }
87
89 {
90 $path = '/path/to/your/file';
91
92 $this->filesystemMock->shouldReceive('has')
93 ->once()
94 ->with(ltrim($path, '/'))
95 ->andReturn(true);
96
97 $this->filesystemMock->shouldReceive('read')
98 ->with(ltrim($path, '/'))
99 ->once()
100 ->andReturn(false);
101
102
103 $this->expectException(IOException::class);
104 $this->expectExceptionMessage('File "' . ltrim($path, '/') . '" not found.');
105 $actualContent = $this->subject->read($path);
106 }
107
109 {
110
111 $path = '/path/to/your/file';
112
113 $this->filesystemMock->shouldReceive('has')
114 ->once()
115 ->with(ltrim($path, '/'))
116 ->andReturn(false);
117
118 $this->filesystemMock->shouldReceive('read')
119 ->never();
120
121
122 $this->expectException(IOException::class);
123 $this->expectExceptionMessage('File "' . ltrim($path, '/') . '" not found.');
124 $actualContent = $this->subject->read($path);
125 }
126
127 public function testGetMimeTypeWhichShouldSucceed(): void
128 {
129 $mimeType = 'image/jpeg';
130 $this->filesystemMock->shouldReceive('mimeType')
131 ->once()
132 ->andReturn($mimeType);
133
134 $actualMimeType = $this->subject->getMimeType('/path/to/your/file');
135 $this->assertSame($mimeType, $actualMimeType);
136 }
137
138 public function testPutContentExistingFile(): void
139 {
140 $content = 'Test file content.';
141 $this->filesystemMock->shouldReceive('has')
142 ->once()
143 ->andReturn(true);
144 $this->filesystemMock->shouldReceive('write')
145 ->with('/path/to/your/file', $content)
146 ->once()
147 ->andReturn(true);
148
149 $this->subject->put('/path/to/your/file', $content);
150 }
151
152 public function testPutContentNonExistingFile(): void
153 {
154 $content = 'Test file content.';
155 $this->filesystemMock->shouldReceive('has')
156 ->twice()
157 ->andReturn(false);
158
159 $this->filesystemMock->shouldReceive('write')
160 ->with('/path/to/your/file', $content)
161 ->once()
162 ->andReturn(true);
163
164 $this->subject->put('/path/to/your/file', $content);
165 }
166
167
169 {
170 $path = '/path/to/your/file';
171 $this->filesystemMock->shouldReceive('mimeType')
172 ->with($path)
173 ->once()
174 ->andReturn('');
175
176 $this->expectException(IOException::class);
177 $this->expectExceptionMessage("Could not determine the MIME type of the file \"$path\".");
178
179 $this->subject->getMimeType($path);
180 }
181
183 {
184 $path = '/path/to/your/file';
185 $this->filesystemMock->shouldReceive('mimeType')
186 ->once()
187 ->with($path)
188 ->andThrow(UnableToRetrieveMetadata::class);
189
190 $this->expectException(IOException::class);
191 $this->expectExceptionMessage("File \"$path\" not found.");
192
193 $this->subject->getMimeType($path);
194 }
195
197 {
198 $datetime = '2012-02-06';
199 $timestamp = strtotime($datetime);
200 $this->filesystemMock
201 ->shouldReceive('lastModified')
202 ->once()
203 ->andReturn($timestamp);
204
205 $actualTimestamp = $this->subject->getTimestamp('/path/to/your/file');
206
207 /*
208 * needs to be equals instead of same because == checks if the object content is the same and === seems to check the reference too
209 * eg.
210 * $a == $b => true
211 * $a === $b => false
212 * $a === $a => true
213 * $b === $b => true
214 *
215 * Danger; this is only the observed behaviour and was not documented at least the part with the === operator.
216 * Tested with DateTime objects (PHP 7.1.6)
217 */
218 $this->assertEquals(new \DateTime($datetime), $actualTimestamp);
219 }
220
222 {
223 $path = '/path/to/your/file';
224 $this->filesystemMock
225 ->shouldReceive('lastModified')
226 ->with($path)
227 ->once()
228 ->andThrow(UnableToRetrieveMetadata::class);
229
230 $this->expectException(IOException::class);
231 $this->expectExceptionMessage("Could not lookup timestamp of the file \"$path\".");
232
233 $this->subject->getTimestamp($path);
234 }
235
237 {
238 $path = '/path/to/your/file';
239 $this->filesystemMock
240 ->shouldReceive('lastModified')
241 ->once()
242 ->with($path)
243 ->andThrow(UnableToReadFile::class);
244
245 $this->expectException(IOException::class);
246 $this->expectExceptionMessage("File \"$path\" not found.");
247
248 $this->subject->getTimestamp($path);
249 }
250
251 public function testGetSizeWhichShouldSucceed(): void
252 {
253 $rawSize = 1024;
254 $size = new DataSize($rawSize, DataSize::KiB); //floating point is never that precise.
255
256 $this->filesystemMock->shouldReceive('fileSize')
257 ->once()
258 ->andReturn($rawSize);
259
260 $actualSize = $this->subject->getSize('/path/to/your/file', DataSize::KiB);
261 $this->assertSame($size->getSize(), $actualSize->getSize(), '');
262 }
263
265 {
266 $path = '/path/to/your/file';
267 $this->filesystemMock
268 ->shouldReceive('fileSize')
269 ->with($path)
270 ->once()
271 ->andThrow(UnableToRetrieveMetadata::class);
272
273 $this->expectException(IOException::class);
274 $this->expectExceptionMessage("File \"$path\" not found.");
275
276 $this->subject->getSize($path, DataSize::MiB);
277 }
278
280 {
281 $path = '/path/to/your/file';
282 $this->filesystemMock
283 ->shouldReceive('fileSize')
284 ->once()
285 ->with($path)
286 ->andThrow(UnableToRetrieveMetadata::class);
287
288 $this->expectException(IOException::class);
289 $this->expectExceptionMessage("File \"$path\" not found.");
290
291 $this->subject->getSize($path, DataSize::GiB);
292 }
293
295 {
296 $path = '/path/to/your/file';
297 $visibility = "private";
298
299 $this->filesystemMock->shouldReceive('has')
300 ->once()
301 ->with($path)
302 ->andReturn(true);
303
304 $this->filesystemMock->shouldReceive('setVisibility')
305 ->once()
306 ->withArgs([$path, $visibility])
307 ->andReturn(true);
308
309 $operationSuccessful = $this->subject->setVisibility($path, $visibility);
310 $this->assertTrue($operationSuccessful);
311 }
312
314 {
315 $path = '/path/to/your/file';
316 $visibility = "private";
317
318 $this->filesystemMock->shouldReceive('has')
319 ->once()
320 ->with($path)
321 ->andReturn(true);
322
323 $this->filesystemMock->shouldReceive('setVisibility')
324 ->once()
325 ->withArgs([$path, $visibility])
326 ->andThrow(UnableToSetVisibility::class);
327
328 $operationSuccessful = $this->subject->setVisibility($path, $visibility);
329 $this->assertFalse($operationSuccessful);
330 }
331
332 #[Test]
333
335 {
336 $path = '/path/to/your/file';
337 $visibility = "private";
338
339 $this->filesystemMock->shouldReceive('has')
340 ->once()
341 ->with($path)
342 ->andReturn(false);
343
344 $this->expectException(FileNotFoundException::class);
345 $this->expectExceptionMessage("Path \"$path\" not found.");
346
347 $this->subject->setVisibility($path, $visibility);
348 }
349
350 #[Test]
351
353 {
354 $path = '/path/to/your/file';
355 $visibility = "not valid";
356
357 $this->filesystemMock->shouldReceive('has')
358 ->once()
359 ->with($path)
360 ->andReturn(true);
361
362 $this->expectException(\InvalidArgumentException::class);
363 $this->expectExceptionMessage("The access must be 'public' or 'private' but '$visibility' was given.");
364
365 $this->subject->setVisibility($path, $visibility);
366 }
367
368 #[Test]
369
371 {
372 $path = '/path/to/your/file';
373 $visibility = "private";
374
375 $this->filesystemMock->shouldReceive('has')
376 ->once()
377 ->with($path)
378 ->andReturn(true);
379
380 $this->filesystemMock->shouldReceive('getVisibility')
381 ->once()
382 ->with($path)
383 ->andReturn($visibility);
384
385 $actualVisibility = $this->subject->getVisibility($path);
386 $this->assertSame($visibility, $actualVisibility);
387 }
388
389 #[Test]
390
392 {
393 $path = '/path/to/your/file';
394
395 $this->filesystemMock->shouldReceive('has')
396 ->once()
397 ->with($path)
398 ->andReturn(false);
399
400 $this->expectException(FileNotFoundException::class);
401 $this->expectExceptionMessage("Path \"$path\" not found.");
402
403 $this->subject->getVisibility($path);
404 }
405
406 #[Test]
407
409 {
410 $path = '/path/to/your/file';
411
412 $this->filesystemMock->shouldReceive('has')
413 ->once()
414 ->with($path)
415 ->andReturn(true);
416
417 $this->filesystemMock->shouldReceive('getVisibility')
418 ->once()
419 ->with($path)
420 ->andReturn(false);
421
422 $this->expectException(IOException::class);
423 $this->expectExceptionMessage("Could not determine visibility for path '$path'.");
424
425 $this->subject->getVisibility($path);
426 }
427
428 #[Test]
429
430 public function testWriteWhichShouldSucceed(): void
431 {
432 $path = '/path/to/your/file';
433 $content = "some awesome content";
434
435 $this->filesystemMock
436 ->shouldReceive('has')
437 ->once()
438 ->with($path)
439 ->andReturn(false)
440 ->getMock()
441 ->shouldReceive('write')
442 ->once()
443 ->withArgs([$path, $content]);
444
445 $this->subject->write($path, $content);
446 }
447
448 #[Test]
449
451 {
452 $path = '/path/to/your/file';
453 $content = "some awesome content";
454
455 $this->filesystemMock
456 ->shouldReceive('has')
457 ->once()
458 ->with($path)
459 ->andReturn(true)
460 ->shouldReceive('write')
461 ->never()
462 ->withArgs([$path, $content])
463 ->andThrow(UnableToWriteFile::class);
464
465 $this->expectException(FileAlreadyExistsException::class);
466 $this->expectExceptionMessage("File \"$path\" already exists.");
467
468 $this->subject->write($path, $content);
469 }
470
471 #[Test]
472
474 {
475 $path = '/path/to/your/file';
476 $content = "some awesome content";
477
478 $this->filesystemMock
479 ->shouldReceive('has')
480 ->once()
481 ->with($path)
482 ->andReturn(false)
483 ->getMock()
484 ->shouldReceive('write')
485 ->once()
486 ->withArgs([$path, $content])
487 ->andThrow(UnableToWriteFile::class);
488
489 $this->expectException(IOException::class);
490 $this->expectExceptionMessage(
491 "Could not write to file \"$path\" because a general IO error occurred. Please check that your destination is writable."
492 );
493
494 $this->subject->write($path, $content);
495 }
496
497 #[Test]
498
499 public function testUpdateWhichShouldSucceed(): void
500 {
501 $path = '/path/to/your/file';
502 $content = "some awesome content";
503
504 $this->filesystemMock->shouldReceive('write')
505 ->once()
506 ->withArgs([$path, $content])
507 ->andReturn(true);
508
509 $this->subject->update($path, $content);
510 }
511
512 #[Test]
513
515 {
516 $path = '/path/to/your/file';
517 $content = "some awesome content";
518
519 $this->filesystemMock->shouldReceive('write')
520 ->once()
521 ->withArgs([$path, $content])
522 ->andThrow(UnableToWriteFile::class);
523
524 $this->expectException(IOException::class);
525 $this->expectExceptionMessage(
526 "Could not write to file \"$path\" because a general IO error occurred. Please check that your destination is writable."
527 );
528
529 $this->subject->update($path, $content);
530 }
531
532 #[Test]
533
535 {
536 $path = '/path/to/your/file';
537 $content = "some awesome content";
538
539 $this->filesystemMock
540 ->shouldReceive('write')
541 ->once()
542 ->withArgs([$path, $content])
543 ->andThrow(UnableToWriteFile::class);
544
545 $this->expectException(IOException::class);
546 $this->expectExceptionMessage(
547 "Could not write to file \"$path\" because a general IO error occurred. Please check that your destination is writable."
548 );
549
550 $this->subject->update($path, $content);
551 }
552
553 #[Test]
554
555 public function testDeleteWhichShouldSucceed(): void
556 {
557 $path = '/path/to/your/file';
558
559 $this->filesystemMock->shouldReceive('delete')
560 ->once()
561 ->with($path)
562 ->andReturn(true);
563
564 $this->subject->delete($path);
565 }
566
567 #[Test]
568
570 {
571 $path = '/path/to/your/file';
572
573 $this->filesystemMock->shouldReceive('delete')
574 ->once()
575 ->with($path)
576 ->andThrow(UnableToDeleteFile::class);
577
578 $this->expectException(IOException::class);
579 $this->expectExceptionMessage(
580 "Could not delete file \"$path\" because a general IO error occurred. Please check that your target is writable."
581 );
582
583 $this->subject->delete($path);
584 }
585
586 #[Test]
587
589 {
590 $path = '/path/to/your/file';
591
592 $this->filesystemMock->shouldReceive('delete')
593 ->once()
594 ->with($path)
595 ->andThrow(UnableToRetrieveMetadata::class);
596
597 $this->expectException(FileNotFoundException::class);
598 $this->expectExceptionMessage("File \"$path\" was not found delete operation failed.");
599
600 $this->subject->delete($path);
601 }
602
603 #[Test]
604
606 {
607 $path = '/path/to/your/file';
608 $content = "awesome content";
609
610 //partially mock the subject to intercept the method calls of the own object.
611 $this->subject = Mockery::mock(FlySystemFileAccess::class, [$this->filesystemMock])->makePartial();
612
613 $this->subject
614 ->shouldReceive('read')
615 ->once()
616 ->with($path)
617 ->andReturn($content)
618 ->getMock()
619 ->shouldReceive('delete')
620 ->once()
621 ->with($path);
622
623 $this->subject->readAndDelete($path);
624 }
625
626 #[Test]
627
628 public function testRenameWhichShouldSucceed(): void
629 {
630 $source = '/source/path';
631 $destination = '/dest/path';
632
633 $this->filesystemMock
634 ->shouldReceive('has')
635 ->once()
636 ->with($destination)
637 ->andReturn(false)
638 ->getMock()
639 ->shouldReceive('move')
640 ->once()
641 ->withArgs([$source, $destination])
642 ->andReturn(true);
643
644 $this->subject->rename($source, $destination);
645 }
646
647 #[Test]
648
650 {
651 $source = '/source/path';
652 $destination = '/dest/path';
653
654 $this->filesystemMock
655 ->shouldReceive('has')
656 ->once()
657 ->with($destination)
658 ->andReturn(false)
659 ->getMock()
660 ->shouldReceive('move')
661 ->once()
662 ->withArgs([$source, $destination])
663 ->andThrow(UnableToRetrieveMetadata::class);
664
665 $this->expectException(FileNotFoundException::class);
666 $this->expectExceptionMessage("File \"$source\" not found.");
667
668 $this->subject->rename($source, $destination);
669 }
670
671 #[Test]
672
674 {
675 $source = '/source/path';
676 $destination = '/dest/path';
677
678 $this->filesystemMock
679 ->shouldReceive('has')
680 ->once()
681 ->with($destination)
682 ->andReturn(true)
683 ->getMock()
684 ->shouldReceive('move')
685 ->never()
686 ->withArgs([$source, $destination])
687 ->andThrow(UnableToMoveFile::class);
688
689 $this->expectException(IOException::class);
690 $this->expectExceptionMessage("File \"$destination\" already exists.");
691
692 $this->subject->rename($source, $destination);
693 }
694
695 #[Test]
696
698 {
699 $source = '/source/path';
700 $destination = '/dest/path';
701
702 $this->filesystemMock
703 ->shouldReceive('has')
704 ->once()
705 ->with($destination)
706 ->andReturn(false)
707 ->getMock()
708 ->shouldReceive('move')
709 ->once()
710 ->withArgs([$source, $destination])
711 ->andThrow(UnableToMoveFile::class);
712
713 $this->expectException(IOException::class);
714 $this->expectExceptionMessage("Could not move file from \"$source\" to \"$destination\".");
715
716 $this->subject->rename($source, $destination);
717 }
718
719 #[Test]
720
721 public function testCopyWhichShouldSucceed(): void
722 {
723 $sourcePath = '/path/to/your/source/file';
724 $destinationPath = '/path/to/your/destination/file';
725
726 $this->filesystemMock
727 ->shouldReceive('has')
728 ->once()
729 ->with($destinationPath)
730 ->andReturn(false)
731 ->getMock()
732 ->shouldReceive('copy')
733 ->once()
734 ->withArgs([$sourcePath, $destinationPath])
735 ->andReturn(true);
736
737 $this->subject->copy($sourcePath, $destinationPath);
738 }
739
740 #[Test]
741
743 {
744 $sourcePath = '/path/to/your/source/file';
745 $destinationPath = '/path/to/your/destination/file';
746
747 $this->filesystemMock
748 ->shouldReceive('has')
749 ->once()
750 ->with($destinationPath)
751 ->andReturn(false)
752 ->getMock()
753 ->shouldReceive('copy')
754 ->once()
755 ->withArgs([$sourcePath, $destinationPath])
756 ->andThrow(UnableToCopyFile::class);
757
758 $this->expectException(IOException::class);
759 $this->expectExceptionMessage(
760 "Could not copy file \"$sourcePath\" to destination \"$destinationPath\" because a general IO error occurred. Please check that your destination is writable."
761 );
762
763 $this->subject->copy($sourcePath, $destinationPath);
764 }
765
766 #[Test]
767
769 {
770 $sourcePath = '/path/to/your/source/file';
771 $destinationPath = '/path/to/your/destination/file';
772
773 $this->filesystemMock
774 ->shouldReceive('has')
775 ->once()
776 ->with($destinationPath)
777 ->andReturn(false)
778 ->getMock()
779 ->shouldReceive('copy')
780 ->once()
781 ->withArgs([$sourcePath, $destinationPath])
782 ->andThrow(UnableToRetrieveMetadata::class);
783
784 $this->expectException(FileNotFoundException::class);
785 $this->expectExceptionMessage("File source \"$sourcePath\" was not found copy failed.");
786
787 $this->subject->copy($sourcePath, $destinationPath);
788 }
789
790 #[Test]
791
793 {
794 $sourcePath = '/path/to/your/source/file';
795 $destinationPath = '/path/to/your/destination/file';
796
797 $this->filesystemMock
798 ->shouldReceive('has')
799 ->once()
800 ->with($destinationPath)
801 ->andReturn(true)
802 ->getMock()
803 ->shouldReceive('copy')
804 ->never()
805 ->withArgs([$sourcePath, $destinationPath])
806 ->andThrow(UnableToCopyFile::class);
807
808 $this->expectException(FileAlreadyExistsException::class);
809 $this->expectExceptionMessage("File \"$destinationPath\" already exists.");
810
811 $this->subject->copy($sourcePath, $destinationPath);
812 }
813}
$datetime
foreach($mandatory_scripts as $file) $timestamp
Definition: buildRTE.php:70
This class provides the data size with additional information to remove the work to calculate the siz...
Definition: DataSize.php:31
Indicates that a file is missing or not found.
Indicates general problems with the input or output operations.
Definition: IOException.php:28
setUp()
Sets up the fixture, for example, open a network connection.
The filesystem interface provides the public interface for the Filesystem service API consumer.
Definition: Filesystem.php:37
$path
Definition: ltiservices.php:30
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...