Merge "maintenance: Script to rename titles for Unicode uppercasing changes"
[lhc/web/wiklou.git] / tests / phpunit / includes / libs / ParamValidator / Util / UploadedFileTest.php
1 <?php
2
3 namespace Wikimedia\ParamValidator\Util;
4
5 require_once __DIR__ . '/UploadedFileTestBase.php';
6
7 use Psr\Http\Message\StreamInterface;
8 use RuntimeException;
9
10 /**
11 * @covers Wikimedia\ParamValidator\Util\UploadedFile
12 */
13 class UploadedFileTest extends UploadedFileTestBase {
14
15 public function testGetStream() {
16 $filename = $this->makeTemp( __FUNCTION__ );
17
18 $file = new UploadedFile( [ 'error' => UPLOAD_ERR_OK, 'tmp_name' => $filename ], false );
19
20 // getStream() fails for non-OK uploads
21 foreach ( [
22 UPLOAD_ERR_INI_SIZE,
23 UPLOAD_ERR_FORM_SIZE,
24 UPLOAD_ERR_PARTIAL,
25 UPLOAD_ERR_NO_FILE,
26 UPLOAD_ERR_NO_TMP_DIR,
27 UPLOAD_ERR_CANT_WRITE,
28 UPLOAD_ERR_EXTENSION,
29 -42
30 ] as $code ) {
31 $file2 = new UploadedFile( [ 'error' => $code, 'tmp_name' => $filename ], false );
32 try {
33 $file2->getStream();
34 $this->fail( 'Expected exception not thrown' );
35 } catch ( \PHPUnit\Framework\AssertionFailedError $ex ) {
36 throw $ex;
37 } catch ( RuntimeException $ex ) {
38 }
39 }
40
41 // getStream() works
42 $stream = $file->getStream();
43 $this->assertInstanceOf( StreamInterface::class, $stream );
44 $stream->seek( 0 );
45 $this->assertSame( 'foobar', $stream->getContents() );
46
47 // Second call also works
48 $this->assertInstanceOf( StreamInterface::class, $file->getStream() );
49
50 // getStream() throws after move, and the stream is invalidated too
51 $file->moveTo( $filename . '.xxx' );
52 try {
53 try {
54 $file->getStream();
55 $this->fail( 'Expected exception not thrown' );
56 } catch ( \PHPUnit\Framework\AssertionFailedError $ex ) {
57 throw $ex;
58 } catch ( RuntimeException $ex ) {
59 $this->assertSame( 'File has already been moved', $ex->getMessage() );
60 }
61 try {
62 $stream->seek( 0 );
63 $stream->getContents();
64 $this->fail( 'Expected exception not thrown' );
65 } catch ( \PHPUnit\Framework\AssertionFailedError $ex ) {
66 throw $ex;
67 } catch ( RuntimeException $ex ) {
68 }
69 } finally {
70 unlink( $filename . '.xxx' ); // Clean up
71 }
72
73 // getStream() fails if the file is missing
74 $file = new UploadedFile( [ 'error' => UPLOAD_ERR_OK, 'tmp_name' => $filename ], true );
75 try {
76 $file->getStream();
77 $this->fail( 'Expected exception not thrown' );
78 } catch ( \PHPUnit\Framework\AssertionFailedError $ex ) {
79 throw $ex;
80 } catch ( RuntimeException $ex ) {
81 $this->assertSame( 'Uploaded file is missing', $ex->getMessage() );
82 }
83 }
84
85 public function testMoveTo() {
86 // Successful move
87 $filename = $this->makeTemp( __FUNCTION__ );
88 $this->assertFileExists( $filename, 'sanity check' );
89 $this->assertFileNotExists( "$filename.xxx", 'sanity check' );
90 $file = new UploadedFile( [ 'error' => UPLOAD_ERR_OK, 'tmp_name' => $filename ], false );
91 $file->moveTo( $filename . '.xxx' );
92 $this->assertFileNotExists( $filename );
93 $this->assertFileExists( "$filename.xxx" );
94
95 // Fails on a second move attempt
96 $this->assertFileNotExists( "$filename.yyy", 'sanity check' );
97 try {
98 $file->moveTo( $filename . '.yyy' );
99 $this->fail( 'Expected exception not thrown' );
100 } catch ( \PHPUnit\Framework\AssertionFailedError $ex ) {
101 throw $ex;
102 } catch ( RuntimeException $ex ) {
103 $this->assertSame( 'File has already been moved', $ex->getMessage() );
104 }
105 $this->assertFileNotExists( $filename );
106 $this->assertFileExists( "$filename.xxx" );
107 $this->assertFileNotExists( "$filename.yyy" );
108
109 // Fails if the file is missing
110 $file = new UploadedFile( [ 'error' => UPLOAD_ERR_OK, 'tmp_name' => "$filename.aaa" ], false );
111 $this->assertFileNotExists( "$filename.aaa", 'sanity check' );
112 $this->assertFileNotExists( "$filename.bbb", 'sanity check' );
113 try {
114 $file->moveTo( $filename . '.bbb' );
115 $this->fail( 'Expected exception not thrown' );
116 } catch ( \PHPUnit\Framework\AssertionFailedError $ex ) {
117 throw $ex;
118 } catch ( RuntimeException $ex ) {
119 $this->assertSame( 'Uploaded file is missing', $ex->getMessage() );
120 }
121 $this->assertFileNotExists( "$filename.aaa" );
122 $this->assertFileNotExists( "$filename.bbb" );
123
124 // Fails for non-upload file (when not flagged to ignore that)
125 $filename = $this->makeTemp( __FUNCTION__ );
126 $this->assertFileExists( $filename, 'sanity check' );
127 $this->assertFileNotExists( "$filename.xxx", 'sanity check' );
128 $file = new UploadedFile( [ 'error' => UPLOAD_ERR_OK, 'tmp_name' => $filename ] );
129 try {
130 $file->moveTo( $filename . '.xxx' );
131 $this->fail( 'Expected exception not thrown' );
132 } catch ( \PHPUnit\Framework\AssertionFailedError $ex ) {
133 throw $ex;
134 } catch ( RuntimeException $ex ) {
135 $this->assertSame( 'Specified file is not an uploaded file', $ex->getMessage() );
136 }
137 $this->assertFileExists( $filename );
138 $this->assertFileNotExists( "$filename.xxx" );
139
140 // Fails for error uploads
141 $filename = $this->makeTemp( __FUNCTION__ );
142 $this->assertFileExists( $filename, 'sanity check' );
143 $this->assertFileNotExists( "$filename.xxx", 'sanity check' );
144 foreach ( [
145 UPLOAD_ERR_INI_SIZE,
146 UPLOAD_ERR_FORM_SIZE,
147 UPLOAD_ERR_PARTIAL,
148 UPLOAD_ERR_NO_FILE,
149 UPLOAD_ERR_NO_TMP_DIR,
150 UPLOAD_ERR_CANT_WRITE,
151 UPLOAD_ERR_EXTENSION,
152 -42
153 ] as $code ) {
154 $file = new UploadedFile( [ 'error' => $code, 'tmp_name' => $filename ], false );
155 try {
156 $file->moveTo( $filename . '.xxx' );
157 $this->fail( 'Expected exception not thrown' );
158 } catch ( \PHPUnit\Framework\AssertionFailedError $ex ) {
159 throw $ex;
160 } catch ( RuntimeException $ex ) {
161 }
162 $this->assertFileExists( $filename );
163 $this->assertFileNotExists( "$filename.xxx" );
164 }
165
166 // Move failure triggers exception
167 $filename = $this->makeTemp( __FUNCTION__, 'file1' );
168 $filename2 = $this->makeTemp( __FUNCTION__, 'file2' );
169 $this->assertFileExists( $filename, 'sanity check' );
170 $file = new UploadedFile( [ 'error' => UPLOAD_ERR_OK, 'tmp_name' => $filename ], false );
171 try {
172 $file->moveTo( $filename2 . DIRECTORY_SEPARATOR . 'foobar' );
173 $this->fail( 'Expected exception not thrown' );
174 } catch ( \PHPUnit\Framework\AssertionFailedError $ex ) {
175 throw $ex;
176 } catch ( RuntimeException $ex ) {
177 }
178 $this->assertFileExists( $filename );
179 }
180
181 public function testInfoMethods() {
182 $filename = $this->makeTemp( __FUNCTION__ );
183 $file = new UploadedFile( [
184 'name' => 'C:\\example.txt',
185 'type' => 'text/plain',
186 'size' => 1025,
187 'error' => UPLOAD_ERR_OK,
188 'tmp_name' => $filename,
189 ], false );
190 $this->assertSame( 1025, $file->getSize() );
191 $this->assertSame( UPLOAD_ERR_OK, $file->getError() );
192 $this->assertSame( 'C:\\example.txt', $file->getClientFilename() );
193 $this->assertSame( 'text/plain', $file->getClientMediaType() );
194
195 // None of these are allowed to error
196 $file = new UploadedFile( [], false );
197 $this->assertSame( null, $file->getSize() );
198 $this->assertSame( UPLOAD_ERR_NO_FILE, $file->getError() );
199 $this->assertSame( null, $file->getClientFilename() );
200 $this->assertSame( null, $file->getClientMediaType() );
201
202 // "if none was provided" behavior, given that $_FILES often contains
203 // the empty string.
204 $file = new UploadedFile( [
205 'name' => '',
206 'type' => '',
207 'size' => 100,
208 'error' => UPLOAD_ERR_NO_FILE,
209 'tmp_name' => $filename,
210 ], false );
211 $this->assertSame( null, $file->getClientFilename() );
212 $this->assertSame( null, $file->getClientMediaType() );
213 }
214
215 }