summaryrefslogtreecommitdiff
path: root/tests/phpunit/includes/api
diff options
context:
space:
mode:
authorPierre Schmitz <pierre@archlinux.de>2012-05-03 13:01:35 +0200
committerPierre Schmitz <pierre@archlinux.de>2012-05-03 13:01:35 +0200
commitd9022f63880ce039446fba8364f68e656b7bf4cb (patch)
tree16b40fbf17bf7c9ee6f4ead25b16dd192378050a /tests/phpunit/includes/api
parent27cf83d177256813e2e802241085fce5dd0f3fb9 (diff)
Update to MediaWiki 1.19.0
Diffstat (limited to 'tests/phpunit/includes/api')
-rw-r--r--tests/phpunit/includes/api/ApiBlockTest.php28
-rw-r--r--tests/phpunit/includes/api/ApiPurgeTest.php34
-rw-r--r--tests/phpunit/includes/api/ApiQueryTest.php8
-rw-r--r--tests/phpunit/includes/api/ApiTest.php36
-rw-r--r--tests/phpunit/includes/api/ApiTestCase.php51
-rw-r--r--tests/phpunit/includes/api/ApiTestCaseUpload.php40
-rw-r--r--tests/phpunit/includes/api/ApiTestUser.php2
-rw-r--r--tests/phpunit/includes/api/ApiUploadTest.php197
-rw-r--r--tests/phpunit/includes/api/ApiWatchTest.php5
-rw-r--r--tests/phpunit/includes/api/RandomImageGenerator.php124
10 files changed, 364 insertions, 161 deletions
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 @@
<?php
-/*
+/**
* RandomImageGenerator -- does what it says on the tin.
* Requires Imagick, the ImageMagick library for PHP, or the command line equivalent (usually 'convert').
*
@@ -27,12 +27,11 @@
class RandomImageGenerator {
private $dictionaryFile;
- private $minWidth = 400;
- private $maxWidth = 800;
- private $minHeight = 400;
- private $maxHeight = 800;
- private $shapesToDraw = 5;
- private $imageWriteMethod;
+ private $minWidth = 400 ;
+ private $maxWidth = 800 ;
+ private $minHeight = 400 ;
+ private $maxHeight = 800 ;
+ private $shapesToDraw = 5 ;
/**
* Orientations: 0th row, 0th column, EXIF orientation code, rotation 2x2 matrix that is opposite of orientation
@@ -41,35 +40,35 @@ class RandomImageGenerator {
* (we also would need a non-symmetric shape for the images to test those, like a letter F)
*/
private static $orientations = array(
- array(
- '0thRow' => '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/>' );
$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)