Merge "Fix use of GenderCache in ApiPageSet::processTitlesArray"
[lhc/web/wiklou.git] / tests / phpunit / includes / api / ApiUploadTest.php
1 <?php
2
3 /**
4 * @group API
5 * @group Database
6 * @group medium
7 *
8 * @covers ApiUpload
9 */
10 class ApiUploadTest extends ApiUploadTestCase {
11 private function filePath( $fileName ) {
12 return __DIR__ . '/../../data/media/' . $fileName;
13 }
14
15 public function setUp() {
16 parent::setUp();
17 $this->tablesUsed[] = 'watchlist'; // This test might interfere with watchlists test.
18 $this->tablesUsed = array_merge( $this->tablesUsed, LocalFile::getQueryInfo()['tables'] );
19 $this->setService( 'RepoGroup', new RepoGroup(
20 [
21 'class' => LocalRepo::class,
22 'name' => 'temp',
23 'backend' => new FSFileBackend( [
24 'name' => 'temp-backend',
25 'wikiId' => wfWikiID(),
26 'basePath' => $this->getNewTempDirectory()
27 ] )
28 ],
29 [],
30 null
31 ) );
32 $this->resetServices();
33 }
34
35 public function testUploadRequiresToken() {
36 $this->setExpectedException(
37 ApiUsageException::class,
38 'The "token" parameter must be set'
39 );
40 $this->doApiRequest( [
41 'action' => 'upload'
42 ] );
43 }
44
45 public function testUploadMissingParams() {
46 $this->setExpectedException(
47 ApiUsageException::class,
48 'One of the parameters "filekey", "file" and "url" is required'
49 );
50 $this->doApiRequestWithToken( [
51 'action' => 'upload',
52 ], null, self::$users['uploader']->getUser() );
53 }
54
55 public function testUpload() {
56 $fileName = 'TestUpload.jpg';
57 $mimeType = 'image/jpeg';
58 $filePath = $this->filePath( 'yuv420.jpg' );
59
60 $this->fakeUploadFile( 'file', $fileName, $mimeType, $filePath );
61 list( $result ) = $this->doApiRequestWithToken( [
62 'action' => 'upload',
63 'filename' => $fileName,
64 'file' => 'dummy content',
65 'comment' => 'dummy comment',
66 'text' => "This is the page text for $fileName",
67 ], null, self::$users['uploader']->getUser() );
68
69 $this->assertArrayHasKey( 'upload', $result );
70 $this->assertEquals( 'Success', $result['upload']['result'] );
71 $this->assertSame( filesize( $filePath ), (int)$result['upload']['imageinfo']['size'] );
72 $this->assertEquals( $mimeType, $result['upload']['imageinfo']['mime'] );
73 }
74
75 public function testUploadZeroLength() {
76 $filePath = $this->getNewTempFile();
77 $mimeType = 'image/jpeg';
78 $fileName = "ApiTestUploadZeroLength.jpg";
79
80 $this->fakeUploadFile( 'file', $fileName, $mimeType, $filePath );
81
82 $this->setExpectedException(
83 ApiUsageException::class,
84 'The file you submitted was empty'
85 );
86 $this->doApiRequestWithToken( [
87 'action' => 'upload',
88 'filename' => $fileName,
89 'file' => 'dummy content',
90 'comment' => 'dummy comment',
91 'text' => "This is the page text for $fileName",
92 ], null, self::$users['uploader']->getUser() );
93 }
94
95 public function testUploadSameFileName() {
96 $fileName = 'TestUploadSameFileName.jpg';
97 $mimeType = 'image/jpeg';
98 $filePaths = [
99 $this->filePath( 'yuv420.jpg' ),
100 $this->filePath( 'yuv444.jpg' )
101 ];
102
103 // we reuse these params
104 $params = [
105 'action' => 'upload',
106 'filename' => $fileName,
107 'file' => 'dummy content',
108 'comment' => 'dummy comment',
109 'text' => "This is the page text for $fileName",
110 ];
111
112 // first upload .... should succeed
113
114 $this->fakeUploadFile( 'file', $fileName, $mimeType, $filePaths[0] );
115 list( $result ) = $this->doApiRequestWithToken( $params, null,
116 self::$users['uploader']->getUser() );
117 $this->assertArrayHasKey( 'upload', $result );
118 $this->assertEquals( 'Success', $result['upload']['result'] );
119
120 // second upload with the same name (but different content)
121
122 $this->fakeUploadFile( 'file', $fileName, $mimeType, $filePaths[1] );
123 list( $result ) = $this->doApiRequestWithToken( $params, null,
124 self::$users['uploader']->getUser() );
125 $this->assertArrayHasKey( 'upload', $result );
126 $this->assertEquals( 'Warning', $result['upload']['result'] );
127 $this->assertArrayHasKey( 'warnings', $result['upload'] );
128 $this->assertArrayHasKey( 'exists', $result['upload']['warnings'] );
129 }
130
131 public function testUploadSameContent() {
132 $fileNames = [ 'TestUploadSameContent_1.jpg', 'TestUploadSameContent_2.jpg' ];
133 $mimeType = 'image/jpeg';
134 $filePath = $this->filePath( 'yuv420.jpg' );
135
136 // first upload .... should succeed
137 $this->fakeUploadFile( 'file', $fileNames[0], $mimeType, $filePath );
138 list( $result ) = $this->doApiRequestWithToken( [
139 'action' => 'upload',
140 'filename' => $fileNames[0],
141 'file' => 'dummy content',
142 'comment' => 'dummy comment',
143 'text' => "This is the page text for {$fileNames[0]}",
144 ], null, self::$users['uploader']->getUser() );
145 $this->assertArrayHasKey( 'upload', $result );
146 $this->assertEquals( 'Success', $result['upload']['result'] );
147
148 // second upload with the same content (but different name)
149 $this->fakeUploadFile( 'file', $fileNames[1], $mimeType, $filePath );
150 list( $result ) = $this->doApiRequestWithToken( [
151 'action' => 'upload',
152 'filename' => $fileNames[1],
153 'file' => 'dummy content',
154 'comment' => 'dummy comment',
155 'text' => "This is the page text for {$fileNames[1]}",
156 ], null, self::$users['uploader']->getUser() );
157
158 $this->assertArrayHasKey( 'upload', $result );
159 $this->assertEquals( 'Warning', $result['upload']['result'] );
160 $this->assertArrayHasKey( 'warnings', $result['upload'] );
161 $this->assertArrayHasKey( 'duplicate', $result['upload']['warnings'] );
162 $this->assertArrayEquals( [ $fileNames[0] ], $result['upload']['warnings']['duplicate'] );
163 $this->assertArrayNotHasKey( 'exists', $result['upload']['warnings'] );
164 }
165
166 public function testUploadStash() {
167 $fileName = 'TestUploadStash.jpg';
168 $mimeType = 'image/jpeg';
169 $filePath = $this->filePath( 'yuv420.jpg' );
170
171 $this->fakeUploadFile( 'file', $fileName, $mimeType, $filePath );
172 list( $result ) = $this->doApiRequestWithToken( [
173 'action' => 'upload',
174 'stash' => 1,
175 'filename' => $fileName,
176 'file' => 'dummy content',
177 'comment' => 'dummy comment',
178 'text' => "This is the page text for $fileName",
179 ], null, self::$users['uploader']->getUser() );
180
181 $this->assertArrayHasKey( 'upload', $result );
182 $this->assertEquals( 'Success', $result['upload']['result'] );
183 $this->assertSame( filesize( $filePath ), (int)$result['upload']['imageinfo']['size'] );
184 $this->assertEquals( $mimeType, $result['upload']['imageinfo']['mime'] );
185 $this->assertArrayHasKey( 'filekey', $result['upload'] );
186 $this->assertEquals( $result['upload']['sessionkey'], $result['upload']['filekey'] );
187 $filekey = $result['upload']['filekey'];
188
189 // it should be visible from Special:UploadStash
190 // XXX ...but how to test this, with a fake WebRequest with the session?
191
192 // now we should try to release the file from stash
193 $this->clearFakeUploads();
194 list( $result ) = $this->doApiRequestWithToken( [
195 'action' => 'upload',
196 'filekey' => $filekey,
197 'filename' => $fileName,
198 'comment' => 'dummy comment',
199 'text' => "This is the page text for $fileName, altered",
200 ], null, self::$users['uploader']->getUser() );
201 $this->assertArrayHasKey( 'upload', $result );
202 $this->assertEquals( 'Success', $result['upload']['result'] );
203 }
204
205 public function testUploadChunks() {
206 $fileName = 'TestUploadChunks.jpg';
207 $mimeType = 'image/jpeg';
208 $filePath = $this->filePath( 'yuv420.jpg' );
209 $fileSize = filesize( $filePath );
210 $chunkSize = 20 * 1024; // The file is ~60kB, use 20kB chunks
211
212 $this->setMwGlobals( [
213 'wgMinUploadChunkSize' => $chunkSize
214 ] );
215
216 // Base upload params:
217 $params = [
218 'action' => 'upload',
219 'stash' => 1,
220 'filename' => $fileName,
221 'filesize' => $fileSize,
222 'offset' => 0,
223 ];
224
225 // Upload chunks
226 $handle = fopen( $filePath, "r" );
227 $resultOffset = 0;
228 $filekey = false;
229 while ( !feof( $handle ) ) {
230 $chunkData = fread( $handle, $chunkSize );
231
232 // Upload the current chunk into the $_FILE object:
233 $this->fakeUploadChunk( 'chunk', 'blob', $mimeType, $chunkData );
234 if ( !$filekey ) {
235 list( $result ) = $this->doApiRequestWithToken( $params, null,
236 self::$users['uploader']->getUser() );
237 // Make sure we got a valid chunk continue:
238 $this->assertArrayHasKey( 'upload', $result );
239 $this->assertArrayHasKey( 'filekey', $result['upload'] );
240 $this->assertEquals( 'Continue', $result['upload']['result'] );
241 $this->assertEquals( $chunkSize, $result['upload']['offset'] );
242
243 $filekey = $result['upload']['filekey'];
244 $resultOffset = $result['upload']['offset'];
245 } else {
246 // Filekey set to chunk session
247 $params['filekey'] = $filekey;
248 // Update the offset ( always add chunkSize for subquent chunks
249 // should be in-sync with $result['upload']['offset'] )
250 $params['offset'] += $chunkSize;
251 // Make sure param offset is insync with resultOffset:
252 $this->assertEquals( $resultOffset, $params['offset'] );
253 // Upload current chunk
254 list( $result ) = $this->doApiRequestWithToken( $params, null,
255 self::$users['uploader']->getUser() );
256 // Make sure we got a valid chunk continue:
257 $this->assertArrayHasKey( 'upload', $result );
258 $this->assertArrayHasKey( 'filekey', $result['upload'] );
259
260 // Check if we were on the last chunk:
261 if ( $params['offset'] + $chunkSize >= $fileSize ) {
262 $this->assertEquals( 'Success', $result['upload']['result'] );
263 break;
264 } else {
265 $this->assertEquals( 'Continue', $result['upload']['result'] );
266 $resultOffset = $result['upload']['offset'];
267 }
268 }
269 }
270 fclose( $handle );
271
272 // Check that we got a valid file result:
273 $this->assertEquals( $fileSize, $result['upload']['imageinfo']['size'] );
274 $this->assertEquals( $mimeType, $result['upload']['imageinfo']['mime'] );
275 $this->assertArrayHasKey( 'filekey', $result['upload'] );
276 $filekey = $result['upload']['filekey'];
277
278 // Now we should try to release the file from stash
279 $this->clearFakeUploads();
280 list( $result ) = $this->doApiRequestWithToken( [
281 'action' => 'upload',
282 'filekey' => $filekey,
283 'filename' => $fileName,
284 'comment' => 'dummy comment',
285 'text' => "This is the page text for $fileName, altered",
286 ], null, self::$users['uploader']->getUser() );
287 $this->assertArrayHasKey( 'upload', $result );
288 $this->assertEquals( 'Success', $result['upload']['result'] );
289 }
290 }