MediaWiki  REL1_21
ApiUploadTest.php
Go to the documentation of this file.
00001 <?php
00002 
00013 // Note for reviewers: this intentionally duplicates functionality already in "ApiSetup" and so on.
00014 // This framework works better IMO and has less strangeness (such as test cases inheriting from "ApiSetup"...)
00015 // (and in the case of the other Upload tests, this flat out just actually works... )
00016 
00017 // TODO: port the other Upload tests, and other API tests to this framework
00018 
00019 require_once( 'ApiTestCaseUpload.php' );
00020 
00029 class ApiUploadTest extends ApiTestCaseUpload {
00030 
00035         function testLogin() {
00036                 $user = self::$users['uploader'];
00037 
00038                 $params = array(
00039                         'action' => 'login',
00040                         'lgname' => $user->username,
00041                         'lgpassword' => $user->password
00042                 );
00043                 list( $result, , $session ) = $this->doApiRequest( $params );
00044                 $this->assertArrayHasKey( "login", $result );
00045                 $this->assertArrayHasKey( "result", $result['login'] );
00046                 $this->assertEquals( "NeedToken", $result['login']['result'] );
00047                 $token = $result['login']['token'];
00048 
00049                 $params = array(
00050                         'action' => 'login',
00051                         'lgtoken' => $token,
00052                         'lgname' => $user->username,
00053                         'lgpassword' => $user->password
00054                 );
00055                 list( $result, , $session ) = $this->doApiRequest( $params, $session );
00056                 $this->assertArrayHasKey( "login", $result );
00057                 $this->assertArrayHasKey( "result", $result['login'] );
00058                 $this->assertEquals( "Success", $result['login']['result'] );
00059                 $this->assertArrayHasKey( 'lgtoken', $result['login'] );
00060 
00061                 $this->assertNotEmpty( $session, 'API Login must return a session' );
00062                 return $session;
00063 
00064         }
00065 
00069         public function testUploadRequiresToken( $session ) {
00070                 $exception = false;
00071                 try {
00072                         $this->doApiRequest( array(
00073                                 'action' => 'upload'
00074                         ) );
00075                 } catch ( UsageException $e ) {
00076                         $exception = true;
00077                         $this->assertEquals( "The token parameter must be set", $e->getMessage() );
00078                 }
00079                 $this->assertTrue( $exception, "Got exception" );
00080         }
00081 
00085         public function testUploadMissingParams( $session ) {
00086                 $exception = false;
00087                 try {
00088                         $this->doApiRequestWithToken( array(
00089                                 'action' => 'upload',
00090                         ), $session, self::$users['uploader']->user );
00091                 } catch ( UsageException $e ) {
00092                         $exception = true;
00093                         $this->assertEquals( "One of the parameters filekey, file, url, statuskey is required",
00094                                 $e->getMessage() );
00095                 }
00096                 $this->assertTrue( $exception, "Got exception" );
00097         }
00098 
00099 
00103         public function testUpload( $session ) {
00104                 $extension = 'png';
00105                 $mimeType = 'image/png';
00106 
00107                 try {
00108                         $randomImageGenerator = new RandomImageGenerator();
00109                         $filePaths = $randomImageGenerator->writeImages( 1, $extension, wfTempDir() );
00110                 } catch ( Exception $e ) {
00111                         $this->markTestIncomplete( $e->getMessage() );
00112                 }
00113 
00114                 $filePath = $filePaths[0];
00115                 $fileSize = filesize( $filePath );
00116                 $fileName = basename( $filePath );
00117 
00118                 $this->deleteFileByFileName( $fileName );
00119                 $this->deleteFileByContent( $filePath );
00120 
00121 
00122                 if ( !$this->fakeUploadFile( 'file', $fileName, $mimeType, $filePath ) ) {
00123                         $this->markTestIncomplete( "Couldn't upload file!\n" );
00124                 }
00125 
00126                 $params = array(
00127                         'action' => 'upload',
00128                         'filename' => $fileName,
00129                         'file' => 'dummy content',
00130                         'comment' => 'dummy comment',
00131                         'text' => "This is the page text for $fileName",
00132                 );
00133 
00134                 $exception = false;
00135                 try {
00136                         list( $result, , ) = $this->doApiRequestWithToken( $params, $session,
00137                                 self::$users['uploader']->user );
00138                 } catch ( UsageException $e ) {
00139                         $exception = true;
00140                 }
00141                 $this->assertTrue( isset( $result['upload'] ) );
00142                 $this->assertEquals( 'Success', $result['upload']['result'] );
00143                 $this->assertEquals( $fileSize, ( int )$result['upload']['imageinfo']['size'] );
00144                 $this->assertEquals( $mimeType, $result['upload']['imageinfo']['mime'] );
00145                 $this->assertFalse( $exception );
00146 
00147                 // clean up
00148                 $this->deleteFileByFilename( $fileName );
00149                 unlink( $filePath );
00150         }
00151 
00152 
00156         public function testUploadZeroLength( $session ) {
00157                 $mimeType = 'image/png';
00158 
00159                 $filePath = tempnam( wfTempDir(), "" );
00160                 $fileName = "apiTestUploadZeroLength.png";
00161 
00162                 $this->deleteFileByFileName( $fileName );
00163 
00164                 if ( !$this->fakeUploadFile( 'file', $fileName, $mimeType, $filePath ) ) {
00165                         $this->markTestIncomplete( "Couldn't upload file!\n" );
00166                 }
00167 
00168                 $params = array(
00169                         'action' => 'upload',
00170                         'filename' => $fileName,
00171                         'file' => 'dummy content',
00172                         'comment' => 'dummy comment',
00173                         'text' => "This is the page text for $fileName",
00174                 );
00175 
00176                 $exception = false;
00177                 try {
00178                         $this->doApiRequestWithToken( $params, $session, self::$users['uploader']->user );
00179                 } catch ( UsageException $e ) {
00180                         $this->assertContains( 'The file you submitted was empty', $e->getMessage() );
00181                         $exception = true;
00182                 }
00183                 $this->assertTrue( $exception );
00184 
00185                 // clean up
00186                 $this->deleteFileByFilename( $fileName );
00187                 unlink( $filePath );
00188         }
00189 
00190 
00194         public function testUploadSameFileName( $session ) {
00195                 $extension = 'png';
00196                 $mimeType = 'image/png';
00197 
00198                 try {
00199                         $randomImageGenerator = new RandomImageGenerator();
00200                         $filePaths = $randomImageGenerator->writeImages( 2, $extension, wfTempDir() );
00201                 } catch ( Exception $e ) {
00202                         $this->markTestIncomplete( $e->getMessage() );
00203                 }
00204 
00205                 // we'll reuse this filename
00206                 $fileName = basename( $filePaths[0] );
00207 
00208                 // clear any other files with the same name
00209                 $this->deleteFileByFileName( $fileName );
00210 
00211                 // we reuse these params
00212                 $params = array(
00213                         'action' => 'upload',
00214                         'filename' => $fileName,
00215                         'file' => 'dummy content',
00216                         'comment' => 'dummy comment',
00217                         'text' => "This is the page text for $fileName",
00218                 );
00219 
00220                 // first upload .... should succeed
00221 
00222                 if ( !$this->fakeUploadFile( 'file', $fileName, $mimeType, $filePaths[0] ) ) {
00223                         $this->markTestIncomplete( "Couldn't upload file!\n" );
00224                 }
00225 
00226                 $exception = false;
00227                 try {
00228                         list( $result, , $session ) = $this->doApiRequestWithToken( $params, $session,
00229                                 self::$users['uploader']->user );
00230                 } catch ( UsageException $e ) {
00231                         $exception = true;
00232                 }
00233                 $this->assertTrue( isset( $result['upload'] ) );
00234                 $this->assertEquals( 'Success', $result['upload']['result'] );
00235                 $this->assertFalse( $exception );
00236 
00237                 // second upload with the same name (but different content)
00238 
00239                 if ( !$this->fakeUploadFile( 'file', $fileName, $mimeType, $filePaths[1] ) ) {
00240                         $this->markTestIncomplete( "Couldn't upload file!\n" );
00241                 }
00242 
00243                 $exception = false;
00244                 try {
00245                         list( $result, , ) = $this->doApiRequestWithToken( $params, $session,
00246                                 self::$users['uploader']->user ); // FIXME: leaks a temporary file
00247                 } catch ( UsageException $e ) {
00248                         $exception = true;
00249                 }
00250                 $this->assertTrue( isset( $result['upload'] ) );
00251                 $this->assertEquals( 'Warning', $result['upload']['result'] );
00252                 $this->assertTrue( isset( $result['upload']['warnings'] ) );
00253                 $this->assertTrue( isset( $result['upload']['warnings']['exists'] ) );
00254                 $this->assertFalse( $exception );
00255 
00256                 // clean up
00257                 $this->deleteFileByFilename( $fileName );
00258                 unlink( $filePaths[0] );
00259                 unlink( $filePaths[1] );
00260         }
00261 
00262 
00266         public function testUploadSameContent( $session ) {
00267                 $extension = 'png';
00268                 $mimeType = 'image/png';
00269 
00270                 try {
00271                         $randomImageGenerator = new RandomImageGenerator();
00272                         $filePaths = $randomImageGenerator->writeImages( 1, $extension, wfTempDir() );
00273                 } catch ( Exception $e ) {
00274                         $this->markTestIncomplete( $e->getMessage() );
00275                 }
00276 
00277                 $fileNames[0] = basename( $filePaths[0] );
00278                 $fileNames[1] = "SameContentAs" . $fileNames[0];
00279 
00280                 // clear any other files with the same name or content
00281                 $this->deleteFileByContent( $filePaths[0] );
00282                 $this->deleteFileByFileName( $fileNames[0] );
00283                 $this->deleteFileByFileName( $fileNames[1] );
00284 
00285                 // first upload .... should succeed
00286 
00287                 $params = array(
00288                         'action' => 'upload',
00289                         'filename' => $fileNames[0],
00290                         'file' => 'dummy content',
00291                         'comment' => 'dummy comment',
00292                         'text' => "This is the page text for " . $fileNames[0],
00293                 );
00294 
00295                 if ( !$this->fakeUploadFile( 'file', $fileNames[0], $mimeType, $filePaths[0] ) ) {
00296                         $this->markTestIncomplete( "Couldn't upload file!\n" );
00297                 }
00298 
00299                 $exception = false;
00300                 try {
00301                         list( $result, $request, $session ) = $this->doApiRequestWithToken( $params, $session,
00302                                 self::$users['uploader']->user );
00303                 } catch ( UsageException $e ) {
00304                         $exception = true;
00305                 }
00306                 $this->assertTrue( isset( $result['upload'] ) );
00307                 $this->assertEquals( 'Success', $result['upload']['result'] );
00308                 $this->assertFalse( $exception );
00309 
00310 
00311                 // second upload with the same content (but different name)
00312 
00313                 if ( !$this->fakeUploadFile( 'file', $fileNames[1], $mimeType, $filePaths[0] ) ) {
00314                         $this->markTestIncomplete( "Couldn't upload file!\n" );
00315                 }
00316 
00317                 $params = array(
00318                         'action' => 'upload',
00319                         'filename' => $fileNames[1],
00320                         'file' => 'dummy content',
00321                         'comment' => 'dummy comment',
00322                         'text' => "This is the page text for " . $fileNames[1],
00323                 );
00324 
00325                 $exception = false;
00326                 try {
00327                         list( $result, $request, $session ) = $this->doApiRequestWithToken( $params, $session,
00328                                 self::$users['uploader']->user ); // FIXME: leaks a temporary file
00329                 } catch ( UsageException $e ) {
00330                         $exception = true;
00331                 }
00332                 $this->assertTrue( isset( $result['upload'] ) );
00333                 $this->assertEquals( 'Warning', $result['upload']['result'] );
00334                 $this->assertTrue( isset( $result['upload']['warnings'] ) );
00335                 $this->assertTrue( isset( $result['upload']['warnings']['duplicate'] ) );
00336                 $this->assertFalse( $exception );
00337 
00338                 // clean up
00339                 $this->deleteFileByFilename( $fileNames[0] );
00340                 $this->deleteFileByFilename( $fileNames[1] );
00341                 unlink( $filePaths[0] );
00342         }
00343 
00344 
00348         public function testUploadStash( $session ) {
00349                 $this->setMwGlobals( array(
00350                         'wgUser' => self::$users['uploader']->user, // @todo FIXME: still used somewhere
00351                 ) );
00352 
00353                 $extension = 'png';
00354                 $mimeType = 'image/png';
00355 
00356                 try {
00357                         $randomImageGenerator = new RandomImageGenerator();
00358                         $filePaths = $randomImageGenerator->writeImages( 1, $extension, wfTempDir() );
00359                 } catch ( Exception $e ) {
00360                         $this->markTestIncomplete( $e->getMessage() );
00361                 }
00362 
00363                 $filePath = $filePaths[0];
00364                 $fileSize = filesize( $filePath );
00365                 $fileName = basename( $filePath );
00366 
00367                 $this->deleteFileByFileName( $fileName );
00368                 $this->deleteFileByContent( $filePath );
00369 
00370                 if ( !$this->fakeUploadFile( 'file', $fileName, $mimeType, $filePath ) ) {
00371                         $this->markTestIncomplete( "Couldn't upload file!\n" );
00372                 }
00373 
00374                 $params = array(
00375                         'action' => 'upload',
00376                         'stash' => 1,
00377                         'filename' => $fileName,
00378                         'file' => 'dummy content',
00379                         'comment' => 'dummy comment',
00380                         'text' => "This is the page text for $fileName",
00381                 );
00382 
00383                 $exception = false;
00384                 try {
00385                         list( $result, $request, $session ) = $this->doApiRequestWithToken( $params, $session,
00386                                 self::$users['uploader']->user ); // FIXME: leaks a temporary file
00387                 } catch ( UsageException $e ) {
00388                         $exception = true;
00389                 }
00390                 $this->assertFalse( $exception );
00391                 $this->assertTrue( isset( $result['upload'] ) );
00392                 $this->assertEquals( 'Success', $result['upload']['result'] );
00393                 $this->assertEquals( $fileSize, ( int )$result['upload']['imageinfo']['size'] );
00394                 $this->assertEquals( $mimeType, $result['upload']['imageinfo']['mime'] );
00395                 $this->assertTrue( isset( $result['upload']['filekey'] ) );
00396                 $this->assertEquals( $result['upload']['sessionkey'], $result['upload']['filekey'] );
00397                 $filekey = $result['upload']['filekey'];
00398 
00399                 // it should be visible from Special:UploadStash
00400                 // XXX ...but how to test this, with a fake WebRequest with the session?
00401 
00402                 // now we should try to release the file from stash
00403                 $params = array(
00404                         'action' => 'upload',
00405                         'filekey' => $filekey,
00406                         'filename' => $fileName,
00407                         'comment' => 'dummy comment',
00408                         'text' => "This is the page text for $fileName, altered",
00409                 );
00410 
00411                 $this->clearFakeUploads();
00412                 $exception = false;
00413                 try {
00414                         list( $result, $request, $session ) = $this->doApiRequestWithToken( $params, $session,
00415                                 self::$users['uploader']->user );
00416                 } catch ( UsageException $e ) {
00417                         $exception = true;
00418                 }
00419                 $this->assertTrue( isset( $result['upload'] ) );
00420                 $this->assertEquals( 'Success', $result['upload']['result'] );
00421                 $this->assertFalse( $exception, "No UsageException exception." );
00422 
00423                 // clean up
00424                 $this->deleteFileByFilename( $fileName );
00425                 unlink( $filePath );
00426         }
00427 
00431         public function testUploadChunks( $session ) {
00432                 $this->setMwGlobals( array(
00433                         'wgUser' => self::$users['uploader']->user, // @todo FIXME: still used somewhere
00434                 ) );
00435 
00436                 $chunkSize = 1048576;
00437                 // Download a large image file
00438                 // ( using RandomImageGenerator for large files is not stable )
00439                 $mimeType = 'image/jpeg';
00440                 $url = 'http://upload.wikimedia.org/wikipedia/commons/e/ed/Oberaargletscher_from_Oberaar%2C_2010_07.JPG';
00441                 $filePath = wfTempDir() . '/Oberaargletscher_from_Oberaar.jpg';
00442                 try {
00443                         // Only download if the file is not avaliable in the temp location:
00444                         if ( !is_file( $filePath ) ) {
00445                                 copy( $url, $filePath );
00446                         }
00447                 } catch ( Exception $e ) {
00448                         $this->markTestIncomplete( $e->getMessage() );
00449                 }
00450 
00451                 $fileSize = filesize( $filePath );
00452                 $fileName = basename( $filePath );
00453 
00454                 $this->deleteFileByFileName( $fileName );
00455                 $this->deleteFileByContent( $filePath );
00456 
00457                 // Base upload params: 
00458                 $params = array(
00459                         'action' => 'upload',
00460                         'stash' => 1,
00461                         'filename' => $fileName,
00462                         'filesize' => $fileSize,
00463                         'offset' => 0,
00464                 );
00465 
00466                 // Upload chunks
00467                 $chunkSessionKey = false;
00468                 $resultOffset = 0;
00469                 // Open the file: 
00470                 $handle = @fopen( $filePath, "r" );
00471                 if ( $handle === false ) {
00472                         $this->markTestIncomplete( "could not open file: $filePath" );
00473                 }
00474                 while ( !feof( $handle ) ) {
00475                         // Get the current chunk
00476                         $chunkData = @fread( $handle, $chunkSize );
00477 
00478                         // Upload the current chunk into the $_FILE object:
00479                         $this->fakeUploadChunk( 'chunk', 'blob', $mimeType, $chunkData );
00480 
00481                         // Check for chunkSessionKey
00482                         if ( !$chunkSessionKey ) {
00483                                 // Upload fist chunk ( and get the session key )
00484                                 try {
00485                                         list( $result, $request, $session ) = $this->doApiRequestWithToken( $params, $session,
00486                                                 self::$users['uploader']->user );
00487                                 } catch ( UsageException $e ) {
00488                                         $this->markTestIncomplete( $e->getMessage() );
00489                                 }
00490                                 // Make sure we got a valid chunk continue: 
00491                                 $this->assertTrue( isset( $result['upload'] ) );
00492                                 $this->assertTrue( isset( $result['upload']['filekey'] ) );
00493                                 // If we don't get a session key mark test incomplete. 
00494                                 if ( !isset( $result['upload']['filekey'] ) ) {
00495                                         $this->markTestIncomplete( "no filekey provided" );
00496                                 }
00497                                 $chunkSessionKey = $result['upload']['filekey'];
00498                                 $this->assertEquals( 'Continue', $result['upload']['result'] );
00499                                 // First chunk should have chunkSize == offset
00500                                 $this->assertEquals( $chunkSize, $result['upload']['offset'] );
00501                                 $resultOffset = $result['upload']['offset'];
00502                                 continue;
00503                         }
00504                         // Filekey set to chunk session
00505                         $params['filekey'] = $chunkSessionKey;
00506                         // Update the offset ( always add chunkSize for subquent chunks should be in-sync with $result['upload']['offset'] )
00507                         $params['offset'] += $chunkSize;
00508                         // Make sure param offset is insync with resultOffset:
00509                         $this->assertEquals( $resultOffset, $params['offset'] );
00510                         // Upload current chunk
00511                         try {
00512                                 list( $result, $request, $session ) = $this->doApiRequestWithToken( $params, $session,
00513                                         self::$users['uploader']->user );
00514                         } catch ( UsageException $e ) {
00515                                 $this->markTestIncomplete( $e->getMessage() );
00516                         }
00517                         // Make sure we got a valid chunk continue: 
00518                         $this->assertTrue( isset( $result['upload'] ) );
00519                         $this->assertTrue( isset( $result['upload']['filekey'] ) );
00520 
00521                         // Check if we were on the last chunk: 
00522                         if ( $params['offset'] + $chunkSize >= $fileSize ) {
00523                                 $this->assertEquals( 'Success', $result['upload']['result'] );
00524                                 break;
00525                         } else {
00526                                 $this->assertEquals( 'Continue', $result['upload']['result'] );
00527                                 // update $resultOffset
00528                                 $resultOffset = $result['upload']['offset'];
00529                         }
00530                 }
00531                 fclose( $handle );
00532 
00533                 // Check that we got a valid file result:
00534                 wfDebug( __METHOD__ . " hohoh filesize {$fileSize} info {$result['upload']['imageinfo']['size']}\n\n" );
00535                 $this->assertEquals( $fileSize, $result['upload']['imageinfo']['size'] );
00536                 $this->assertEquals( $mimeType, $result['upload']['imageinfo']['mime'] );
00537                 $this->assertTrue( isset( $result['upload']['filekey'] ) );
00538                 $filekey = $result['upload']['filekey'];
00539 
00540                 // Now we should try to release the file from stash
00541                 $params = array(
00542                         'action' => 'upload',
00543                         'filekey' => $filekey,
00544                         'filename' => $fileName,
00545                         'comment' => 'dummy comment',
00546                         'text' => "This is the page text for $fileName, altered",
00547                 );
00548                 $this->clearFakeUploads();
00549                 $exception = false;
00550                 try {
00551                         list( $result, $request, $session ) = $this->doApiRequestWithToken( $params, $session,
00552                                 self::$users['uploader']->user );
00553                 } catch ( UsageException $e ) {
00554                         $exception = true;
00555                 }
00556                 $this->assertTrue( isset( $result['upload'] ) );
00557                 $this->assertEquals( 'Success', $result['upload']['result'] );
00558                 $this->assertFalse( $exception );
00559 
00560                 // clean up
00561                 $this->deleteFileByFilename( $fileName );
00562                 // don't remove downloaded temporary file for fast subquent tests. 
00563                 //unlink( $filePath );
00564         }
00565 }