MediaWiki
REL1_21
|
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 }