/Tests/Binary/Loader/FileSystemLoaderTest.php

https://github.com/liip/LiipImagineBundle · PHP · 247 lines · 164 code · 34 blank · 49 comment · 1 complexity · 18384b630992b030812ab1ce0f4f18d2 MD5 · raw file

  1. <?php
  2. /*
  3. * This file is part of the `liip/LiipImagineBundle` project.
  4. *
  5. * (c) https://github.com/liip/LiipImagineBundle/graphs/contributors
  6. *
  7. * For the full copyright and license information, please view the LICENSE.md
  8. * file that was distributed with this source code.
  9. */
  10. namespace Liip\ImagineBundle\Tests\Binary\Loader;
  11. use Liip\ImagineBundle\Binary\Loader\FileSystemLoader;
  12. use Liip\ImagineBundle\Binary\Loader\LoaderInterface;
  13. use Liip\ImagineBundle\Binary\Locator\FileSystemLocator;
  14. use Liip\ImagineBundle\Binary\Locator\LocatorInterface;
  15. use Liip\ImagineBundle\Model\FileBinary;
  16. use PHPUnit\Framework\TestCase;
  17. use Symfony\Component\HttpFoundation\File\MimeType\ExtensionGuesser;
  18. use Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesser;
  19. use Symfony\Component\Mime\MimeTypeGuesserInterface;
  20. use Symfony\Component\Mime\MimeTypes;
  21. /**
  22. * @covers \Liip\ImagineBundle\Binary\Loader\FileSystemLoader
  23. */
  24. class FileSystemLoaderTest extends TestCase
  25. {
  26. public function testConstruction(): void
  27. {
  28. $loader = $this->getFileSystemLoader();
  29. $this->assertInstanceOf(FileSystemLoader::class, $loader);
  30. }
  31. /**
  32. * @dataProvider provideMultipleWrongArgumentsConstructorCases
  33. *
  34. * @param $expectedMessage
  35. * @param $mimeGuesser
  36. * @param $extensionGuesser
  37. */
  38. public function testThrowsIfConstructedWithWrongTypeArguments($expectedMessage, $mimeGuesser, $extensionGuesser): void
  39. {
  40. $this->expectException(\Liip\ImagineBundle\Exception\InvalidArgumentException::class);
  41. $this->expectExceptionMessage($expectedMessage);
  42. new FileSystemLoader(
  43. $mimeGuesser,
  44. $extensionGuesser,
  45. $this->getFileSystemLocator($this->getDefaultDataRoots())
  46. );
  47. }
  48. /**
  49. * @return string[][]
  50. */
  51. public static function provideMultipleWrongArgumentsConstructorCases(): array
  52. {
  53. return [
  54. [
  55. '$mimeGuesser must be an instance of Symfony\Component\Mime\MimeTypeGuesserInterface or Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesserInterface',
  56. 'foo',
  57. 'bar',
  58. ],
  59. [
  60. '$extensionGuesser must be an instance of Symfony\Component\Mime\MimeTypesInterface or Symfony\Component\HttpFoundation\File\MimeType\ExtensionGuesserInterface',
  61. class_exists(MimeTypes::class) ? MimeTypes::getDefault() : MimeTypeGuesser::getInstance(),
  62. 'bar',
  63. ],
  64. ];
  65. }
  66. public function testImplementsLoaderInterface(): void
  67. {
  68. $this->assertInstanceOf(LoaderInterface::class, $this->getFileSystemLoader());
  69. }
  70. /**
  71. * @return array[]
  72. */
  73. public static function provideLoadCases(): array
  74. {
  75. $file = pathinfo(__FILE__, PATHINFO_BASENAME);
  76. return [
  77. [
  78. __DIR__,
  79. $file,
  80. ],
  81. [
  82. __DIR__.'/',
  83. $file,
  84. ],
  85. [
  86. __DIR__, '/'.
  87. $file,
  88. ],
  89. [
  90. __DIR__.'/../../Binary/Loader',
  91. '/'.$file,
  92. ],
  93. [
  94. realpath(__DIR__.'/..'),
  95. 'Loader/'.$file,
  96. ],
  97. [
  98. __DIR__.'/../',
  99. '/Loader/../../Binary/Loader/'.$file,
  100. ],
  101. ];
  102. }
  103. /**
  104. * @dataProvider provideLoadCases
  105. */
  106. public function testLoad(string $root, string $path): void
  107. {
  108. $this->assertValidLoaderFindReturn($this->getFileSystemLoader([$root])->find($path));
  109. }
  110. /**
  111. * @return string[][]
  112. */
  113. public static function provideMultipleRootLoadCases(): array
  114. {
  115. $pathsPrepended = [
  116. realpath(__DIR__.'/../'),
  117. realpath(__DIR__.'/../../'),
  118. realpath(__DIR__.'/../../../'),
  119. ];
  120. return array_map(function ($parameters) use ($pathsPrepended) {
  121. return [[$pathsPrepended[mt_rand(0, \count($pathsPrepended) - 1)], $parameters[0]], $parameters[1]];
  122. }, static::provideLoadCases());
  123. }
  124. /**
  125. * @dataProvider provideMultipleRootLoadCases
  126. *
  127. * @param string[] $roots
  128. */
  129. public function testMultipleRootLoadCases(array $roots, string $path): void
  130. {
  131. $this->assertValidLoaderFindReturn($this->getFileSystemLoader($roots)->find($path));
  132. }
  133. public function testAllowsEmptyRootPath(): void
  134. {
  135. $loader = $this->getFileSystemLoader([]);
  136. $this->assertInstanceOf(FileSystemLoader::class, $loader);
  137. }
  138. public function testThrowsIfRootPathDoesNotExist(): void
  139. {
  140. $this->expectException(\Liip\ImagineBundle\Exception\InvalidArgumentException::class);
  141. $this->expectExceptionMessage('Root image path not resolvable');
  142. $loader = $this->getFileSystemLoader(['/a/bad/root/path']);
  143. $this->assertInstanceOf(FileSystemLoader::class, $loader);
  144. }
  145. /**
  146. * @return array[]
  147. */
  148. public function provideOutsideRootPathsData(): array
  149. {
  150. return [
  151. ['../Loader/../../Binary/Loader/../../../Resources/config/routing.yaml'],
  152. ['../../Binary/'],
  153. ];
  154. }
  155. /**
  156. * @dataProvider provideOutsideRootPathsData
  157. *
  158. * @param string $path
  159. */
  160. public function testThrowsIfRealPathOutsideRootPath($path): void
  161. {
  162. $this->expectException(\Liip\ImagineBundle\Exception\Binary\Loader\NotLoadableException::class);
  163. $this->expectExceptionMessage('Source image invalid');
  164. $loader = $this->getFileSystemLoader()->find($path);
  165. $this->assertInstanceOf(FileSystemLoader::class, $loader);
  166. }
  167. public function testPathWithDoublePeriodBackStep(): void
  168. {
  169. $this->assertValidLoaderFindReturn($this->getFileSystemLoader()->find('/../../Binary/Loader/'.pathinfo(__FILE__, PATHINFO_BASENAME)));
  170. }
  171. public function testThrowsIfFileDoesNotExist(): void
  172. {
  173. $this->expectException(\Liip\ImagineBundle\Exception\Binary\Loader\NotLoadableException::class);
  174. $this->expectExceptionMessage('Source image not resolvable');
  175. $loader = $this->getFileSystemLoader()->find('fileNotExist');
  176. $this->assertInstanceOf(FileSystemLoader::class, $loader);
  177. }
  178. /**
  179. * @param string[] $roots
  180. */
  181. private function getFileSystemLocator(array $roots): FileSystemLocator
  182. {
  183. return new FileSystemLocator($roots);
  184. }
  185. /**
  186. * @return string[]
  187. */
  188. private function getDefaultDataRoots(): array
  189. {
  190. return [__DIR__];
  191. }
  192. private function getFileSystemLoader(array $roots = [], LocatorInterface $locator = null): FileSystemLoader
  193. {
  194. if (interface_exists(MimeTypeGuesserInterface::class)) {
  195. $mimeTypes = MimeTypes::getDefault();
  196. return new FileSystemLoader(
  197. $mimeTypes,
  198. $mimeTypes,
  199. $locator ?? $this->getFileSystemLocator(\count($roots) ? $roots : $this->getDefaultDataRoots())
  200. );
  201. }
  202. return new FileSystemLoader(
  203. MimeTypeGuesser::getInstance(),
  204. ExtensionGuesser::getInstance(),
  205. $locator ?? $this->getFileSystemLocator(\count($roots) ? $roots : $this->getDefaultDataRoots())
  206. );
  207. }
  208. private function assertValidLoaderFindReturn(FileBinary $return, string $message = ''): void
  209. {
  210. $this->assertInstanceOf(FileBinary::class, $return, $message);
  211. $this->assertStringStartsWith('text/', $return->getMimeType(), $message);
  212. }
  213. }