|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
namespace Tests\Nyholm\Psr7; |
|
4
|
|
|
|
|
5
|
|
|
use Nyholm\Psr7\Stream; |
|
6
|
|
|
use Nyholm\Psr7\UploadedFile; |
|
7
|
|
|
use PHPUnit\Framework\TestCase; |
|
8
|
|
|
|
|
9
|
|
|
/** |
|
10
|
|
|
* @covers \Nyholm\Psr7\UploadedFile |
|
11
|
|
|
*/ |
|
12
|
|
|
class UploadedFileTest extends TestCase |
|
13
|
|
|
{ |
|
14
|
|
|
protected $cleanup; |
|
15
|
|
|
|
|
16
|
|
|
public function setUp() |
|
17
|
|
|
{ |
|
18
|
|
|
$this->cleanup = []; |
|
19
|
|
|
} |
|
20
|
|
|
|
|
21
|
|
|
public function tearDown() |
|
22
|
|
|
{ |
|
23
|
|
|
foreach ($this->cleanup as $file) { |
|
24
|
|
|
if (is_scalar($file) && file_exists($file)) { |
|
25
|
|
|
unlink($file); |
|
26
|
|
|
} |
|
27
|
|
|
} |
|
28
|
|
|
} |
|
29
|
|
|
|
|
30
|
|
View Code Duplication |
public function invalidStreams() |
|
|
|
|
|
|
31
|
|
|
{ |
|
32
|
|
|
return [ |
|
33
|
|
|
'null' => [null], |
|
34
|
|
|
'true' => [true], |
|
35
|
|
|
'false' => [false], |
|
36
|
|
|
'int' => [1], |
|
37
|
|
|
'float' => [1.1], |
|
38
|
|
|
'array' => [['filename']], |
|
39
|
|
|
'object' => [(object) ['filename']], |
|
40
|
|
|
]; |
|
41
|
|
|
} |
|
42
|
|
|
|
|
43
|
|
|
/** |
|
44
|
|
|
* @dataProvider invalidStreams |
|
45
|
|
|
*/ |
|
46
|
|
|
public function testRaisesExceptionOnInvalidStreamOrFile($streamOrFile) |
|
47
|
|
|
{ |
|
48
|
|
|
$this->expectException(\InvalidArgumentException::class); |
|
49
|
|
|
$this->expectExceptionMessage('Invalid stream or file provided for UploadedFile'); |
|
50
|
|
|
|
|
51
|
|
|
new UploadedFile($streamOrFile, 0, UPLOAD_ERR_OK); |
|
52
|
|
|
} |
|
53
|
|
|
|
|
54
|
|
|
public function invalidErrorStatuses() |
|
55
|
|
|
{ |
|
56
|
|
|
return [ |
|
57
|
|
|
'null' => [null], |
|
58
|
|
|
'true' => [true], |
|
59
|
|
|
'false' => [false], |
|
60
|
|
|
'float' => [1.1], |
|
61
|
|
|
'string' => ['1'], |
|
62
|
|
|
'array' => [[1]], |
|
63
|
|
|
'object' => [(object) [1]], |
|
64
|
|
|
'negative' => [-1], |
|
65
|
|
|
'too-big' => [9], |
|
66
|
|
|
]; |
|
67
|
|
|
} |
|
68
|
|
|
|
|
69
|
|
|
/** |
|
70
|
|
|
* @dataProvider invalidErrorStatuses |
|
71
|
|
|
*/ |
|
72
|
|
|
public function testRaisesExceptionOnInvalidErrorStatus($status) |
|
73
|
|
|
{ |
|
74
|
|
|
$this->expectException(\InvalidArgumentException::class); |
|
75
|
|
|
$this->expectExceptionMessage('status'); |
|
76
|
|
|
|
|
77
|
|
|
new UploadedFile(fopen('php://temp', 'wb+'), 0, $status); |
|
78
|
|
|
} |
|
79
|
|
|
|
|
80
|
|
View Code Duplication |
public function invalidFilenamesAndMediaTypes() |
|
|
|
|
|
|
81
|
|
|
{ |
|
82
|
|
|
return [ |
|
83
|
|
|
'true' => [true], |
|
84
|
|
|
'false' => [false], |
|
85
|
|
|
'int' => [1], |
|
86
|
|
|
'float' => [1.1], |
|
87
|
|
|
'array' => [['string']], |
|
88
|
|
|
'object' => [(object) ['string']], |
|
89
|
|
|
]; |
|
90
|
|
|
} |
|
91
|
|
|
|
|
92
|
|
|
/** |
|
93
|
|
|
* @dataProvider invalidFilenamesAndMediaTypes |
|
94
|
|
|
*/ |
|
95
|
|
View Code Duplication |
public function testRaisesExceptionOnInvalidClientFilename($filename) |
|
|
|
|
|
|
96
|
|
|
{ |
|
97
|
|
|
$this->expectException(\InvalidArgumentException::class); |
|
98
|
|
|
$this->expectExceptionMessage('filename'); |
|
99
|
|
|
|
|
100
|
|
|
new UploadedFile(fopen('php://temp', 'wb+'), 0, UPLOAD_ERR_OK, $filename); |
|
101
|
|
|
} |
|
102
|
|
|
|
|
103
|
|
|
/** |
|
104
|
|
|
* @dataProvider invalidFilenamesAndMediaTypes |
|
105
|
|
|
*/ |
|
106
|
|
View Code Duplication |
public function testRaisesExceptionOnInvalidClientMediaType($mediaType) |
|
|
|
|
|
|
107
|
|
|
{ |
|
108
|
|
|
$this->expectException(\InvalidArgumentException::class); |
|
109
|
|
|
$this->expectExceptionMessage('media type'); |
|
110
|
|
|
|
|
111
|
|
|
new UploadedFile(fopen('php://temp', 'wb+'), 0, UPLOAD_ERR_OK, 'foobar.baz', $mediaType); |
|
112
|
|
|
} |
|
113
|
|
|
|
|
114
|
|
|
public function testGetStreamReturnsOriginalStreamObject() |
|
115
|
|
|
{ |
|
116
|
|
|
$stream = Stream::create(''); |
|
117
|
|
|
$upload = new UploadedFile($stream, 0, UPLOAD_ERR_OK); |
|
118
|
|
|
|
|
119
|
|
|
$this->assertSame($stream, $upload->getStream()); |
|
120
|
|
|
} |
|
121
|
|
|
|
|
122
|
|
|
public function testGetStreamReturnsWrappedPhpStream() |
|
123
|
|
|
{ |
|
124
|
|
|
$stream = fopen('php://temp', 'wb+'); |
|
125
|
|
|
$upload = new UploadedFile($stream, 0, UPLOAD_ERR_OK); |
|
126
|
|
|
$uploadStream = $upload->getStream()->detach(); |
|
127
|
|
|
|
|
128
|
|
|
$this->assertSame($stream, $uploadStream); |
|
129
|
|
|
} |
|
130
|
|
|
|
|
131
|
|
|
public function testSuccessful() |
|
132
|
|
|
{ |
|
133
|
|
|
$stream = Stream::create('Foo bar!'); |
|
134
|
|
|
$upload = new UploadedFile($stream, $stream->getSize(), UPLOAD_ERR_OK, 'filename.txt', 'text/plain'); |
|
135
|
|
|
|
|
136
|
|
|
$this->assertEquals($stream->getSize(), $upload->getSize()); |
|
137
|
|
|
$this->assertEquals('filename.txt', $upload->getClientFilename()); |
|
138
|
|
|
$this->assertEquals('text/plain', $upload->getClientMediaType()); |
|
139
|
|
|
|
|
140
|
|
|
$this->cleanup[] = $to = tempnam(sys_get_temp_dir(), 'successful'); |
|
141
|
|
|
$upload->moveTo($to); |
|
142
|
|
|
$this->assertFileExists($to); |
|
143
|
|
|
$this->assertEquals($stream->__toString(), file_get_contents($to)); |
|
144
|
|
|
} |
|
145
|
|
|
|
|
146
|
|
View Code Duplication |
public function invalidMovePaths() |
|
|
|
|
|
|
147
|
|
|
{ |
|
148
|
|
|
return [ |
|
149
|
|
|
'null' => [null], |
|
150
|
|
|
'true' => [true], |
|
151
|
|
|
'false' => [false], |
|
152
|
|
|
'int' => [1], |
|
153
|
|
|
'float' => [1.1], |
|
154
|
|
|
'empty' => [''], |
|
155
|
|
|
'array' => [['filename']], |
|
156
|
|
|
'object' => [(object) ['filename']], |
|
157
|
|
|
]; |
|
158
|
|
|
} |
|
159
|
|
|
|
|
160
|
|
|
/** |
|
161
|
|
|
* @dataProvider invalidMovePaths |
|
162
|
|
|
*/ |
|
163
|
|
|
public function testMoveRaisesExceptionForInvalidPath($path) |
|
164
|
|
|
{ |
|
165
|
|
|
$stream = (new \Nyholm\Psr7\Factory\StreamFactory())->createStream('Foo bar!'); |
|
166
|
|
|
$upload = new UploadedFile($stream, 0, UPLOAD_ERR_OK); |
|
167
|
|
|
|
|
168
|
|
|
$this->cleanup[] = $path; |
|
169
|
|
|
|
|
170
|
|
|
$this->expectException(\InvalidArgumentException::class); |
|
171
|
|
|
$this->expectExceptionMessage('path'); |
|
172
|
|
|
$upload->moveTo($path); |
|
173
|
|
|
} |
|
174
|
|
|
|
|
175
|
|
View Code Duplication |
public function testMoveCannotBeCalledMoreThanOnce() |
|
|
|
|
|
|
176
|
|
|
{ |
|
177
|
|
|
$stream = (new \Nyholm\Psr7\Factory\StreamFactory())->createStream('Foo bar!'); |
|
178
|
|
|
$upload = new UploadedFile($stream, 0, UPLOAD_ERR_OK); |
|
179
|
|
|
|
|
180
|
|
|
$this->cleanup[] = $to = tempnam(sys_get_temp_dir(), 'diac'); |
|
181
|
|
|
$upload->moveTo($to); |
|
182
|
|
|
$this->assertTrue(file_exists($to)); |
|
183
|
|
|
|
|
184
|
|
|
$this->expectException(\RuntimeException::class); |
|
185
|
|
|
$this->expectExceptionMessage('moved'); |
|
186
|
|
|
$upload->moveTo($to); |
|
187
|
|
|
} |
|
188
|
|
|
|
|
189
|
|
View Code Duplication |
public function testCannotRetrieveStreamAfterMove() |
|
|
|
|
|
|
190
|
|
|
{ |
|
191
|
|
|
$stream = (new \Nyholm\Psr7\Factory\StreamFactory())->createStream('Foo bar!'); |
|
192
|
|
|
$upload = new UploadedFile($stream, 0, UPLOAD_ERR_OK); |
|
193
|
|
|
|
|
194
|
|
|
$this->cleanup[] = $to = tempnam(sys_get_temp_dir(), 'diac'); |
|
195
|
|
|
$upload->moveTo($to); |
|
196
|
|
|
$this->assertFileExists($to); |
|
197
|
|
|
|
|
198
|
|
|
$this->expectException(\RuntimeException::class); |
|
199
|
|
|
$this->expectExceptionMessage('moved'); |
|
200
|
|
|
$upload->getStream(); |
|
201
|
|
|
} |
|
202
|
|
|
|
|
203
|
|
|
public function nonOkErrorStatus() |
|
204
|
|
|
{ |
|
205
|
|
|
return [ |
|
206
|
|
|
'UPLOAD_ERR_INI_SIZE' => [UPLOAD_ERR_INI_SIZE], |
|
207
|
|
|
'UPLOAD_ERR_FORM_SIZE' => [UPLOAD_ERR_FORM_SIZE], |
|
208
|
|
|
'UPLOAD_ERR_PARTIAL' => [UPLOAD_ERR_PARTIAL], |
|
209
|
|
|
'UPLOAD_ERR_NO_FILE' => [UPLOAD_ERR_NO_FILE], |
|
210
|
|
|
'UPLOAD_ERR_NO_TMP_DIR' => [UPLOAD_ERR_NO_TMP_DIR], |
|
211
|
|
|
'UPLOAD_ERR_CANT_WRITE' => [UPLOAD_ERR_CANT_WRITE], |
|
212
|
|
|
'UPLOAD_ERR_EXTENSION' => [UPLOAD_ERR_EXTENSION], |
|
213
|
|
|
]; |
|
214
|
|
|
} |
|
215
|
|
|
|
|
216
|
|
|
/** |
|
217
|
|
|
* @dataProvider nonOkErrorStatus |
|
218
|
|
|
*/ |
|
219
|
|
|
public function testConstructorDoesNotRaiseExceptionForInvalidStreamWhenErrorStatusPresent($status) |
|
220
|
|
|
{ |
|
221
|
|
|
$uploadedFile = new UploadedFile('not ok', 0, $status); |
|
222
|
|
|
$this->assertSame($status, $uploadedFile->getError()); |
|
223
|
|
|
} |
|
224
|
|
|
|
|
225
|
|
|
/** |
|
226
|
|
|
* @dataProvider nonOkErrorStatus |
|
227
|
|
|
*/ |
|
228
|
|
|
public function testMoveToRaisesExceptionWhenErrorStatusPresent($status) |
|
229
|
|
|
{ |
|
230
|
|
|
$uploadedFile = new UploadedFile('not ok', 0, $status); |
|
231
|
|
|
$this->expectException(\RuntimeException::class); |
|
232
|
|
|
$this->expectExceptionMessage('upload error'); |
|
233
|
|
|
$uploadedFile->moveTo(__DIR__.'/'.uniqid()); |
|
234
|
|
|
} |
|
235
|
|
|
|
|
236
|
|
|
/** |
|
237
|
|
|
* @dataProvider nonOkErrorStatus |
|
238
|
|
|
*/ |
|
239
|
|
|
public function testGetStreamRaisesExceptionWhenErrorStatusPresent($status) |
|
240
|
|
|
{ |
|
241
|
|
|
$uploadedFile = new UploadedFile('not ok', 0, $status); |
|
242
|
|
|
$this->expectException(\RuntimeException::class); |
|
243
|
|
|
$this->expectExceptionMessage('upload error'); |
|
244
|
|
|
$stream = $uploadedFile->getStream(); |
|
|
|
|
|
|
245
|
|
|
} |
|
246
|
|
|
|
|
247
|
|
|
public function testMoveToCreatesStreamIfOnlyAFilenameWasProvided() |
|
248
|
|
|
{ |
|
249
|
|
|
$this->cleanup[] = $from = tempnam(sys_get_temp_dir(), 'copy_from'); |
|
250
|
|
|
$this->cleanup[] = $to = tempnam(sys_get_temp_dir(), 'copy_to'); |
|
251
|
|
|
|
|
252
|
|
|
copy(__FILE__, $from); |
|
253
|
|
|
|
|
254
|
|
|
$uploadedFile = new UploadedFile($from, 100, UPLOAD_ERR_OK, basename($from), 'text/plain'); |
|
255
|
|
|
$uploadedFile->moveTo($to); |
|
256
|
|
|
|
|
257
|
|
|
$this->assertFileEquals(__FILE__, $to); |
|
258
|
|
|
} |
|
259
|
|
|
} |
|
260
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.