From d9022f63880ce039446fba8364f68e656b7bf4cb Mon Sep 17 00:00:00 2001 From: Pierre Schmitz Date: Thu, 3 May 2012 13:01:35 +0200 Subject: Update to MediaWiki 1.19.0 --- tests/phpunit/includes/api/ApiBlockTest.php | 28 ++- tests/phpunit/includes/api/ApiPurgeTest.php | 34 ++-- tests/phpunit/includes/api/ApiQueryTest.php | 8 +- tests/phpunit/includes/api/ApiTest.php | 36 ++-- tests/phpunit/includes/api/ApiTestCase.php | 51 ++++-- tests/phpunit/includes/api/ApiTestCaseUpload.php | 40 ++++- tests/phpunit/includes/api/ApiTestUser.php | 2 +- tests/phpunit/includes/api/ApiUploadTest.php | 197 +++++++++++++++++---- tests/phpunit/includes/api/ApiWatchTest.php | 5 +- .../phpunit/includes/api/RandomImageGenerator.php | 124 ++++++------- 10 files changed, 364 insertions(+), 161 deletions(-) (limited to 'tests/phpunit/includes/api') diff --git a/tests/phpunit/includes/api/ApiBlockTest.php b/tests/phpunit/includes/api/ApiBlockTest.php index 227555eb..b95d8214 100644 --- a/tests/phpunit/includes/api/ApiBlockTest.php +++ b/tests/phpunit/includes/api/ApiBlockTest.php @@ -15,24 +15,34 @@ class ApiBlockTest extends ApiTestCase { } function addDBData() { - $user = User::newFromName( 'UTBlockee' ); + $user = User::newFromName( 'UTApiBlockee' ); if ( $user->getId() == 0 ) { $user->addToDatabase(); - $user->setPassword( 'UTBlockeePassword' ); + $user->setPassword( 'UTApiBlockeePassword' ); $user->saveSettings(); } } + /** + * This test has probably always been broken and use an invalid token + * Bug tracking brokenness is https://bugzilla.wikimedia.org/35646 + * + * Root cause is https://gerrit.wikimedia.org/r/3434 + * Which made the Block/Unblock API to actually verify the token + * previously always considered valid (bug 34212). + * + * @group Broken + */ function testMakeNormalBlock() { $data = $this->getTokens(); - $user = User::newFromName( 'UTBlockee' ); + $user = User::newFromName( 'UTApiBlockee' ); if ( !$user->getId() ) { - $this->markTestIncomplete( "The user UTBlockee does not exist" ); + $this->markTestIncomplete( "The user UTApiBlockee does not exist" ); } if( !isset( $data[0]['query']['pages'] ) ) { @@ -45,15 +55,15 @@ class ApiBlockTest extends ApiTestCase { $data = $this->doApiRequest( array( 'action' => 'block', - 'user' => 'UTBlockee', - 'reason' => BlockTest::REASON, - 'token' => $pageinfo['blocktoken'] ), $data ); + 'user' => 'UTApiBlockee', + 'reason' => 'Some reason', + 'token' => $pageinfo['blocktoken'] ), $data, false, self::$users['sysop']->user ); - $block = Block::newFromTarget('UTBlockee'); + $block = Block::newFromTarget('UTApiBlockee'); $this->assertTrue( !is_null( $block ), 'Block is valid' ); - $this->assertEquals( 'UTBlockee', (string)$block->getTarget() ); + $this->assertEquals( 'UTApiBlockee', (string)$block->getTarget() ); $this->assertEquals( 'Some reason', $block->mReason ); $this->assertEquals( 'infinity', $block->mExpiry ); diff --git a/tests/phpunit/includes/api/ApiPurgeTest.php b/tests/phpunit/includes/api/ApiPurgeTest.php index db1563e9..70c20746 100644 --- a/tests/phpunit/includes/api/ApiPurgeTest.php +++ b/tests/phpunit/includes/api/ApiPurgeTest.php @@ -9,33 +9,31 @@ class ApiPurgeTest extends ApiTestCase { parent::setUp(); $this->doLogin(); } - + + /** + * @group Broken + */ function testPurgeMainPage() { - if ( !Title::newFromText( 'UTPage' )->exists() ) { $this->markTestIncomplete( "The article [[UTPage]] does not exist" ); } - + $somePage = mt_rand(); $data = $this->doApiRequest( array( 'action' => 'purge', 'titles' => 'UTPage|' . $somePage . '|%5D' ) ); - - $this->assertArrayHasKey( 'purge', $data[0] ); - - $this->assertArrayHasKey( 0, $data[0]['purge'] ); - $this->assertArrayHasKey( 'purged', $data[0]['purge'][0] ); - $this->assertEquals( 'UTPage', $data[0]['purge'][0]['title'] ); - - $this->assertArrayHasKey( 1, $data[0]['purge'] ); - $this->assertArrayHasKey( 'missing', $data[0]['purge'][1] ); - $this->assertEquals( $somePage, $data[0]['purge'][1]['title'] ); - - $this->assertArrayHasKey( 2, $data[0]['purge'] ); - $this->assertArrayHasKey( 'invalid', $data[0]['purge'][2] ); - $this->assertEquals( '%5D', $data[0]['purge'][2]['title'] ); - + + $this->assertArrayHasKey( 'purge', $data[0], + "Must receive a 'purge' result from API" ); + + $this->assertEquals( 3, count( $data[0]['purge'] ), + "Purge request for three articles should give back three results received: " . var_export( $data[0]['purge'], true ) ); + + $pages = array( 'UTPage' => 'purged', $somePage => 'missing', '%5D' => 'invalid' ); + foreach( $data[0]['purge'] as $v ) { + $this->assertArrayHasKey( $pages[$v['title']], $v ); + } } } diff --git a/tests/phpunit/includes/api/ApiQueryTest.php b/tests/phpunit/includes/api/ApiQueryTest.php index 114eadf3..ae05a30a 100644 --- a/tests/phpunit/includes/api/ApiQueryTest.php +++ b/tests/phpunit/includes/api/ApiQueryTest.php @@ -22,10 +22,13 @@ class ApiQueryTest extends ApiTestCase { $this->assertArrayHasKey( 'query', $data[0] ); $this->assertArrayHasKey( 'normalized', $data[0]['query'] ); + // Forge a normalized title + $to = Title::newFromText( $wgMetaNamespace.':ArticleA' ); + $this->assertEquals( array( 'from' => 'Project:articleA', - 'to' => $wgMetaNamespace . ':ArticleA' + 'to' => $to->getPrefixedText(), ), $data[0]['query']['normalized'][0] ); @@ -50,7 +53,6 @@ class ApiQueryTest extends ApiTestCase { 'action' => 'query', 'titles' => $title . '|Talk:' ) ); - $this->assertArrayHasKey( 'query', $data[0] ); $this->assertArrayHasKey( 'pages', $data[0]['query'] ); $this->assertEquals( 2, count( $data[0]['query']['pages'] ) ); @@ -60,8 +62,6 @@ class ApiQueryTest extends ApiTestCase { $this->assertArrayHasKey( 'missing', $data[0]['query']['pages'][-2] ); $this->assertArrayHasKey( 'invalid', $data[0]['query']['pages'][-1] ); - - } } diff --git a/tests/phpunit/includes/api/ApiTest.php b/tests/phpunit/includes/api/ApiTest.php index a587e6b1..1d9c3238 100644 --- a/tests/phpunit/includes/api/ApiTest.php +++ b/tests/phpunit/includes/api/ApiTest.php @@ -96,7 +96,7 @@ class ApiTest extends ApiTestCase { "lgtoken" => $token, "lgname" => $user->username, "lgpassword" => "badnowayinhell", - ) + ), $ret[2] ); $result = $ret[0]; @@ -137,7 +137,7 @@ class ApiTest extends ApiTestCase { "lgtoken" => $token, "lgname" => $user->username, "lgpassword" => $user->password, - ) + ), $ret[2] ); $result = $ret[0]; @@ -148,6 +148,9 @@ class ApiTest extends ApiTestCase { $this->assertEquals( "Success", $a ); } + /** + * @group Broken + */ function testApiGotCookie() { $this->markTestIncomplete( "The server can't do external HTTP requests, and the internal one won't give cookies" ); @@ -192,24 +195,23 @@ class ApiTest extends ApiTestCase { } /** - * @depends testApiGotCookie + * @todo Finish filling me out...what are we trying to test here? */ - function testApiListPages( CookieJar $cj ) { - $this->markTestIncomplete( "Not done with this yet" ); + function testApiListPages() { global $wgServer; - - if ( $wgServer == "http://localhost" ) { + if ( !isset( $wgServer ) ) { $this->markTestIncomplete( 'This test needs $wgServer to be set in LocalSettings.php' ); } - $req = MWHttpRequest::factory( self::$apiUrl . "?action=query&format=xml&prop=revisions&" . - "titles=Main%20Page&rvprop=timestamp|user|comment|content" ); - $req->setCookieJar( $cj ); - $req->execute(); - libxml_use_internal_errors( true ); - $sxe = simplexml_load_string( $req->getContent() ); - $this->assertNotInternalType( "bool", $sxe ); - $this->assertThat( $sxe, $this->isInstanceOf( "SimpleXMLElement" ) ); - $a = $sxe->query[0]->pages[0]->page[0]->attributes(); + + $ret = $this->doApiRequest( array( + 'action' => 'query', + 'prop' => 'revisions', + 'titles' => 'Main Page', + 'rvprop' => 'timestamp|user|comment|content', + ) ); + + $result = $ret[0]['query']['pages']; + $this->markTestIncomplete( "Somebody needs to finish loving me" ); } function testRunLogin() { @@ -228,7 +230,7 @@ class ApiTest extends ApiTestCase { 'action' => 'login', "lgtoken" => $token, "lgname" => $sysopUser->username, - "lgpassword" => $sysopUser->password ), $data ); + "lgpassword" => $sysopUser->password ), $data[2] ); $this->assertArrayHasKey( "login", $data[0] ); $this->assertArrayHasKey( "result", $data[0]['login'] ); diff --git a/tests/phpunit/includes/api/ApiTestCase.php b/tests/phpunit/includes/api/ApiTestCase.php index 2917c880..8801391f 100644 --- a/tests/phpunit/includes/api/ApiTestCase.php +++ b/tests/phpunit/includes/api/ApiTestCase.php @@ -7,6 +7,11 @@ abstract class ApiTestCase extends MediaWikiLangTestCase { public static $users; protected static $apiUrl; + /** + * @var ApiTestContext + */ + protected $apiContext; + function setUp() { global $wgContLang, $wgAuth, $wgMemc, $wgRequest, $wgUser, $wgServer; @@ -21,31 +26,37 @@ abstract class ApiTestCase extends MediaWikiLangTestCase { 'sysop' => new ApiTestUser( 'Apitestsysop', 'Api Test Sysop', - 'api_test_sysop@sample.com', + 'api_test_sysop@example.com', array( 'sysop' ) ), 'uploader' => new ApiTestUser( 'Apitestuser', 'Api Test User', - 'api_test_user@sample.com', + 'api_test_user@example.com', array() ) ); $wgUser = self::$users['sysop']->user; + $this->apiContext = new ApiTestContext(); + } - protected function doApiRequest( $params, $session = null, $appendModule = false ) { + protected function doApiRequest( $params, $session = null, $appendModule = false, $user = null ) { if ( is_null( $session ) ) { $session = array(); } - $request = new FauxRequest( $params, true, $session ); - $module = new ApiMain( $request, true ); + $context = $this->apiContext->newTestContext( $params, $session, $user ); + $module = new ApiMain( $context, true ); $module->execute(); - $results = array( $module->getResultData(), $request, $request->getSessionArray() ); + $results = array( + $module->getResultData(), + $context->getRequest(), + $context->getRequest()->getSessionArray() + ); if( $appendModule ) { $results[] = $module; } @@ -59,14 +70,15 @@ abstract class ApiTestCase extends MediaWikiLangTestCase { * request, without actually requesting a "real" edit token * @param $params: key-value API params * @param $session: session array + * @param $user String|null A User object for the context */ - protected function doApiRequestWithToken( $params, $session ) { + protected function doApiRequestWithToken( $params, $session, $user = null ) { if ( $session['wsToken'] ) { // add edit token to fake session $session['wsEditToken'] = $session['wsToken']; // add token to request parameters $params['token'] = md5( $session['wsToken'] ) . User::EDIT_TOKEN_SUFFIX; - return $this->doApiRequest( $params, $session ); + return $this->doApiRequest( $params, $session, false, $user ); } else { throw new Exception( "request data not in right format" ); } @@ -91,12 +103,11 @@ abstract class ApiTestCase extends MediaWikiLangTestCase { } protected function getTokenList( $user ) { - $GLOBALS['wgUser'] = $user->user; $data = $this->doApiRequest( array( 'action' => 'query', 'titles' => 'Main Page', 'intoken' => 'edit|delete|protect|move|block|unblock', - 'prop' => 'info' ) ); + 'prop' => 'info' ), false, $user->user ); return $data; } } @@ -137,3 +148,23 @@ class MockApi extends ApiBase { ); } } + +class ApiTestContext extends RequestContext { + + /** + * Returns a DerivativeContext with the request variables in place + * + * @param $params Array key-value API params + * @param $session Array session data + * @param $user User or null + * @return DerivativeContext + */ + public function newTestContext( $params, $session, $user = null ) { + $context = new DerivativeContext( $this ); + $context->setRequest( new FauxRequest( $params, true, $session ) ); + if ( $user !== null ) { + $context->setUser( $user ); + } + return $context; + } +} diff --git a/tests/phpunit/includes/api/ApiTestCaseUpload.php b/tests/phpunit/includes/api/ApiTestCaseUpload.php index e51e7214..39c79547 100644 --- a/tests/phpunit/includes/api/ApiTestCaseUpload.php +++ b/tests/phpunit/includes/api/ApiTestCaseUpload.php @@ -19,6 +19,10 @@ abstract class ApiTestCaseUpload extends ApiTestCase { $this->clearFakeUploads(); } + public function tearDown() { + $this->clearTempUpload(); + } + /** * Helper function -- remove files and associated articles by Title * @param $title Title: title to be removed @@ -33,8 +37,8 @@ abstract class ApiTestCaseUpload extends ApiTestCase { if ( !$status->isGood() ) { return false; } - $article = new Article( $title ); - $article->doDeleteArticle( "removing for test" ); + $page = WikiPage::factory( $title ); + $page->doDeleteArticle( "removing for test" ); // see if it now doesn't exist; reload $title = Title::newFromText( $title->getText(), NS_FILE ); @@ -56,7 +60,7 @@ abstract class ApiTestCaseUpload extends ApiTestCase { * @param $filePath String: path to file on the filesystem */ public function deleteFileByContent( $filePath ) { - $hash = File::sha1Base36( $filePath ); + $hash = FSFile::getSha1Base36FromPath( $filePath ); $dupes = RepoGroup::singleton()->findBySha1( $hash ); $success = true; foreach ( $dupes as $dupe ) { @@ -100,6 +104,36 @@ abstract class ApiTestCaseUpload extends ApiTestCase { return true; } + function fakeUploadChunk( $fieldName, $fileName, $type, & $chunkData ){ + $tmpName = tempnam( wfTempDir(), "" ); + // copy the chunk data to temp location: + if ( !file_put_contents( $tmpName, $chunkData ) ) { + throw new Exception( "couldn't copy chunk data to $tmpName" ); + } + + clearstatcache(); + $size = filesize( $tmpName ); + if ( $size === false ) { + throw new Exception( "couldn't stat $tmpName" ); + } + + $_FILES[ $fieldName ] = array( + 'name' => $fileName, + 'type' => $type, + 'tmp_name' => $tmpName, + 'size' => $size, + 'error' => null + ); + } + + function clearTempUpload() { + if( isset( $_FILES['file']['tmp_name'] ) ) { + $tmp = $_FILES['file']['tmp_name']; + if( file_exists( $tmp ) ) { + unlink( $tmp ); + } + } + } /** * Remove traces of previous fake uploads diff --git a/tests/phpunit/includes/api/ApiTestUser.php b/tests/phpunit/includes/api/ApiTestUser.php index df60682f..8d5f61a7 100644 --- a/tests/phpunit/includes/api/ApiTestUser.php +++ b/tests/phpunit/includes/api/ApiTestUser.php @@ -8,7 +8,7 @@ class ApiTestUser { public $groups; public $user; - function __construct( $username, $realname = 'Real Name', $email = 'sample@sample.com', $groups = array() ) { + function __construct( $username, $realname = 'Real Name', $email = 'sample@example.com', $groups = array() ) { $this->username = $username; $this->realname = $realname; $this->email = $email; diff --git a/tests/phpunit/includes/api/ApiUploadTest.php b/tests/phpunit/includes/api/ApiUploadTest.php index 5c929784..7a700326 100644 --- a/tests/phpunit/includes/api/ApiUploadTest.php +++ b/tests/phpunit/includes/api/ApiUploadTest.php @@ -19,6 +19,9 @@ require_once( 'ApiTestCaseUpload.php' ); /** * @group Database + * @group Broken + * Broken test, reports false errors from time to time. + * See https://bugzilla.wikimedia.org/26169 * * This is pretty sucky... needs to be prettified. */ @@ -54,6 +57,7 @@ class ApiUploadTest extends ApiTestCaseUpload { $this->assertEquals( "Success", $result['login']['result'] ); $this->assertArrayHasKey( 'lgtoken', $result['login'] ); + $this->assertNotEmpty( $session, 'API Login must return a session' ); return $session; } @@ -78,14 +82,11 @@ class ApiUploadTest extends ApiTestCaseUpload { * @depends testLogin */ public function testUploadMissingParams( $session ) { - global $wgUser; - $wgUser = self::$users['uploader']->user; - $exception = false; try { $this->doApiRequestWithToken( array( 'action' => 'upload', - ), $session ); + ), $session, self::$users['uploader']->user ); } catch ( UsageException $e ) { $exception = true; $this->assertEquals( "One of the parameters filekey, file, url, statuskey is required", @@ -99,20 +100,17 @@ class ApiUploadTest extends ApiTestCaseUpload { * @depends testLogin */ public function testUpload( $session ) { - global $wgUser; - $wgUser = self::$users['uploader']->user; - $extension = 'png'; $mimeType = 'image/png'; try { $randomImageGenerator = new RandomImageGenerator(); + $filePaths = $randomImageGenerator->writeImages( 1, $extension, wfTempDir() ); } catch ( Exception $e ) { $this->markTestIncomplete( $e->getMessage() ); } - $filePaths = $randomImageGenerator->writeImages( 1, $extension, wfTempDir() ); $filePath = $filePaths[0]; $fileSize = filesize( $filePath ); $fileName = basename( $filePath ); @@ -135,7 +133,8 @@ class ApiUploadTest extends ApiTestCaseUpload { $exception = false; try { - list( $result, , ) = $this->doApiRequestWithToken( $params, $session ); + list( $result, , ) = $this->doApiRequestWithToken( $params, $session, + self::$users['uploader']->user ); } catch ( UsageException $e ) { $exception = true; } @@ -155,9 +154,6 @@ class ApiUploadTest extends ApiTestCaseUpload { * @depends testLogin */ public function testUploadZeroLength( $session ) { - global $wgUser; - $wgUser = self::$users['uploader']->user; - $mimeType = 'image/png'; $filePath = tempnam( wfTempDir(), "" ); @@ -179,7 +175,7 @@ class ApiUploadTest extends ApiTestCaseUpload { $exception = false; try { - $this->doApiRequestWithToken( $params, $session ); + $this->doApiRequestWithToken( $params, $session, self::$users['uploader']->user ); } catch ( UsageException $e ) { $this->assertContains( 'The file you submitted was empty', $e->getMessage() ); $exception = true; @@ -196,20 +192,17 @@ class ApiUploadTest extends ApiTestCaseUpload { * @depends testLogin */ public function testUploadSameFileName( $session ) { - global $wgUser; - $wgUser = self::$users['uploader']->user; - $extension = 'png'; $mimeType = 'image/png'; try { $randomImageGenerator = new RandomImageGenerator(); + $filePaths = $randomImageGenerator->writeImages( 2, $extension, wfTempDir() ); } catch ( Exception $e ) { $this->markTestIncomplete( $e->getMessage() ); } - $filePaths = $randomImageGenerator->writeImages( 2, $extension, wfTempDir() ); // we'll reuse this filename $fileName = basename( $filePaths[0] ); @@ -233,7 +226,8 @@ class ApiUploadTest extends ApiTestCaseUpload { $exception = false; try { - list( $result, , $session ) = $this->doApiRequestWithToken( $params, $session ); + list( $result, , $session ) = $this->doApiRequestWithToken( $params, $session, + self::$users['uploader']->user ); } catch ( UsageException $e ) { $exception = true; } @@ -249,7 +243,8 @@ class ApiUploadTest extends ApiTestCaseUpload { $exception = false; try { - list( $result, , ) = $this->doApiRequestWithToken( $params, $session ); + list( $result, , ) = $this->doApiRequestWithToken( $params, $session, + self::$users['uploader']->user ); // FIXME: leaks a temporary file } catch ( UsageException $e ) { $exception = true; } @@ -270,19 +265,17 @@ class ApiUploadTest extends ApiTestCaseUpload { * @depends testLogin */ public function testUploadSameContent( $session ) { - global $wgUser; - $wgUser = self::$users['uploader']->user; - $extension = 'png'; $mimeType = 'image/png'; try { $randomImageGenerator = new RandomImageGenerator(); + $filePaths = $randomImageGenerator->writeImages( 1, $extension, wfTempDir() ); } catch ( Exception $e ) { $this->markTestIncomplete( $e->getMessage() ); } - $filePaths = $randomImageGenerator->writeImages( 1, $extension, wfTempDir() ); + $fileNames[0] = basename( $filePaths[0] ); $fileNames[1] = "SameContentAs" . $fileNames[0]; @@ -307,7 +300,8 @@ class ApiUploadTest extends ApiTestCaseUpload { $exception = false; try { - list( $result, $request, $session ) = $this->doApiRequestWithToken( $params, $session ); + list( $result, $request, $session ) = $this->doApiRequestWithToken( $params, $session, + self::$users['uploader']->user ); } catch ( UsageException $e ) { $exception = true; } @@ -332,7 +326,8 @@ class ApiUploadTest extends ApiTestCaseUpload { $exception = false; try { - list( $result, $request, $session ) = $this->doApiRequestWithToken( $params, $session ); + list( $result, $request, $session ) = $this->doApiRequestWithToken( $params, $session, + self::$users['uploader']->user ); // FIXME: leaks a temporary file } catch ( UsageException $e ) { $exception = true; } @@ -354,19 +349,19 @@ class ApiUploadTest extends ApiTestCaseUpload { */ public function testUploadStash( $session ) { global $wgUser; - $wgUser = self::$users['uploader']->user; + $wgUser = self::$users['uploader']->user; // @todo FIXME: still used somewhere $extension = 'png'; $mimeType = 'image/png'; try { $randomImageGenerator = new RandomImageGenerator(); + $filePaths = $randomImageGenerator->writeImages( 1, $extension, wfTempDir() ); } catch ( Exception $e ) { $this->markTestIncomplete( $e->getMessage() ); } - $filePaths = $randomImageGenerator->writeImages( 1, $extension, wfTempDir() ); $filePath = $filePaths[0]; $fileSize = filesize( $filePath ); $fileName = basename( $filePath ); @@ -389,7 +384,8 @@ class ApiUploadTest extends ApiTestCaseUpload { $exception = false; try { - list( $result, $request, $session ) = $this->doApiRequestWithToken( $params, $session ); + list( $result, $request, $session ) = $this->doApiRequestWithToken( $params, $session, + self::$users['uploader']->user ); // FIXME: leaks a temporary file } catch ( UsageException $e ) { $exception = true; } @@ -417,17 +413,156 @@ class ApiUploadTest extends ApiTestCaseUpload { $this->clearFakeUploads(); $exception = false; try { - list( $result, $request, $session ) = $this->doApiRequestWithToken( $params, $session ); + list( $result, $request, $session ) = $this->doApiRequestWithToken( $params, $session, + self::$users['uploader']->user ); } catch ( UsageException $e ) { $exception = true; } $this->assertTrue( isset( $result['upload'] ) ); $this->assertEquals( 'Success', $result['upload']['result'] ); - $this->assertFalse( $exception ); + $this->assertFalse( $exception, "No UsageException exception." ); // clean up $this->deleteFileByFilename( $fileName ); unlink( $filePath ); } -} + + + /** + * @depends testLogin + */ + public function testUploadChunks( $session ) { + global $wgUser; + $wgUser = self::$users['uploader']->user; // @todo FIXME: still used somewhere + + $chunkSize = 1048576; + // Download a large image file + // ( using RandomImageGenerator for large files is not stable ) + $mimeType = 'image/jpeg'; + $url = 'http://upload.wikimedia.org/wikipedia/commons/e/ed/Oberaargletscher_from_Oberaar%2C_2010_07.JPG'; + $filePath = wfTempDir() . '/Oberaargletscher_from_Oberaar.jpg'; + try { + // Only download if the file is not avaliable in the temp location: + if( !is_file( $filePath ) ){ + copy($url, $filePath); + } + } + catch ( Exception $e ) { + $this->markTestIncomplete( $e->getMessage() ); + } + $fileSize = filesize( $filePath ); + $fileName = basename( $filePath ); + + $this->deleteFileByFileName( $fileName ); + $this->deleteFileByContent( $filePath ); + + // Base upload params: + $params = array( + 'action' => 'upload', + 'stash' => 1, + 'filename' => $fileName, + 'filesize' => $fileSize, + 'offset' => 0, + ); + + // Upload chunks + $chunkSessionKey = false; + $resultOffset = 0; + // Open the file: + $handle = @fopen ($filePath, "r"); + if( $handle === false ){ + $this->markTestIncomplete( "could not open file: $filePath" ); + } + while (!feof ($handle)) { + // Get the current chunk + $chunkData = @fread( $handle, $chunkSize ); + + // Upload the current chunk into the $_FILE object: + $this->fakeUploadChunk( 'chunk', 'blob', $mimeType, $chunkData ); + + // Check for chunkSessionKey + if( !$chunkSessionKey ){ + // Upload fist chunk ( and get the session key ) + try { + list( $result, $request, $session ) = $this->doApiRequestWithToken( $params, $session, + self::$users['uploader']->user ); + } catch ( UsageException $e ) { + $this->markTestIncomplete( $e->getMessage() ); + } + // Make sure we got a valid chunk continue: + $this->assertTrue( isset( $result['upload'] ) ); + $this->assertTrue( isset( $result['upload']['filekey'] ) ); + // If we don't get a session key mark test incomplete. + if( ! isset( $result['upload']['filekey'] ) ){ + $this->markTestIncomplete( "no filekey provided" ); + } + $chunkSessionKey = $result['upload']['filekey']; + $this->assertEquals( 'Continue', $result['upload']['result'] ); + // First chunk should have chunkSize == offset + $this->assertEquals( $chunkSize, $result['upload']['offset'] ); + $resultOffset = $result['upload']['offset']; + continue; + } + // Filekey set to chunk session + $params['filekey'] = $chunkSessionKey; + // Update the offset ( always add chunkSize for subquent chunks should be in-sync with $result['upload']['offset'] ) + $params['offset'] += $chunkSize; + // Make sure param offset is insync with resultOffset: + $this->assertEquals( $resultOffset, $params['offset'] ); + // Upload current chunk + try { + list( $result, $request, $session ) = $this->doApiRequestWithToken( $params, $session, + self::$users['uploader']->user ); + } catch ( UsageException $e ) { + $this->markTestIncomplete( $e->getMessage() ); + } + // Make sure we got a valid chunk continue: + $this->assertTrue( isset( $result['upload'] ) ); + $this->assertTrue( isset( $result['upload']['filekey'] ) ); + + // Check if we were on the last chunk: + if( $params['offset'] + $chunkSize >= $fileSize ){ + $this->assertEquals( 'Success', $result['upload']['result'] ); + break; + } else { + $this->assertEquals( 'Continue', $result['upload']['result'] ); + // update $resultOffset + $resultOffset = $result['upload']['offset']; + } + } + fclose ($handle); + + // Check that we got a valid file result: + wfDebug( __METHOD__ . " hohoh filesize {$fileSize} info {$result['upload']['imageinfo']['size']}\n\n"); + $this->assertEquals( $fileSize, $result['upload']['imageinfo']['size'] ); + $this->assertEquals( $mimeType, $result['upload']['imageinfo']['mime'] ); + $this->assertTrue( isset( $result['upload']['filekey'] ) ); + $filekey = $result['upload']['filekey']; + + // Now we should try to release the file from stash + $params = array( + 'action' => 'upload', + 'filekey' => $filekey, + 'filename' => $fileName, + 'comment' => 'dummy comment', + 'text' => "This is the page text for $fileName, altered", + ); + $this->clearFakeUploads(); + $exception = false; + try { + list( $result, $request, $session ) = $this->doApiRequestWithToken( $params, $session, + self::$users['uploader']->user ); + } catch ( UsageException $e ) { + $exception = true; + } + $this->assertTrue( isset( $result['upload'] ) ); + $this->assertEquals( 'Success', $result['upload']['result'] ); + $this->assertFalse( $exception ); + + // clean up + $this->deleteFileByFilename( $fileName ); + // don't remove downloaded temporary file for fast subquent tests. + //unlink( $filePath ); + } +} diff --git a/tests/phpunit/includes/api/ApiWatchTest.php b/tests/phpunit/includes/api/ApiWatchTest.php index 3c7ff304..b7803746 100644 --- a/tests/phpunit/includes/api/ApiWatchTest.php +++ b/tests/phpunit/includes/api/ApiWatchTest.php @@ -41,6 +41,7 @@ class ApiWatchTest extends ApiTestCase { /** * @depends testWatchEdit + * @group Broken */ function testWatchClear() { @@ -92,7 +93,9 @@ class ApiWatchTest extends ApiTestCase { $this->assertArrayHasKey( 'edit', $data[0]['protect']['protections'][0] ); } - + /** + * @group Broken + */ function testGetRollbackToken() { $data = $this->getTokens(); diff --git a/tests/phpunit/includes/api/RandomImageGenerator.php b/tests/phpunit/includes/api/RandomImageGenerator.php index ae349978..86c0a828 100644 --- a/tests/phpunit/includes/api/RandomImageGenerator.php +++ b/tests/phpunit/includes/api/RandomImageGenerator.php @@ -1,6 +1,6 @@ 'top', - '0thCol' => 'left', - 'exifCode' => 1, - 'counterRotation' => array( array( 1, 0 ), array( 0, 1 ) ) + array( + '0thRow' => 'top', + '0thCol' => 'left', + 'exifCode' => 1, + 'counterRotation' => array( array( 1, 0 ), array( 0, 1 ) ) ), - array( + array( '0thRow' => 'bottom', - '0thCol' => 'right', - 'exifCode' => 3, - 'counterRotation' => array( array( -1, 0 ), array( 0, -1 ) ) + '0thCol' => 'right', + 'exifCode' => 3, + 'counterRotation' => array( array( -1, 0 ), array( 0, -1 ) ) ), - array( - '0thRow' => 'right', - '0thCol' => 'top', - 'exifCode' => 6, - 'counterRotation' => array( array( 0, 1 ), array( 1, 0 ) ) + array( + '0thRow' => 'right', + '0thCol' => 'top', + 'exifCode' => 6, + 'counterRotation' => array( array( 0, 1 ), array( 1, 0 ) ) ), - array( - '0thRow' => 'left', - '0thCol' => 'bottom', - 'exifCode' => 8, - 'counterRotation' => array( array( 0, -1 ), array( -1, 0 ) ) + array( + '0thRow' => 'left', + '0thCol' => 'bottom', + 'exifCode' => 8, + 'counterRotation' => array( array( 0, -1 ), array( -1, 0 ) ) ) ); public function __construct( $options = array() ) { - foreach ( array( 'dictionaryFile', 'minWidth', 'minHeight', 'maxHeight', 'shapesToDraw' ) as $property ) { + foreach ( array( 'dictionaryFile', 'minWidth', 'minHeight', 'maxWidth', 'maxHeight', 'shapesToDraw' ) as $property ) { if ( isset( $options[$property] ) ) { $this->$property = $options[$property]; } @@ -77,10 +76,10 @@ class RandomImageGenerator { // find the dictionary file, to generate random names if ( !isset( $this->dictionaryFile ) ) { - foreach ( array( - '/usr/share/dict/words', - '/usr/dict/words', - dirname( __FILE__ ) . '/words.txt' ) + foreach ( array( + '/usr/share/dict/words', + '/usr/dict/words', + dirname( __FILE__ ) . '/words.txt' ) as $dictionaryFile ) { if ( is_file( $dictionaryFile ) and is_readable( $dictionaryFile ) ) { $this->dictionaryFile = $dictionaryFile; @@ -91,14 +90,6 @@ class RandomImageGenerator { if ( !isset( $this->dictionaryFile ) ) { throw new Exception( "RandomImageGenerator: dictionary file not found or not specified properly" ); } - - if ( !class_exists( 'Imagick' ) ) { - throw new Exception( 'No Imagick extension' ); - } - global $wgExiv2Command; - if ( !$wgExiv2Command || !is_executable( $wgExiv2Command ) ) { - throw new Exception( 'exiv2 not executable or $wgExiv2Command not set' ); - } } /** @@ -125,15 +116,16 @@ class RandomImageGenerator { */ function getImageWriteMethod( $format ) { global $wgUseImageMagick, $wgImageMagickConvertCommand; - if ( $format === 'svg' ) { + if ( $format === 'svg' ) { return 'writeSvg'; } else { // figure out how to write images - if ( class_exists( 'Imagick' ) ) { + global $wgExiv2Command; + if ( class_exists( 'Imagick' ) && $wgExiv2Command && is_executable( $wgExiv2Command ) ) { return 'writeImageWithApi'; } elseif ( $wgUseImageMagick && $wgImageMagickConvertCommand && is_executable( $wgImageMagickConvertCommand ) ) { return 'writeImageWithCommandLine'; - } + } } throw new Exception( "RandomImageGenerator: could not find a suitable method to write images in '$format' format" ); } @@ -219,7 +211,7 @@ class RandomImageGenerator { */ static function shapePointsToString( $shape ) { $points = array(); - foreach ( $shape as $point ) { + foreach ( $shape as $point ) { $points[] = $point['x'] . ',' . $point['y']; } return join( " ", $points ); @@ -232,16 +224,16 @@ class RandomImageGenerator { * @param $format: file format to write (which is obviously always svg here) * @param $filename: filename to write to */ - public function writeSvg( $spec, $format, $filename ) { + public function writeSvg( $spec, $format, $filename ) { $svg = new SimpleXmlElement( '' ); $svg->addAttribute( 'xmlns', 'http://www.w3.org/2000/svg' ); - $svg->addAttribute( 'version', '1.1' ); - $svg->addAttribute( 'width', $spec['width'] ); - $svg->addAttribute( 'height', $spec['height'] ); + $svg->addAttribute( 'version', '1.1' ); + $svg->addAttribute( 'width', $spec['width'] ); + $svg->addAttribute( 'height', $spec['height'] ); $g = $svg->addChild( 'g' ); foreach ( $spec['draws'] as $drawSpec ) { $shape = $g->addChild( 'polygon' ); - $shape->addAttribute( 'fill', $drawSpec['fill'] ); + $shape->addAttribute( 'fill', $drawSpec['fill'] ); $shape->addAttribute( 'points', self::shapePointsToString( $drawSpec['shape'] ) ); }; if ( ! $fh = fopen( $filename, 'w' ) ) { @@ -260,20 +252,20 @@ class RandomImageGenerator { * @param $filename: filename to write to */ public function writeImageWithApi( $spec, $format, $filename ) { - // this is a hack because I can't get setImageOrientation() to work. See below. + // this is a hack because I can't get setImageOrientation() to work. See below. global $wgExiv2Command; $image = new Imagick(); /** - * If the format is 'jpg', will also add a random orientation -- the image will be drawn rotated with triangle points + * If the format is 'jpg', will also add a random orientation -- the image will be drawn rotated with triangle points * facing in some direction (0, 90, 180 or 270 degrees) and a countering rotation should turn the triangle points upward again */ $orientation = self::$orientations[0]; // default is normal orientation if ( $format == 'jpg' ) { $orientation = self::$orientations[ array_rand( self::$orientations ) ]; - $spec = self::rotateImageSpec( $spec, $orientation['counterRotation'] ); + $spec = self::rotateImageSpec( $spec, $orientation['counterRotation'] ); } - + $image->newImage( $spec['width'], $spec['height'], new ImagickPixel( $spec['fill'] ) ); foreach ( $spec['draws'] as $drawSpec ) { @@ -296,7 +288,7 @@ class RandomImageGenerator { $cmd = wfEscapeShellArg( $wgExiv2Command ) . " -M " . wfEscapeShellArg( "set Exif.Image.Orientation " . $orientation['exifCode'] ) - . " " + . " " . wfEscapeShellArg( $filename ); $retval = 0; @@ -304,15 +296,13 @@ class RandomImageGenerator { if ( $retval !== 0 ) { print "Error with $cmd: $retval, $err\n"; } - } - - + } } /** * Given an image specification, produce rotated version * This is used when simulating a rotated image capture with EXIF orientation - * @param $spec Object returned by getImageSpec + * @param $spec Object returned by getImageSpec * @param $matrix 2x2 transformation matrix * @return transformed Spec */ @@ -323,8 +313,8 @@ class RandomImageGenerator { $correctionY = 0; if ( $dims['x'] < 0 ) { $correctionX = abs( $dims['x'] ); - } - if ( $dims['y'] < 0 ) { + } + if ( $dims['y'] < 0 ) { $correctionY = abs( $dims['y'] ); } $tSpec['width'] = abs( $dims['x'] ); @@ -332,7 +322,7 @@ class RandomImageGenerator { $tSpec['fill'] = $spec['fill']; $tSpec['draws'] = array(); foreach( $spec['draws'] as $draw ) { - $tDraw = array( + $tDraw = array( 'fill' => $draw['fill'], 'shape' => array() ); @@ -349,13 +339,13 @@ class RandomImageGenerator { /** * Given a matrix and a pair of images, return new position - * @param $matrix: 2x2 rotation matrix + * @param $matrix: 2x2 rotation matrix * @param $x: x-coordinate number * @param $y: y-coordinate number - * @return Array transformed with properties x, y + * @return Array transformed with properties x, y */ private static function matrixMultiply2x2( $matrix, $x, $y ) { - return array( + return array( 'x' => $x * $matrix[0][0] + $y * $matrix[0][1], 'y' => $x * $matrix[1][0] + $y * $matrix[1][1] ); @@ -366,10 +356,10 @@ class RandomImageGenerator { * Based on an image specification, write such an image to disk, using the command line ImageMagick program ('convert'). * * Sample command line: - * $ convert -size 100x60 xc:rgb(90,87,45) \ - * -draw 'fill rgb(12,34,56) polygon 41,39 44,57 50,57 41,39' \ - * -draw 'fill rgb(99,123,231) circle 59,39 56,57' \ - * -draw 'fill rgb(240,12,32) circle 50,21 50,3' filename.png + * $ convert -size 100x60 xc:rgb(90,87,45) \ + * -draw 'fill rgb(12,34,56) polygon 41,39 44,57 50,57 41,39' \ + * -draw 'fill rgb(99,123,231) circle 59,39 56,57' \ + * -draw 'fill rgb(240,12,32) circle 50,21 50,3' filename.png * * @param $spec: spec describing background and shapes to draw * @param $format: file format to write (unused by this method but kept so it has the same signature as writeImageWithApi) -- cgit v1.2.2