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