[FEATURE] Introduce Request/Response based on PSR-7
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Tests / Unit / Http / UploadedFileTest.php
1 <?php
2 namespace TYPO3\CMS\Core\Tests\Unit\Http;
3
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 use TYPO3\CMS\Core\Http\Stream;
18 use TYPO3\CMS\Core\Http\UploadedFile;
19 use TYPO3\CMS\Core\Utility\GeneralUtility;
20
21 /**
22 * Testcase for \TYPO3\CMS\Core\Http\UploadedFile
23 *
24 * Adapted from https://github.com/phly/http/
25 */
26 class UploadedFileTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
27
28 protected $tmpFile;
29
30 public function setUp() {
31 $this->tmpfile = NULL;
32 }
33
34 public function tearDown() {
35 if (is_scalar($this->tmpFile) && file_exists($this->tmpFile)) {
36 unlink($this->tmpFile);
37 }
38 }
39
40 /**
41 * @return array
42 */
43 public function invalidStreamsDataProvider() {
44 return [
45 'null' => [NULL],
46 'true' => [TRUE],
47 'false' => [FALSE],
48 'int' => [1],
49 'float' => [1.1],
50 /* Have not figured out a valid way to test an invalid path yet; null byte injection
51 * appears to get caught by fopen()
52 'invalid-path' => [ ('WIN' === strtoupper(substr(PHP_OS, 0, 3))) ? '[:]' : 'foo' . chr(0) ],
53 */
54 'array' => [['filename']],
55 'object' => [(object) ['filename']],
56 ];
57 }
58
59 /**
60 * @dataProvider invalidStreamsDataProvider
61 * @test
62 */
63 public function constructorRaisesExceptionOnInvalidStreamOrFile($streamOrFile) {
64 $this->setExpectedException('InvalidArgumentException');
65 new UploadedFile($streamOrFile, 0, UPLOAD_ERR_OK);
66 }
67
68 /**
69 * @return array
70 */
71 public function invalidSizesDataProvider() {
72 return [
73 'null' => [NULL],
74 'true' => [TRUE],
75 'false' => [FALSE],
76 'float' => [1.1],
77 'string' => ['1'],
78 'array' => [[1]],
79 'object' => [(object) [1]],
80 ];
81 }
82
83 /**
84 * @dataProvider invalidSizesDataProvider
85 * @test
86 */
87 public function constructorRaisesExceptionOnInvalidSize($size) {
88 $this->setExpectedException('InvalidArgumentException', 'size');
89 new UploadedFile(fopen('php://temp', 'wb+'), $size, UPLOAD_ERR_OK);
90 }
91
92 /**
93 * @return array
94 */
95 public function invalidErrorStatusesDataProvider() {
96 return [
97 'null' => [NULL],
98 'true' => [TRUE],
99 'false' => [FALSE],
100 'float' => [1.1],
101 'string' => ['1'],
102 'array' => [[1]],
103 'object' => [(object) [1]],
104 'negative' => [-1],
105 'too-big' => [9],
106 ];
107 }
108
109 /**
110 * @dataProvider invalidErrorStatusesDataProvider
111 * @test
112 */
113 public function constructorRaisesExceptionOnInvalidErrorStatus($status) {
114 $this->setExpectedException('InvalidArgumentException', 'status');
115 new UploadedFile(fopen('php://temp', 'wb+'), 0, $status);
116 }
117
118 /**
119 * @return array
120 */
121 public function invalidFilenamesAndMediaTypesDataProvider() {
122 return [
123 'true' => [TRUE],
124 'false' => [FALSE],
125 'int' => [1],
126 'float' => [1.1],
127 'array' => [['string']],
128 'object' => [(object) ['string']],
129 ];
130 }
131
132 /**
133 * @dataProvider invalidFilenamesAndMediaTypesDataProvider
134 * @test
135 */
136 public function constructorRaisesExceptionOnInvalidClientFilename($filename) {
137 $this->setExpectedException('InvalidArgumentException', 'filename');
138 new UploadedFile(fopen('php://temp', 'wb+'), 0, UPLOAD_ERR_OK, $filename);
139 }
140
141 /**
142 * @dataProvider invalidFilenamesAndMediaTypesDataProvider
143 * @test
144 */
145 public function constructorRaisesExceptionOnInvalidClientMediaType($mediaType) {
146 $this->setExpectedException('InvalidArgumentException', 'media type');
147 new UploadedFile(fopen('php://temp', 'wb+'), 0, UPLOAD_ERR_OK, 'foobar.baz', $mediaType);
148 }
149
150 /**
151 * @test
152 */
153 public function getStreamReturnsOriginalStreamObject() {
154 $stream = new Stream('php://temp');
155 $upload = new UploadedFile($stream, 0, UPLOAD_ERR_OK);
156 $this->assertSame($stream, $upload->getStream());
157 }
158
159 /**
160 * @test
161 */
162 public function getStreamReturnsWrappedPhpStream() {
163 $stream = fopen('php://temp', 'wb+');
164 $upload = new UploadedFile($stream, 0, UPLOAD_ERR_OK);
165 $uploadStream = $upload->getStream()->detach();
166 $this->assertSame($stream, $uploadStream);
167 }
168
169 /**
170 * @test
171 */
172 public function getStreamReturnsStreamForFile() {
173 $this->tmpFile = $stream = tempnam(sys_get_temp_dir(), 'phly');
174 $upload = new UploadedFile($stream, 0, UPLOAD_ERR_OK);
175 $uploadStream = $upload->getStream();
176 $r = new \ReflectionProperty($uploadStream, 'stream');
177 $r->setAccessible(TRUE);
178 $this->assertSame($stream, $r->getValue($uploadStream));
179 }
180
181 /**
182 * @test
183 */
184 public function moveToMovesFileToDesignatedPath() {
185 $stream = new Stream('php://temp', 'wb+');
186 $stream->write('Foo bar!');
187 $upload = new UploadedFile($stream, 0, UPLOAD_ERR_OK);
188
189 $this->tmpFile = $to = GeneralUtility::tempnam('psr7');
190 $upload->moveTo($to);
191 $this->assertTrue(file_exists($to));
192 $contents = file_get_contents($to);
193 $this->assertEquals($stream->__toString(), $contents);
194 }
195
196 /**
197 * @return array
198 */
199 public function invalidMovePathsDataProvider() {
200 return [
201 'null' => [NULL],
202 'true' => [TRUE],
203 'false' => [FALSE],
204 'int' => [1],
205 'float' => [1.1],
206 'empty' => [''],
207 'array' => [['filename']],
208 'object' => [(object) ['filename']],
209 ];
210 }
211
212 /**
213 * @dataProvider invalidMovePathsDataProvider
214 * @test
215 */
216 public function moveToRaisesExceptionForInvalidPath($path) {
217 $stream = new Stream('php://temp', 'wb+');
218 $stream->write('Foo bar!');
219 $upload = new UploadedFile($stream, 0, UPLOAD_ERR_OK);
220
221 $this->tmpFile = $path;
222 $this->setExpectedException('InvalidArgumentException', 'path');
223 $upload->moveTo($path);
224 }
225
226 /**
227 * @test
228 */
229 public function moveToCannotBeCalledMoreThanOnce() {
230 $stream = new Stream('php://temp', 'wb+');
231 $stream->write('Foo bar!');
232 $upload = new UploadedFile($stream, 0, UPLOAD_ERR_OK);
233
234 $this->tmpFile = $to = GeneralUtility::tempnam('psr7');
235 $upload->moveTo($to);
236 $this->assertTrue(file_exists($to));
237
238 $this->setExpectedException('RuntimeException', 'moved');
239 $upload->moveTo($to);
240 }
241
242 /**
243 * @test
244 */
245 public function getGetStreamRaisesExceptionAfterMove() {
246 $stream = new Stream('php://temp', 'wb+');
247 $stream->write('Foo bar!');
248 $upload = new UploadedFile($stream, 0, UPLOAD_ERR_OK);
249
250 $this->tmpFile = $to = GeneralUtility::tempnam('psr7');
251 $upload->moveTo($to);
252 $this->assertTrue(file_exists($to));
253
254 $this->setExpectedException('RuntimeException', 'moved');
255 $upload->getStream();
256 }
257
258 }