PageRenderTime 56ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/src/Symfony/Component/Validator/Tests/Constraints/FileValidatorTest.php

https://github.com/bbt123/symfony
PHP | 378 lines | 282 code | 65 blank | 31 comment | 3 complexity | 190b9abbe038ab4cd3dcee135663c833 MD5 | raw file
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Component\Validator\Tests\Constraints;
  11. use Symfony\Component\HttpFoundation\File\UploadedFile;
  12. use Symfony\Component\Validator\Constraints\File;
  13. use Symfony\Component\Validator\Constraints\FileValidator;
  14. abstract class FileValidatorTest extends \PHPUnit_Framework_TestCase
  15. {
  16. protected $context;
  17. protected $validator;
  18. protected $path;
  19. protected $file;
  20. protected function setUp()
  21. {
  22. $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
  23. $this->validator = new FileValidator();
  24. $this->validator->initialize($this->context);
  25. $this->path = sys_get_temp_dir().DIRECTORY_SEPARATOR.'FileValidatorTest';
  26. $this->file = fopen($this->path, 'w');
  27. }
  28. protected function tearDown()
  29. {
  30. if (is_resource($this->file)) {
  31. fclose($this->file);
  32. }
  33. if (file_exists($this->path)) {
  34. unlink($this->path);
  35. }
  36. $this->context = null;
  37. $this->validator = null;
  38. $this->path = null;
  39. $this->file = null;
  40. }
  41. public function testNullIsValid()
  42. {
  43. $this->context->expects($this->never())
  44. ->method('addViolation');
  45. $this->validator->validate(null, new File());
  46. }
  47. public function testEmptyStringIsValid()
  48. {
  49. $this->context->expects($this->never())
  50. ->method('addViolation');
  51. $this->validator->validate('', new File());
  52. }
  53. /**
  54. * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException
  55. */
  56. public function testExpectsStringCompatibleTypeOrFile()
  57. {
  58. $this->validator->validate(new \stdClass(), new File());
  59. }
  60. public function testValidFile()
  61. {
  62. $this->context->expects($this->never())
  63. ->method('addViolation');
  64. $this->validator->validate($this->path, new File());
  65. }
  66. public function testValidUploadedfile()
  67. {
  68. $this->context->expects($this->never())
  69. ->method('addViolation');
  70. $file = new UploadedFile($this->path, 'originalName', null, null, null, true);
  71. $this->validator->validate($file, new File());
  72. }
  73. public function provideMaxSizeExceededTests()
  74. {
  75. return array(
  76. array(11, 10, '11', '10', 'bytes'),
  77. array(ceil(1.005*1000), ceil(1.005*1000) - 1, '1005', '1004', 'bytes'),
  78. array(ceil(1.005*1000*1000), ceil(1.005*1000*1000) - 1, '1005000', '1004999', 'bytes'),
  79. // round(size) == 1.01kB, limit == 1kB
  80. array(ceil(1.005*1000), 1000, '1.01', '1', 'kB'),
  81. array(ceil(1.005*1000), '1k', '1.01', '1', 'kB'),
  82. // round(size) == 1kB, limit == 1kB -> use bytes
  83. array(ceil(1.004*1000), 1000, '1004', '1000', 'bytes'),
  84. array(ceil(1.004*1000), '1k', '1004', '1000', 'bytes'),
  85. array(1000 + 1, 1000, '1001', '1000', 'bytes'),
  86. array(1000 + 1, '1k', '1001', '1000', 'bytes'),
  87. // round(size) == 1.01MB, limit == 1MB
  88. array(ceil(1.005*1000*1000), 1000*1000, '1.01', '1', 'MB'),
  89. array(ceil(1.005*1000*1000), '1000k', '1.01', '1', 'MB'),
  90. array(ceil(1.005*1000*1000), '1M', '1.01', '1', 'MB'),
  91. // round(size) == 1MB, limit == 1MB -> use kB
  92. array(ceil(1.004*1000*1000), 1000*1000, '1004', '1000', 'kB'),
  93. array(ceil(1.004*1000*1000), '1000k', '1004', '1000', 'kB'),
  94. array(ceil(1.004*1000*1000), '1M', '1004', '1000', 'kB'),
  95. array(1000*1000 + 1, 1000*1000, '1000001', '1000000', 'bytes'),
  96. array(1000*1000 + 1, '1000k', '1000001', '1000000', 'bytes'),
  97. array(1000*1000 + 1, '1M', '1000001', '1000000', 'bytes'),
  98. );
  99. }
  100. /**
  101. * @dataProvider provideMaxSizeExceededTests
  102. */
  103. public function testMaxSizeExceeded($bytesWritten, $limit, $sizeAsString, $limitAsString, $suffix)
  104. {
  105. fseek($this->file, $bytesWritten-1, SEEK_SET);
  106. fwrite($this->file, '0');
  107. fclose($this->file);
  108. $constraint = new File(array(
  109. 'maxSize' => $limit,
  110. 'maxSizeMessage' => 'myMessage',
  111. ));
  112. $this->context->expects($this->once())
  113. ->method('addViolation')
  114. ->with('myMessage', array(
  115. '{{ limit }}' => $limitAsString,
  116. '{{ size }}' => $sizeAsString,
  117. '{{ suffix }}' => $suffix,
  118. '{{ file }}' => $this->path,
  119. ));
  120. $this->validator->validate($this->getFile($this->path), $constraint);
  121. }
  122. public function provideMaxSizeNotExceededTests()
  123. {
  124. return array(
  125. array(10, 10),
  126. array(9, 10),
  127. array(1000, '1k'),
  128. array(1000 - 1, '1k'),
  129. array(1000*1000, '1M'),
  130. array(1000*1000 - 1, '1M'),
  131. );
  132. }
  133. /**
  134. * @dataProvider provideMaxSizeNotExceededTests
  135. */
  136. public function testMaxSizeNotExceeded($bytesWritten, $limit)
  137. {
  138. fseek($this->file, $bytesWritten-1, SEEK_SET);
  139. fwrite($this->file, '0');
  140. fclose($this->file);
  141. $constraint = new File(array(
  142. 'maxSize' => $limit,
  143. 'maxSizeMessage' => 'myMessage',
  144. ));
  145. $this->context->expects($this->never())
  146. ->method('addViolation');
  147. $this->validator->validate($this->getFile($this->path), $constraint);
  148. }
  149. /**
  150. * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
  151. */
  152. public function testInvalidMaxSize()
  153. {
  154. $constraint = new File(array(
  155. 'maxSize' => '1abc',
  156. ));
  157. $this->validator->validate($this->path, $constraint);
  158. }
  159. public function testValidMimeType()
  160. {
  161. $file = $this
  162. ->getMockBuilder('Symfony\Component\HttpFoundation\File\File')
  163. ->disableOriginalConstructor()
  164. ->getMock()
  165. ;
  166. $file
  167. ->expects($this->once())
  168. ->method('getPathname')
  169. ->will($this->returnValue($this->path))
  170. ;
  171. $file
  172. ->expects($this->once())
  173. ->method('getMimeType')
  174. ->will($this->returnValue('image/jpg'))
  175. ;
  176. $this->context->expects($this->never())
  177. ->method('addViolation');
  178. $constraint = new File(array(
  179. 'mimeTypes' => array('image/png', 'image/jpg'),
  180. ));
  181. $this->validator->validate($file, $constraint);
  182. }
  183. public function testValidWildcardMimeType()
  184. {
  185. $file = $this
  186. ->getMockBuilder('Symfony\Component\HttpFoundation\File\File')
  187. ->disableOriginalConstructor()
  188. ->getMock()
  189. ;
  190. $file
  191. ->expects($this->once())
  192. ->method('getPathname')
  193. ->will($this->returnValue($this->path))
  194. ;
  195. $file
  196. ->expects($this->once())
  197. ->method('getMimeType')
  198. ->will($this->returnValue('image/jpg'))
  199. ;
  200. $this->context->expects($this->never())
  201. ->method('addViolation');
  202. $constraint = new File(array(
  203. 'mimeTypes' => array('image/*'),
  204. ));
  205. $this->validator->validate($file, $constraint);
  206. }
  207. public function testInvalidMimeType()
  208. {
  209. $file = $this
  210. ->getMockBuilder('Symfony\Component\HttpFoundation\File\File')
  211. ->disableOriginalConstructor()
  212. ->getMock()
  213. ;
  214. $file
  215. ->expects($this->once())
  216. ->method('getPathname')
  217. ->will($this->returnValue($this->path))
  218. ;
  219. $file
  220. ->expects($this->once())
  221. ->method('getMimeType')
  222. ->will($this->returnValue('application/pdf'))
  223. ;
  224. $constraint = new File(array(
  225. 'mimeTypes' => array('image/png', 'image/jpg'),
  226. 'mimeTypesMessage' => 'myMessage',
  227. ));
  228. $this->context->expects($this->once())
  229. ->method('addViolation')
  230. ->with('myMessage', array(
  231. '{{ type }}' => '"application/pdf"',
  232. '{{ types }}' => '"image/png", "image/jpg"',
  233. '{{ file }}' => $this->path,
  234. ));
  235. $this->validator->validate($file, $constraint);
  236. }
  237. public function testInvalidWildcardMimeType()
  238. {
  239. $file = $this
  240. ->getMockBuilder('Symfony\Component\HttpFoundation\File\File')
  241. ->disableOriginalConstructor()
  242. ->getMock()
  243. ;
  244. $file
  245. ->expects($this->once())
  246. ->method('getPathname')
  247. ->will($this->returnValue($this->path))
  248. ;
  249. $file
  250. ->expects($this->once())
  251. ->method('getMimeType')
  252. ->will($this->returnValue('application/pdf'))
  253. ;
  254. $constraint = new File(array(
  255. 'mimeTypes' => array('image/*', 'image/jpg'),
  256. 'mimeTypesMessage' => 'myMessage',
  257. ));
  258. $this->context->expects($this->once())
  259. ->method('addViolation')
  260. ->with('myMessage', array(
  261. '{{ type }}' => '"application/pdf"',
  262. '{{ types }}' => '"image/*", "image/jpg"',
  263. '{{ file }}' => $this->path,
  264. ));
  265. $this->validator->validate($file, $constraint);
  266. }
  267. /**
  268. * @dataProvider uploadedFileErrorProvider
  269. */
  270. public function testUploadedFileError($error, $message, array $params = array(), $maxSize = null)
  271. {
  272. $file = new UploadedFile('/path/to/file', 'originalName', 'mime', 0, $error);
  273. $constraint = new File(array(
  274. $message => 'myMessage',
  275. 'maxSize' => $maxSize
  276. ));
  277. $this->context->expects($this->once())
  278. ->method('addViolation')
  279. ->with('myMessage', $params);
  280. $this->validator->validate($file, $constraint);
  281. }
  282. public function uploadedFileErrorProvider()
  283. {
  284. $tests = array(
  285. array(UPLOAD_ERR_FORM_SIZE, 'uploadFormSizeErrorMessage'),
  286. array(UPLOAD_ERR_PARTIAL, 'uploadPartialErrorMessage'),
  287. array(UPLOAD_ERR_NO_FILE, 'uploadNoFileErrorMessage'),
  288. array(UPLOAD_ERR_NO_TMP_DIR, 'uploadNoTmpDirErrorMessage'),
  289. array(UPLOAD_ERR_CANT_WRITE, 'uploadCantWriteErrorMessage'),
  290. array(UPLOAD_ERR_EXTENSION, 'uploadExtensionErrorMessage'),
  291. );
  292. if (class_exists('Symfony\Component\HttpFoundation\File\UploadedFile')) {
  293. // when no maxSize is specified on constraint, it should use the ini value
  294. $tests[] = array(UPLOAD_ERR_INI_SIZE, 'uploadIniSizeErrorMessage', array(
  295. '{{ limit }}' => UploadedFile::getMaxFilesize(),
  296. '{{ suffix }}' => 'bytes',
  297. ));
  298. // it should use the smaller limitation (maxSize option in this case)
  299. $tests[] = array(UPLOAD_ERR_INI_SIZE, 'uploadIniSizeErrorMessage', array(
  300. '{{ limit }}' => 1,
  301. '{{ suffix }}' => 'bytes',
  302. ), '1');
  303. // it correctly parses the maxSize option and not only uses simple string comparison
  304. // 1000M should be bigger than the ini value
  305. $tests[] = array(UPLOAD_ERR_INI_SIZE, 'uploadIniSizeErrorMessage', array(
  306. '{{ limit }}' => UploadedFile::getMaxFilesize(),
  307. '{{ suffix }}' => 'bytes',
  308. ), '1000M');
  309. }
  310. return $tests;
  311. }
  312. abstract protected function getFile($filename);
  313. }