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