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