disable ApiUploadTest
[lhc/web/wiklou.git] / tests / phpunit / includes / api / ApiUploadTest.php
1 <?php
2
3 /**
4 * @group Database
5 */
6
7 /**
8 * n.b. Ensure that you can write to the images/ directory as the
9 * user that will run tests.
10 */
11
12 // Note for reviewers: this intentionally duplicates functionality already in "ApiSetup" and so on.
13 // This framework works better IMO and has less strangeness (such as test cases inheriting from "ApiSetup"...)
14 // (and in the case of the other Upload tests, this flat out just actually works... )
15
16 // TODO: port the other Upload tests, and other API tests to this framework
17
18 require_once( 'ApiTestCaseUpload.php' );
19
20 /**
21 * @group Database
22 * @group Broken
23 * Broken test, reports false errors from time to time.
24 * See https://bugzilla.wikimedia.org/26169
25 *
26 * This is pretty sucky... needs to be prettified.
27 */
28 class ApiUploadTest extends ApiTestCaseUpload {
29
30 /**
31 * Testing login
32 * XXX this is a funny way of getting session context
33 */
34 function testLogin() {
35 $user = self::$users['uploader'];
36
37 $params = array(
38 'action' => 'login',
39 'lgname' => $user->username,
40 'lgpassword' => $user->password
41 );
42 list( $result, , $session ) = $this->doApiRequest( $params );
43 $this->assertArrayHasKey( "login", $result );
44 $this->assertArrayHasKey( "result", $result['login'] );
45 $this->assertEquals( "NeedToken", $result['login']['result'] );
46 $token = $result['login']['token'];
47
48 $params = array(
49 'action' => 'login',
50 'lgtoken' => $token,
51 'lgname' => $user->username,
52 'lgpassword' => $user->password
53 );
54 list( $result, , $session ) = $this->doApiRequest( $params, $session );
55 $this->assertArrayHasKey( "login", $result );
56 $this->assertArrayHasKey( "result", $result['login'] );
57 $this->assertEquals( "Success", $result['login']['result'] );
58 $this->assertArrayHasKey( 'lgtoken', $result['login'] );
59
60 $this->assertNotEmpty( $session, 'API Login must return a session' );
61 return $session;
62
63 }
64
65 /**
66 * @depends testLogin
67 */
68 public function testUploadRequiresToken( $session ) {
69 $exception = false;
70 try {
71 $this->doApiRequest( array(
72 'action' => 'upload'
73 ) );
74 } catch ( UsageException $e ) {
75 $exception = true;
76 $this->assertEquals( "The token parameter must be set", $e->getMessage() );
77 }
78 $this->assertTrue( $exception, "Got exception" );
79 }
80
81 /**
82 * @depends testLogin
83 */
84 public function testUploadMissingParams( $session ) {
85 $exception = false;
86 try {
87 $this->doApiRequestWithToken( array(
88 'action' => 'upload',
89 ), $session, self::$users['uploader']->user );
90 } catch ( UsageException $e ) {
91 $exception = true;
92 $this->assertEquals( "One of the parameters filekey, file, url, statuskey is required",
93 $e->getMessage() );
94 }
95 $this->assertTrue( $exception, "Got exception" );
96 }
97
98
99 /**
100 * @depends testLogin
101 */
102 public function testUpload( $session ) {
103 $extension = 'png';
104 $mimeType = 'image/png';
105
106 try {
107 $randomImageGenerator = new RandomImageGenerator();
108 $filePaths = $randomImageGenerator->writeImages( 1, $extension, wfTempDir() );
109 }
110 catch ( Exception $e ) {
111 $this->markTestIncomplete( $e->getMessage() );
112 }
113
114 $filePath = $filePaths[0];
115 $fileSize = filesize( $filePath );
116 $fileName = basename( $filePath );
117
118 $this->deleteFileByFileName( $fileName );
119 $this->deleteFileByContent( $filePath );
120
121
122 if (! $this->fakeUploadFile( 'file', $fileName, $mimeType, $filePath ) ) {
123 $this->markTestIncomplete( "Couldn't upload file!\n" );
124 }
125
126 $params = array(
127 'action' => 'upload',
128 'filename' => $fileName,
129 'file' => 'dummy content',
130 'comment' => 'dummy comment',
131 'text' => "This is the page text for $fileName",
132 );
133
134 $exception = false;
135 try {
136 list( $result, , ) = $this->doApiRequestWithToken( $params, $session,
137 self::$users['uploader']->user );
138 } catch ( UsageException $e ) {
139 $exception = true;
140 }
141 $this->assertTrue( isset( $result['upload'] ) );
142 $this->assertEquals( 'Success', $result['upload']['result'] );
143 $this->assertEquals( $fileSize, ( int )$result['upload']['imageinfo']['size'] );
144 $this->assertEquals( $mimeType, $result['upload']['imageinfo']['mime'] );
145 $this->assertFalse( $exception );
146
147 // clean up
148 $this->deleteFileByFilename( $fileName );
149 unlink( $filePath );
150 }
151
152
153 /**
154 * @depends testLogin
155 */
156 public function testUploadZeroLength( $session ) {
157 $mimeType = 'image/png';
158
159 $filePath = tempnam( wfTempDir(), "" );
160 $fileName = "apiTestUploadZeroLength.png";
161
162 $this->deleteFileByFileName( $fileName );
163
164 if (! $this->fakeUploadFile( 'file', $fileName, $mimeType, $filePath ) ) {
165 $this->markTestIncomplete( "Couldn't upload file!\n" );
166 }
167
168 $params = array(
169 'action' => 'upload',
170 'filename' => $fileName,
171 'file' => 'dummy content',
172 'comment' => 'dummy comment',
173 'text' => "This is the page text for $fileName",
174 );
175
176 $exception = false;
177 try {
178 $this->doApiRequestWithToken( $params, $session, self::$users['uploader']->user );
179 } catch ( UsageException $e ) {
180 $this->assertContains( 'The file you submitted was empty', $e->getMessage() );
181 $exception = true;
182 }
183 $this->assertTrue( $exception );
184
185 // clean up
186 $this->deleteFileByFilename( $fileName );
187 unlink( $filePath );
188 }
189
190
191 /**
192 * @depends testLogin
193 */
194 public function testUploadSameFileName( $session ) {
195 $extension = 'png';
196 $mimeType = 'image/png';
197
198 try {
199 $randomImageGenerator = new RandomImageGenerator();
200 $filePaths = $randomImageGenerator->writeImages( 2, $extension, wfTempDir() );
201 }
202 catch ( Exception $e ) {
203 $this->markTestIncomplete( $e->getMessage() );
204 }
205
206 // we'll reuse this filename
207 $fileName = basename( $filePaths[0] );
208
209 // clear any other files with the same name
210 $this->deleteFileByFileName( $fileName );
211
212 // we reuse these params
213 $params = array(
214 'action' => 'upload',
215 'filename' => $fileName,
216 'file' => 'dummy content',
217 'comment' => 'dummy comment',
218 'text' => "This is the page text for $fileName",
219 );
220
221 // first upload .... should succeed
222
223 if (! $this->fakeUploadFile( 'file', $fileName, $mimeType, $filePaths[0] ) ) {
224 $this->markTestIncomplete( "Couldn't upload file!\n" );
225 }
226
227 $exception = false;
228 try {
229 list( $result, , $session ) = $this->doApiRequestWithToken( $params, $session,
230 self::$users['uploader']->user );
231 } catch ( UsageException $e ) {
232 $exception = true;
233 }
234 $this->assertTrue( isset( $result['upload'] ) );
235 $this->assertEquals( 'Success', $result['upload']['result'] );
236 $this->assertFalse( $exception );
237
238 // second upload with the same name (but different content)
239
240 if (! $this->fakeUploadFile( 'file', $fileName, $mimeType, $filePaths[1] ) ) {
241 $this->markTestIncomplete( "Couldn't upload file!\n" );
242 }
243
244 $exception = false;
245 try {
246 list( $result, , ) = $this->doApiRequestWithToken( $params, $session,
247 self::$users['uploader']->user ); // FIXME: leaks a temporary file
248 } catch ( UsageException $e ) {
249 $exception = true;
250 }
251 $this->assertTrue( isset( $result['upload'] ) );
252 $this->assertEquals( 'Warning', $result['upload']['result'] );
253 $this->assertTrue( isset( $result['upload']['warnings'] ) );
254 $this->assertTrue( isset( $result['upload']['warnings']['exists'] ) );
255 $this->assertFalse( $exception );
256
257 // clean up
258 $this->deleteFileByFilename( $fileName );
259 unlink( $filePaths[0] );
260 unlink( $filePaths[1] );
261 }
262
263
264 /**
265 * @depends testLogin
266 */
267 public function testUploadSameContent( $session ) {
268 $extension = 'png';
269 $mimeType = 'image/png';
270
271 try {
272 $randomImageGenerator = new RandomImageGenerator();
273 $filePaths = $randomImageGenerator->writeImages( 1, $extension, wfTempDir() );
274 }
275 catch ( Exception $e ) {
276 $this->markTestIncomplete( $e->getMessage() );
277 }
278
279 $fileNames[0] = basename( $filePaths[0] );
280 $fileNames[1] = "SameContentAs" . $fileNames[0];
281
282 // clear any other files with the same name or content
283 $this->deleteFileByContent( $filePaths[0] );
284 $this->deleteFileByFileName( $fileNames[0] );
285 $this->deleteFileByFileName( $fileNames[1] );
286
287 // first upload .... should succeed
288
289 $params = array(
290 'action' => 'upload',
291 'filename' => $fileNames[0],
292 'file' => 'dummy content',
293 'comment' => 'dummy comment',
294 'text' => "This is the page text for " . $fileNames[0],
295 );
296
297 if (! $this->fakeUploadFile( 'file', $fileNames[0], $mimeType, $filePaths[0] ) ) {
298 $this->markTestIncomplete( "Couldn't upload file!\n" );
299 }
300
301 $exception = false;
302 try {
303 list( $result, $request, $session ) = $this->doApiRequestWithToken( $params, $session,
304 self::$users['uploader']->user );
305 } catch ( UsageException $e ) {
306 $exception = true;
307 }
308 $this->assertTrue( isset( $result['upload'] ) );
309 $this->assertEquals( 'Success', $result['upload']['result'] );
310 $this->assertFalse( $exception );
311
312
313 // second upload with the same content (but different name)
314
315 if (! $this->fakeUploadFile( 'file', $fileNames[1], $mimeType, $filePaths[0] ) ) {
316 $this->markTestIncomplete( "Couldn't upload file!\n" );
317 }
318
319 $params = array(
320 'action' => 'upload',
321 'filename' => $fileNames[1],
322 'file' => 'dummy content',
323 'comment' => 'dummy comment',
324 'text' => "This is the page text for " . $fileNames[1],
325 );
326
327 $exception = false;
328 try {
329 list( $result, $request, $session ) = $this->doApiRequestWithToken( $params, $session,
330 self::$users['uploader']->user ); // FIXME: leaks a temporary file
331 } catch ( UsageException $e ) {
332 $exception = true;
333 }
334 $this->assertTrue( isset( $result['upload'] ) );
335 $this->assertEquals( 'Warning', $result['upload']['result'] );
336 $this->assertTrue( isset( $result['upload']['warnings'] ) );
337 $this->assertTrue( isset( $result['upload']['warnings']['duplicate'] ) );
338 $this->assertFalse( $exception );
339
340 // clean up
341 $this->deleteFileByFilename( $fileNames[0] );
342 $this->deleteFileByFilename( $fileNames[1] );
343 unlink( $filePaths[0] );
344 }
345
346
347 /**
348 * @depends testLogin
349 */
350 public function testUploadStash( $session ) {
351 global $wgUser;
352 $wgUser = self::$users['uploader']->user; // @todo FIXME: still used somewhere
353
354 $extension = 'png';
355 $mimeType = 'image/png';
356
357 try {
358 $randomImageGenerator = new RandomImageGenerator();
359 $filePaths = $randomImageGenerator->writeImages( 1, $extension, wfTempDir() );
360 }
361 catch ( Exception $e ) {
362 $this->markTestIncomplete( $e->getMessage() );
363 }
364
365 $filePath = $filePaths[0];
366 $fileSize = filesize( $filePath );
367 $fileName = basename( $filePath );
368
369 $this->deleteFileByFileName( $fileName );
370 $this->deleteFileByContent( $filePath );
371
372 if (! $this->fakeUploadFile( 'file', $fileName, $mimeType, $filePath ) ) {
373 $this->markTestIncomplete( "Couldn't upload file!\n" );
374 }
375
376 $params = array(
377 'action' => 'upload',
378 'stash' => 1,
379 'filename' => $fileName,
380 'file' => 'dummy content',
381 'comment' => 'dummy comment',
382 'text' => "This is the page text for $fileName",
383 );
384
385 $exception = false;
386 try {
387 list( $result, $request, $session ) = $this->doApiRequestWithToken( $params, $session,
388 self::$users['uploader']->user ); // FIXME: leaks a temporary file
389 } catch ( UsageException $e ) {
390 $exception = true;
391 }
392 $this->assertFalse( $exception );
393 $this->assertTrue( isset( $result['upload'] ) );
394 $this->assertEquals( 'Success', $result['upload']['result'] );
395 $this->assertEquals( $fileSize, ( int )$result['upload']['imageinfo']['size'] );
396 $this->assertEquals( $mimeType, $result['upload']['imageinfo']['mime'] );
397 $this->assertTrue( isset( $result['upload']['filekey'] ) );
398 $this->assertEquals( $result['upload']['sessionkey'], $result['upload']['filekey'] );
399 $filekey = $result['upload']['filekey'];
400
401 // it should be visible from Special:UploadStash
402 // XXX ...but how to test this, with a fake WebRequest with the session?
403
404 // now we should try to release the file from stash
405 $params = array(
406 'action' => 'upload',
407 'filekey' => $filekey,
408 'filename' => $fileName,
409 'comment' => 'dummy comment',
410 'text' => "This is the page text for $fileName, altered",
411 );
412
413 $this->clearFakeUploads();
414 $exception = false;
415 try {
416 list( $result, $request, $session ) = $this->doApiRequestWithToken( $params, $session,
417 self::$users['uploader']->user );
418 } catch ( UsageException $e ) {
419 $exception = true;
420 }
421 $this->assertTrue( isset( $result['upload'] ) );
422 $this->assertEquals( 'Success', $result['upload']['result'] );
423 $this->assertFalse( $exception, "No UsageException exception." );
424
425 // clean up
426 $this->deleteFileByFilename( $fileName );
427 unlink( $filePath );
428 }
429
430
431 /**
432 * @depends testLogin
433 */
434 public function testUploadChunks( $session ) {
435 global $wgUser;
436 $wgUser = self::$users['uploader']->user; // @todo FIXME: still used somewhere
437
438 $chunkSize = 1048576;
439 // Download a large image file
440 // ( using RandomImageGenerator for large files is not stable )
441 $mimeType = 'image/jpeg';
442 $url = 'http://upload.wikimedia.org/wikipedia/commons/e/ed/Oberaargletscher_from_Oberaar%2C_2010_07.JPG';
443 $filePath = wfTempDir() . '/Oberaargletscher_from_Oberaar.jpg';
444 try {
445 // Only download if the file is not avaliable in the temp location:
446 if( !is_file( $filePath ) ){
447 copy($url, $filePath);
448 }
449 }
450 catch ( Exception $e ) {
451 $this->markTestIncomplete( $e->getMessage() );
452 }
453
454 $fileSize = filesize( $filePath );
455 $fileName = basename( $filePath );
456
457 $this->deleteFileByFileName( $fileName );
458 $this->deleteFileByContent( $filePath );
459
460 // Base upload params:
461 $params = array(
462 'action' => 'upload',
463 'stash' => 1,
464 'filename' => $fileName,
465 'filesize' => $fileSize,
466 'offset' => 0,
467 );
468
469 // Upload chunks
470 $chunkSessionKey = false;
471 $resultOffset = 0;
472 // Open the file:
473 $handle = @fopen ($filePath, "r");
474 if( $handle === false ){
475 $this->markTestIncomplete( "could not open file: $filePath" );
476 }
477 while (!feof ($handle)) {
478 // Get the current chunk
479 $chunkData = @fread( $handle, $chunkSize );
480
481 // Upload the current chunk into the $_FILE object:
482 $this->fakeUploadChunk( 'chunk', 'blob', $mimeType, $chunkData );
483
484 // Check for chunkSessionKey
485 if( !$chunkSessionKey ){
486 // Upload fist chunk ( and get the session key )
487 try {
488 list( $result, $request, $session ) = $this->doApiRequestWithToken( $params, $session,
489 self::$users['uploader']->user );
490 } catch ( UsageException $e ) {
491 $this->markTestIncomplete( $e->getMessage() );
492 }
493 // Make sure we got a valid chunk continue:
494 $this->assertTrue( isset( $result['upload'] ) );
495 $this->assertTrue( isset( $result['upload']['filekey'] ) );
496 // If we don't get a session key mark test incomplete.
497 if( ! isset( $result['upload']['filekey'] ) ){
498 $this->markTestIncomplete( "no filekey provided" );
499 }
500 $chunkSessionKey = $result['upload']['filekey'];
501 $this->assertEquals( 'Continue', $result['upload']['result'] );
502 // First chunk should have chunkSize == offset
503 $this->assertEquals( $chunkSize, $result['upload']['offset'] );
504 $resultOffset = $result['upload']['offset'];
505 continue;
506 }
507 // Filekey set to chunk session
508 $params['filekey'] = $chunkSessionKey;
509 // Update the offset ( always add chunkSize for subquent chunks should be in-sync with $result['upload']['offset'] )
510 $params['offset'] += $chunkSize;
511 // Make sure param offset is insync with resultOffset:
512 $this->assertEquals( $resultOffset, $params['offset'] );
513 // Upload current chunk
514 try {
515 list( $result, $request, $session ) = $this->doApiRequestWithToken( $params, $session,
516 self::$users['uploader']->user );
517 } catch ( UsageException $e ) {
518 $this->markTestIncomplete( $e->getMessage() );
519 }
520 // Make sure we got a valid chunk continue:
521 $this->assertTrue( isset( $result['upload'] ) );
522 $this->assertTrue( isset( $result['upload']['filekey'] ) );
523
524 // Check if we were on the last chunk:
525 if( $params['offset'] + $chunkSize >= $fileSize ){
526 $this->assertEquals( 'Success', $result['upload']['result'] );
527 break;
528 } else {
529 $this->assertEquals( 'Continue', $result['upload']['result'] );
530 // update $resultOffset
531 $resultOffset = $result['upload']['offset'];
532 }
533 }
534 fclose ($handle);
535
536 // Check that we got a valid file result:
537 wfDebug( __METHOD__ . " hohoh filesize {$fileSize} info {$result['upload']['imageinfo']['size']}\n\n");
538 $this->assertEquals( $fileSize, $result['upload']['imageinfo']['size'] );
539 $this->assertEquals( $mimeType, $result['upload']['imageinfo']['mime'] );
540 $this->assertTrue( isset( $result['upload']['filekey'] ) );
541 $filekey = $result['upload']['filekey'];
542
543 // Now we should try to release the file from stash
544 $params = array(
545 'action' => 'upload',
546 'filekey' => $filekey,
547 'filename' => $fileName,
548 'comment' => 'dummy comment',
549 'text' => "This is the page text for $fileName, altered",
550 );
551 $this->clearFakeUploads();
552 $exception = false;
553 try {
554 list( $result, $request, $session ) = $this->doApiRequestWithToken( $params, $session,
555 self::$users['uploader']->user );
556 } catch ( UsageException $e ) {
557 $exception = true;
558 }
559 $this->assertTrue( isset( $result['upload'] ) );
560 $this->assertEquals( 'Success', $result['upload']['result'] );
561 $this->assertFalse( $exception );
562
563 // clean up
564 $this->deleteFileByFilename( $fileName );
565 // don't remove downloaded temporary file for fast subquent tests.
566 //unlink( $filePath );
567 }
568 }