9 * n.b. Ensure that you can write to the images/ directory as the
10 * user that will run tests.
13 // Note for reviewers: this intentionally duplicates functionality already in "ApiSetup" and so on.
14 // This framework works better IMO and has less strangeness (such as test cases inheriting from "ApiSetup"...)
15 // (and in the case of the other Upload tests, this flat out just actually works... )
17 // TODO: port the other Upload tests, and other API tests to this framework
19 require_once( 'ApiTestCaseUpload.php' );
24 * Broken test, reports false errors from time to time.
25 * See https://bugzilla.wikimedia.org/26169
27 * This is pretty sucky... needs to be prettified.
29 class ApiUploadTest
extends ApiTestCaseUpload
{
33 * XXX this is a funny way of getting session context
35 function testLogin() {
36 $user = self
::$users['uploader'];
40 'lgname' => $user->username
,
41 'lgpassword' => $user->password
43 list( $result, , $session ) = $this->doApiRequest( $params );
44 $this->assertArrayHasKey( "login", $result );
45 $this->assertArrayHasKey( "result", $result['login'] );
46 $this->assertEquals( "NeedToken", $result['login']['result'] );
47 $token = $result['login']['token'];
52 'lgname' => $user->username
,
53 'lgpassword' => $user->password
55 list( $result, , $session ) = $this->doApiRequest( $params, $session );
56 $this->assertArrayHasKey( "login", $result );
57 $this->assertArrayHasKey( "result", $result['login'] );
58 $this->assertEquals( "Success", $result['login']['result'] );
59 $this->assertArrayHasKey( 'lgtoken', $result['login'] );
61 $this->assertNotEmpty( $session, 'API Login must return a session' );
69 public function testUploadRequiresToken( $session ) {
72 $this->doApiRequest( array(
75 } catch ( UsageException
$e ) {
77 $this->assertEquals( "The token parameter must be set", $e->getMessage() );
79 $this->assertTrue( $exception, "Got exception" );
85 public function testUploadMissingParams( $session ) {
88 $this->doApiRequestWithToken( array(
90 ), $session, self
::$users['uploader']->user
);
91 } catch ( UsageException
$e ) {
93 $this->assertEquals( "One of the parameters filekey, file, url, statuskey is required",
96 $this->assertTrue( $exception, "Got exception" );
103 public function testUpload( $session ) {
105 $mimeType = 'image/png';
108 $randomImageGenerator = new RandomImageGenerator();
109 $filePaths = $randomImageGenerator->writeImages( 1, $extension, wfTempDir() );
111 catch ( Exception
$e ) {
112 $this->markTestIncomplete( $e->getMessage() );
115 $filePath = $filePaths[0];
116 $fileSize = filesize( $filePath );
117 $fileName = basename( $filePath );
119 $this->deleteFileByFileName( $fileName );
120 $this->deleteFileByContent( $filePath );
123 if (! $this->fakeUploadFile( 'file', $fileName, $mimeType, $filePath ) ) {
124 $this->markTestIncomplete( "Couldn't upload file!\n" );
128 'action' => 'upload',
129 'filename' => $fileName,
130 'file' => 'dummy content',
131 'comment' => 'dummy comment',
132 'text' => "This is the page text for $fileName",
137 list( $result, , ) = $this->doApiRequestWithToken( $params, $session,
138 self
::$users['uploader']->user
);
139 } catch ( UsageException
$e ) {
142 $this->assertTrue( isset( $result['upload'] ) );
143 $this->assertEquals( 'Success', $result['upload']['result'] );
144 $this->assertEquals( $fileSize, ( int )$result['upload']['imageinfo']['size'] );
145 $this->assertEquals( $mimeType, $result['upload']['imageinfo']['mime'] );
146 $this->assertFalse( $exception );
149 $this->deleteFileByFilename( $fileName );
157 public function testUploadZeroLength( $session ) {
158 $mimeType = 'image/png';
160 $filePath = tempnam( wfTempDir(), "" );
161 $fileName = "apiTestUploadZeroLength.png";
163 $this->deleteFileByFileName( $fileName );
165 if (! $this->fakeUploadFile( 'file', $fileName, $mimeType, $filePath ) ) {
166 $this->markTestIncomplete( "Couldn't upload file!\n" );
170 'action' => 'upload',
171 'filename' => $fileName,
172 'file' => 'dummy content',
173 'comment' => 'dummy comment',
174 'text' => "This is the page text for $fileName",
179 $this->doApiRequestWithToken( $params, $session, self
::$users['uploader']->user
);
180 } catch ( UsageException
$e ) {
181 $this->assertContains( 'The file you submitted was empty', $e->getMessage() );
184 $this->assertTrue( $exception );
187 $this->deleteFileByFilename( $fileName );
195 public function testUploadSameFileName( $session ) {
197 $mimeType = 'image/png';
200 $randomImageGenerator = new RandomImageGenerator();
201 $filePaths = $randomImageGenerator->writeImages( 2, $extension, wfTempDir() );
203 catch ( Exception
$e ) {
204 $this->markTestIncomplete( $e->getMessage() );
207 // we'll reuse this filename
208 $fileName = basename( $filePaths[0] );
210 // clear any other files with the same name
211 $this->deleteFileByFileName( $fileName );
213 // we reuse these params
215 'action' => 'upload',
216 'filename' => $fileName,
217 'file' => 'dummy content',
218 'comment' => 'dummy comment',
219 'text' => "This is the page text for $fileName",
222 // first upload .... should succeed
224 if (! $this->fakeUploadFile( 'file', $fileName, $mimeType, $filePaths[0] ) ) {
225 $this->markTestIncomplete( "Couldn't upload file!\n" );
230 list( $result, , $session ) = $this->doApiRequestWithToken( $params, $session,
231 self
::$users['uploader']->user
);
232 } catch ( UsageException
$e ) {
235 $this->assertTrue( isset( $result['upload'] ) );
236 $this->assertEquals( 'Success', $result['upload']['result'] );
237 $this->assertFalse( $exception );
239 // second upload with the same name (but different content)
241 if (! $this->fakeUploadFile( 'file', $fileName, $mimeType, $filePaths[1] ) ) {
242 $this->markTestIncomplete( "Couldn't upload file!\n" );
247 list( $result, , ) = $this->doApiRequestWithToken( $params, $session,
248 self
::$users['uploader']->user
); // FIXME: leaks a temporary file
249 } catch ( UsageException
$e ) {
252 $this->assertTrue( isset( $result['upload'] ) );
253 $this->assertEquals( 'Warning', $result['upload']['result'] );
254 $this->assertTrue( isset( $result['upload']['warnings'] ) );
255 $this->assertTrue( isset( $result['upload']['warnings']['exists'] ) );
256 $this->assertFalse( $exception );
259 $this->deleteFileByFilename( $fileName );
260 unlink( $filePaths[0] );
261 unlink( $filePaths[1] );
268 public function testUploadSameContent( $session ) {
270 $mimeType = 'image/png';
273 $randomImageGenerator = new RandomImageGenerator();
274 $filePaths = $randomImageGenerator->writeImages( 1, $extension, wfTempDir() );
276 catch ( Exception
$e ) {
277 $this->markTestIncomplete( $e->getMessage() );
280 $fileNames[0] = basename( $filePaths[0] );
281 $fileNames[1] = "SameContentAs" . $fileNames[0];
283 // clear any other files with the same name or content
284 $this->deleteFileByContent( $filePaths[0] );
285 $this->deleteFileByFileName( $fileNames[0] );
286 $this->deleteFileByFileName( $fileNames[1] );
288 // first upload .... should succeed
291 'action' => 'upload',
292 'filename' => $fileNames[0],
293 'file' => 'dummy content',
294 'comment' => 'dummy comment',
295 'text' => "This is the page text for " . $fileNames[0],
298 if (! $this->fakeUploadFile( 'file', $fileNames[0], $mimeType, $filePaths[0] ) ) {
299 $this->markTestIncomplete( "Couldn't upload file!\n" );
304 list( $result, $request, $session ) = $this->doApiRequestWithToken( $params, $session,
305 self
::$users['uploader']->user
);
306 } catch ( UsageException
$e ) {
309 $this->assertTrue( isset( $result['upload'] ) );
310 $this->assertEquals( 'Success', $result['upload']['result'] );
311 $this->assertFalse( $exception );
314 // second upload with the same content (but different name)
316 if (! $this->fakeUploadFile( 'file', $fileNames[1], $mimeType, $filePaths[0] ) ) {
317 $this->markTestIncomplete( "Couldn't upload file!\n" );
321 'action' => 'upload',
322 'filename' => $fileNames[1],
323 'file' => 'dummy content',
324 'comment' => 'dummy comment',
325 'text' => "This is the page text for " . $fileNames[1],
330 list( $result, $request, $session ) = $this->doApiRequestWithToken( $params, $session,
331 self
::$users['uploader']->user
); // FIXME: leaks a temporary file
332 } catch ( UsageException
$e ) {
335 $this->assertTrue( isset( $result['upload'] ) );
336 $this->assertEquals( 'Warning', $result['upload']['result'] );
337 $this->assertTrue( isset( $result['upload']['warnings'] ) );
338 $this->assertTrue( isset( $result['upload']['warnings']['duplicate'] ) );
339 $this->assertFalse( $exception );
342 $this->deleteFileByFilename( $fileNames[0] );
343 $this->deleteFileByFilename( $fileNames[1] );
344 unlink( $filePaths[0] );
351 public function testUploadStash( $session ) {
353 $wgUser = self
::$users['uploader']->user
; // @todo FIXME: still used somewhere
356 $mimeType = 'image/png';
359 $randomImageGenerator = new RandomImageGenerator();
360 $filePaths = $randomImageGenerator->writeImages( 1, $extension, wfTempDir() );
362 catch ( Exception
$e ) {
363 $this->markTestIncomplete( $e->getMessage() );
366 $filePath = $filePaths[0];
367 $fileSize = filesize( $filePath );
368 $fileName = basename( $filePath );
370 $this->deleteFileByFileName( $fileName );
371 $this->deleteFileByContent( $filePath );
373 if (! $this->fakeUploadFile( 'file', $fileName, $mimeType, $filePath ) ) {
374 $this->markTestIncomplete( "Couldn't upload file!\n" );
378 'action' => 'upload',
380 'filename' => $fileName,
381 'file' => 'dummy content',
382 'comment' => 'dummy comment',
383 'text' => "This is the page text for $fileName",
388 list( $result, $request, $session ) = $this->doApiRequestWithToken( $params, $session,
389 self
::$users['uploader']->user
); // FIXME: leaks a temporary file
390 } catch ( UsageException
$e ) {
393 $this->assertFalse( $exception );
394 $this->assertTrue( isset( $result['upload'] ) );
395 $this->assertEquals( 'Success', $result['upload']['result'] );
396 $this->assertEquals( $fileSize, ( int )$result['upload']['imageinfo']['size'] );
397 $this->assertEquals( $mimeType, $result['upload']['imageinfo']['mime'] );
398 $this->assertTrue( isset( $result['upload']['filekey'] ) );
399 $this->assertEquals( $result['upload']['sessionkey'], $result['upload']['filekey'] );
400 $filekey = $result['upload']['filekey'];
402 // it should be visible from Special:UploadStash
403 // XXX ...but how to test this, with a fake WebRequest with the session?
405 // now we should try to release the file from stash
407 'action' => 'upload',
408 'filekey' => $filekey,
409 'filename' => $fileName,
410 'comment' => 'dummy comment',
411 'text' => "This is the page text for $fileName, altered",
414 $this->clearFakeUploads();
417 list( $result, $request, $session ) = $this->doApiRequestWithToken( $params, $session,
418 self
::$users['uploader']->user
);
419 } catch ( UsageException
$e ) {
422 $this->assertTrue( isset( $result['upload'] ) );
423 $this->assertEquals( 'Success', $result['upload']['result'] );
424 $this->assertFalse( $exception, "No UsageException exception." );
427 $this->deleteFileByFilename( $fileName );
435 public function testUploadChunks( $session ) {
437 $wgUser = self
::$users['uploader']->user
; // @todo FIXME: still used somewhere
439 $chunkSize = 1048576;
440 // Download a large image file
441 // ( using RandomImageGenerator for large files is not stable )
442 $mimeType = 'image/jpeg';
443 $url = 'http://upload.wikimedia.org/wikipedia/commons/e/ed/Oberaargletscher_from_Oberaar%2C_2010_07.JPG';
444 $filePath = wfTempDir() . '/Oberaargletscher_from_Oberaar.jpg';
446 // Only download if the file is not avaliable in the temp location:
447 if( !is_file( $filePath ) ){
448 copy($url, $filePath);
451 catch ( Exception
$e ) {
452 $this->markTestIncomplete( $e->getMessage() );
455 $fileSize = filesize( $filePath );
456 $fileName = basename( $filePath );
458 $this->deleteFileByFileName( $fileName );
459 $this->deleteFileByContent( $filePath );
461 // Base upload params:
463 'action' => 'upload',
465 'filename' => $fileName,
466 'filesize' => $fileSize,
471 $chunkSessionKey = false;
474 $handle = @fopen
($filePath, "r");
475 if( $handle === false ){
476 $this->markTestIncomplete( "could not open file: $filePath" );
478 while (!feof ($handle)) {
479 // Get the current chunk
480 $chunkData = @fread
( $handle, $chunkSize );
482 // Upload the current chunk into the $_FILE object:
483 $this->fakeUploadChunk( 'chunk', 'blob', $mimeType, $chunkData );
485 // Check for chunkSessionKey
486 if( !$chunkSessionKey ){
487 // Upload fist chunk ( and get the session key )
489 list( $result, $request, $session ) = $this->doApiRequestWithToken( $params, $session,
490 self
::$users['uploader']->user
);
491 } catch ( UsageException
$e ) {
492 $this->markTestIncomplete( $e->getMessage() );
494 // Make sure we got a valid chunk continue:
495 $this->assertTrue( isset( $result['upload'] ) );
496 $this->assertTrue( isset( $result['upload']['filekey'] ) );
497 // If we don't get a session key mark test incomplete.
498 if( ! isset( $result['upload']['filekey'] ) ){
499 $this->markTestIncomplete( "no filekey provided" );
501 $chunkSessionKey = $result['upload']['filekey'];
502 $this->assertEquals( 'Continue', $result['upload']['result'] );
503 // First chunk should have chunkSize == offset
504 $this->assertEquals( $chunkSize, $result['upload']['offset'] );
505 $resultOffset = $result['upload']['offset'];
508 // Filekey set to chunk session
509 $params['filekey'] = $chunkSessionKey;
510 // Update the offset ( always add chunkSize for subquent chunks should be in-sync with $result['upload']['offset'] )
511 $params['offset'] +
= $chunkSize;
512 // Make sure param offset is insync with resultOffset:
513 $this->assertEquals( $resultOffset, $params['offset'] );
514 // Upload current chunk
516 list( $result, $request, $session ) = $this->doApiRequestWithToken( $params, $session,
517 self
::$users['uploader']->user
);
518 } catch ( UsageException
$e ) {
519 $this->markTestIncomplete( $e->getMessage() );
521 // Make sure we got a valid chunk continue:
522 $this->assertTrue( isset( $result['upload'] ) );
523 $this->assertTrue( isset( $result['upload']['filekey'] ) );
525 // Check if we were on the last chunk:
526 if( $params['offset'] +
$chunkSize >= $fileSize ){
527 $this->assertEquals( 'Success', $result['upload']['result'] );
530 $this->assertEquals( 'Continue', $result['upload']['result'] );
531 // update $resultOffset
532 $resultOffset = $result['upload']['offset'];
537 // Check that we got a valid file result:
538 wfDebug( __METHOD__
. " hohoh filesize {$fileSize} info {$result['upload']['imageinfo']['size']}\n\n");
539 $this->assertEquals( $fileSize, $result['upload']['imageinfo']['size'] );
540 $this->assertEquals( $mimeType, $result['upload']['imageinfo']['mime'] );
541 $this->assertTrue( isset( $result['upload']['filekey'] ) );
542 $filekey = $result['upload']['filekey'];
544 // Now we should try to release the file from stash
546 'action' => 'upload',
547 'filekey' => $filekey,
548 'filename' => $fileName,
549 'comment' => 'dummy comment',
550 'text' => "This is the page text for $fileName, altered",
552 $this->clearFakeUploads();
555 list( $result, $request, $session ) = $this->doApiRequestWithToken( $params, $session,
556 self
::$users['uploader']->user
);
557 } catch ( UsageException
$e ) {
560 $this->assertTrue( isset( $result['upload'] ) );
561 $this->assertEquals( 'Success', $result['upload']['result'] );
562 $this->assertFalse( $exception );
565 $this->deleteFileByFilename( $fileName );
566 // don't remove downloaded temporary file for fast subquent tests.
567 //unlink( $filePath );