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