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