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