MediaWiki
REL1_24
|
00001 <?php 00013 // Note for reviewers: this intentionally duplicates functionality already in 00014 // "ApiSetup" and so on. This framework works better IMO and has less 00015 // strangeness (such as test cases inheriting from "ApiSetup"...) (and in the 00016 // case of the other Upload tests, this flat out just actually works... ) 00017 00018 // @todo Port the other Upload tests, and other API tests to this framework 00019 00020 require_once 'ApiTestCaseUpload.php'; 00021 00030 class ApiUploadTest extends ApiTestCaseUpload { 00035 public 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 00063 return $session; 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 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 00114 $filePath = $filePaths[0]; 00115 $fileSize = filesize( $filePath ); 00116 $fileName = basename( $filePath ); 00117 00118 $this->deleteFileByFileName( $fileName ); 00119 $this->deleteFileByContent( $filePath ); 00120 00121 if ( !$this->fakeUploadFile( 'file', $fileName, $mimeType, $filePath ) ) { 00122 $this->markTestIncomplete( "Couldn't upload file!\n" ); 00123 } 00124 00125 $params = array( 00126 'action' => 'upload', 00127 'filename' => $fileName, 00128 'file' => 'dummy content', 00129 'comment' => 'dummy comment', 00130 'text' => "This is the page text for $fileName", 00131 ); 00132 00133 $exception = false; 00134 try { 00135 list( $result, , ) = $this->doApiRequestWithToken( $params, $session, 00136 self::$users['uploader']->user ); 00137 } catch ( UsageException $e ) { 00138 $exception = true; 00139 } 00140 $this->assertTrue( isset( $result['upload'] ) ); 00141 $this->assertEquals( 'Success', $result['upload']['result'] ); 00142 $this->assertEquals( $fileSize, (int)$result['upload']['imageinfo']['size'] ); 00143 $this->assertEquals( $mimeType, $result['upload']['imageinfo']['mime'] ); 00144 $this->assertFalse( $exception ); 00145 00146 // clean up 00147 $this->deleteFileByFilename( $fileName ); 00148 unlink( $filePath ); 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 00191 public function testUploadSameFileName( $session ) { 00192 $extension = 'png'; 00193 $mimeType = 'image/png'; 00194 00195 try { 00196 $randomImageGenerator = new RandomImageGenerator(); 00197 $filePaths = $randomImageGenerator->writeImages( 2, $extension, wfTempDir() ); 00198 } catch ( Exception $e ) { 00199 $this->markTestIncomplete( $e->getMessage() ); 00200 } 00201 00202 // 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 00263 public function testUploadSameContent( $session ) { 00264 $extension = 'png'; 00265 $mimeType = 'image/png'; 00266 00267 try { 00268 $randomImageGenerator = new RandomImageGenerator(); 00269 $filePaths = $randomImageGenerator->writeImages( 1, $extension, wfTempDir() ); 00270 } catch ( Exception $e ) { 00271 $this->markTestIncomplete( $e->getMessage() ); 00272 } 00273 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 00360 $filePath = $filePaths[0]; 00361 $fileSize = filesize( $filePath ); 00362 $fileName = basename( $filePath ); 00363 00364 $this->deleteFileByFileName( $fileName ); 00365 $this->deleteFileByContent( $filePath ); 00366 00367 if ( !$this->fakeUploadFile( 'file', $fileName, $mimeType, $filePath ) ) { 00368 $this->markTestIncomplete( "Couldn't upload file!\n" ); 00369 } 00370 00371 $params = array( 00372 'action' => 'upload', 00373 'stash' => 1, 00374 'filename' => $fileName, 00375 'file' => 'dummy content', 00376 'comment' => 'dummy comment', 00377 'text' => "This is the page text for $fileName", 00378 ); 00379 00380 $exception = false; 00381 try { 00382 list( $result, , $session ) = $this->doApiRequestWithToken( $params, $session, 00383 self::$users['uploader']->user ); // FIXME: leaks a temporary file 00384 } catch ( UsageException $e ) { 00385 $exception = true; 00386 } 00387 $this->assertFalse( $exception ); 00388 $this->assertTrue( isset( $result['upload'] ) ); 00389 $this->assertEquals( 'Success', $result['upload']['result'] ); 00390 $this->assertEquals( $fileSize, (int)$result['upload']['imageinfo']['size'] ); 00391 $this->assertEquals( $mimeType, $result['upload']['imageinfo']['mime'] ); 00392 $this->assertTrue( isset( $result['upload']['filekey'] ) ); 00393 $this->assertEquals( $result['upload']['sessionkey'], $result['upload']['filekey'] ); 00394 $filekey = $result['upload']['filekey']; 00395 00396 // it should be visible from Special:UploadStash 00397 // XXX ...but how to test this, with a fake WebRequest with the session? 00398 00399 // now we should try to release the file from stash 00400 $params = array( 00401 'action' => 'upload', 00402 'filekey' => $filekey, 00403 'filename' => $fileName, 00404 'comment' => 'dummy comment', 00405 'text' => "This is the page text for $fileName, altered", 00406 ); 00407 00408 $this->clearFakeUploads(); 00409 $exception = false; 00410 try { 00411 list( $result ) = $this->doApiRequestWithToken( $params, $session, 00412 self::$users['uploader']->user ); 00413 } catch ( UsageException $e ) { 00414 $exception = true; 00415 } 00416 $this->assertTrue( isset( $result['upload'] ) ); 00417 $this->assertEquals( 'Success', $result['upload']['result'] ); 00418 $this->assertFalse( $exception, "No UsageException exception." ); 00419 00420 // clean up 00421 $this->deleteFileByFilename( $fileName ); 00422 unlink( $filePath ); 00423 } 00424 00428 public function testUploadChunks( $session ) { 00429 $this->setMwGlobals( array( 00430 // @todo FIXME: still used somewhere 00431 'wgUser' => self::$users['uploader']->user, 00432 ) ); 00433 00434 $chunkSize = 1048576; 00435 // Download a large image file 00436 // ( using RandomImageGenerator for large files is not stable ) 00437 $mimeType = 'image/jpeg'; 00438 $url = 'http://upload.wikimedia.org/wikipedia/commons/' 00439 . 'e/ed/Oberaargletscher_from_Oberaar%2C_2010_07.JPG'; 00440 $filePath = wfTempDir() . '/Oberaargletscher_from_Oberaar.jpg'; 00441 try { 00442 // Only download if the file is not avaliable in the temp location: 00443 if ( !is_file( $filePath ) ) { 00444 copy( $url, $filePath ); 00445 } 00446 } catch ( Exception $e ) { 00447 $this->markTestIncomplete( $e->getMessage() ); 00448 } 00449 00450 $fileSize = filesize( $filePath ); 00451 $fileName = basename( $filePath ); 00452 00453 $this->deleteFileByFileName( $fileName ); 00454 $this->deleteFileByContent( $filePath ); 00455 00456 // Base upload params: 00457 $params = array( 00458 'action' => 'upload', 00459 'stash' => 1, 00460 'filename' => $fileName, 00461 'filesize' => $fileSize, 00462 'offset' => 0, 00463 ); 00464 00465 // Upload chunks 00466 $chunkSessionKey = false; 00467 $resultOffset = 0; 00468 // Open the file: 00469 wfSuppressWarnings(); 00470 $handle = fopen( $filePath, "r" ); 00471 wfRestoreWarnings(); 00472 00473 if ( $handle === false ) { 00474 $this->markTestIncomplete( "could not open file: $filePath" ); 00475 } 00476 00477 while ( !feof( $handle ) ) { 00478 // Get the current chunk 00479 wfSuppressWarnings(); 00480 $chunkData = fread( $handle, $chunkSize ); 00481 wfRestoreWarnings(); 00482 00483 // Upload the current chunk into the $_FILE object: 00484 $this->fakeUploadChunk( 'chunk', 'blob', $mimeType, $chunkData ); 00485 00486 // Check for chunkSessionKey 00487 if ( !$chunkSessionKey ) { 00488 // Upload fist chunk ( and get the session key ) 00489 try { 00490 list( $result, , $session ) = $this->doApiRequestWithToken( $params, $session, 00491 self::$users['uploader']->user ); 00492 } catch ( UsageException $e ) { 00493 $this->markTestIncomplete( $e->getMessage() ); 00494 } 00495 // Make sure we got a valid chunk continue: 00496 $this->assertTrue( isset( $result['upload'] ) ); 00497 $this->assertTrue( isset( $result['upload']['filekey'] ) ); 00498 // If we don't get a session key mark test incomplete. 00499 if ( !isset( $result['upload']['filekey'] ) ) { 00500 $this->markTestIncomplete( "no filekey provided" ); 00501 } 00502 $chunkSessionKey = $result['upload']['filekey']; 00503 $this->assertEquals( 'Continue', $result['upload']['result'] ); 00504 // First chunk should have chunkSize == offset 00505 $this->assertEquals( $chunkSize, $result['upload']['offset'] ); 00506 $resultOffset = $result['upload']['offset']; 00507 continue; 00508 } 00509 // Filekey set to chunk session 00510 $params['filekey'] = $chunkSessionKey; 00511 // Update the offset ( always add chunkSize for subquent chunks 00512 // should be in-sync with $result['upload']['offset'] ) 00513 $params['offset'] += $chunkSize; 00514 // Make sure param offset is insync with resultOffset: 00515 $this->assertEquals( $resultOffset, $params['offset'] ); 00516 // Upload current chunk 00517 try { 00518 list( $result, , $session ) = $this->doApiRequestWithToken( $params, $session, 00519 self::$users['uploader']->user ); 00520 } catch ( UsageException $e ) { 00521 $this->markTestIncomplete( $e->getMessage() ); 00522 } 00523 // Make sure we got a valid chunk continue: 00524 $this->assertTrue( isset( $result['upload'] ) ); 00525 $this->assertTrue( isset( $result['upload']['filekey'] ) ); 00526 00527 // Check if we were on the last chunk: 00528 if ( $params['offset'] + $chunkSize >= $fileSize ) { 00529 $this->assertEquals( 'Success', $result['upload']['result'] ); 00530 break; 00531 } else { 00532 $this->assertEquals( 'Continue', $result['upload']['result'] ); 00533 // update $resultOffset 00534 $resultOffset = $result['upload']['offset']; 00535 } 00536 } 00537 fclose( $handle ); 00538 00539 // Check that we got a valid file result: 00540 wfDebug( __METHOD__ 00541 . " hohoh filesize {$fileSize} info {$result['upload']['imageinfo']['size']}\n\n" ); 00542 $this->assertEquals( $fileSize, $result['upload']['imageinfo']['size'] ); 00543 $this->assertEquals( $mimeType, $result['upload']['imageinfo']['mime'] ); 00544 $this->assertTrue( isset( $result['upload']['filekey'] ) ); 00545 $filekey = $result['upload']['filekey']; 00546 00547 // Now we should try to release the file from stash 00548 $params = array( 00549 'action' => 'upload', 00550 'filekey' => $filekey, 00551 'filename' => $fileName, 00552 'comment' => 'dummy comment', 00553 'text' => "This is the page text for $fileName, altered", 00554 ); 00555 $this->clearFakeUploads(); 00556 $exception = false; 00557 try { 00558 list( $result ) = $this->doApiRequestWithToken( $params, $session, 00559 self::$users['uploader']->user ); 00560 } catch ( UsageException $e ) { 00561 $exception = true; 00562 } 00563 $this->assertTrue( isset( $result['upload'] ) ); 00564 $this->assertEquals( 'Success', $result['upload']['result'] ); 00565 $this->assertFalse( $exception ); 00566 00567 // clean up 00568 $this->deleteFileByFilename( $fileName ); 00569 // don't remove downloaded temporary file for fast subquent tests. 00570 //unlink( $filePath ); 00571 } 00572 }