Apply modification of mdale's patch from Bug #28420: “Re-factor upload tests to support extensions extending upload test case”
This commit is contained in:
parent
107314d651
commit
4e9b2c5c53
4 changed files with 253 additions and 240 deletions
64
tests/phpunit/includes/api/ApiTestCase.php
Normal file
64
tests/phpunit/includes/api/ApiTestCase.php
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
<?php
|
||||
|
||||
abstract class ApiTestCase extends MediaWikiTestCase {
|
||||
public static $users;
|
||||
|
||||
function setUp() {
|
||||
global $wgContLang, $wgAuth, $wgMemc, $wgRequest, $wgUser;
|
||||
|
||||
$wgMemc = new EmptyBagOStuff();
|
||||
$wgContLang = Language::factory( 'en' );
|
||||
$wgAuth = new StubObject( 'wgAuth', 'AuthPlugin' );
|
||||
$wgRequest = new FauxRequest( array() );
|
||||
|
||||
self::$users = array(
|
||||
'sysop' => new ApiTestUser(
|
||||
'Apitestsysop',
|
||||
'Api Test Sysop',
|
||||
'api_test_sysop@sample.com',
|
||||
array( 'sysop' )
|
||||
),
|
||||
'uploader' => new ApiTestUser(
|
||||
'Apitestuser',
|
||||
'Api Test User',
|
||||
'api_test_user@sample.com',
|
||||
array()
|
||||
)
|
||||
);
|
||||
|
||||
$wgUser = self::$users['sysop']->user;
|
||||
|
||||
}
|
||||
|
||||
protected function doApiRequest( $params, $session = null, $appendModule = false ) {
|
||||
if ( is_null( $session ) ) {
|
||||
$session = array();
|
||||
}
|
||||
|
||||
$request = new FauxRequest( $params, true, $session );
|
||||
$module = new ApiMain( $request, true );
|
||||
$module->execute();
|
||||
|
||||
return array( $module->getResultData(), $request, $request->getSessionArray() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an edit token to the API request
|
||||
* This is cheating a bit -- we grab a token in the correct format and then add it to the pseudo-session and to the
|
||||
* request, without actually requesting a "real" edit token
|
||||
* @param $params: key-value API params
|
||||
* @param $session: session array
|
||||
*/
|
||||
protected function doApiRequestWithToken( $params, $session ) {
|
||||
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 );
|
||||
} else {
|
||||
throw new Exception( "request data not in right format" );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
128
tests/phpunit/includes/api/ApiTestCaseUpload.php
Normal file
128
tests/phpunit/includes/api/ApiTestCaseUpload.php
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* * Abstract class to support upload tests
|
||||
*/
|
||||
require_once( 'ApiTestUser.php' );
|
||||
require_once( 'ApiTestCase.php' );
|
||||
|
||||
abstract class ApiTestCaseUpload extends ApiTestCase {
|
||||
/**
|
||||
* Fixture -- run before every test
|
||||
*/
|
||||
public function setUp() {
|
||||
global $wgEnableUploads, $wgEnableAPI;
|
||||
parent::setUp();
|
||||
|
||||
$wgEnableUploads = true;
|
||||
$wgEnableAPI = true;
|
||||
wfSetupSession();
|
||||
|
||||
ini_set( 'log_errors', 1 );
|
||||
ini_set( 'error_reporting', 1 );
|
||||
ini_set( 'display_errors', 1 );
|
||||
|
||||
$this->clearFakeUploads();
|
||||
}
|
||||
|
||||
/**
|
||||
* Fixture -- run after every test
|
||||
* Clean up temporary files etc.
|
||||
*/
|
||||
function tearDown() {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Helper function -- remove files and associated articles by Title
|
||||
* @param $title Title: title to be removed
|
||||
*/
|
||||
public function deleteFileByTitle( $title ) {
|
||||
if ( $title->exists() ) {
|
||||
$file = wfFindFile( $title, array( 'ignoreRedirect' => true ) );
|
||||
$noOldArchive = ""; // yes this really needs to be set this way
|
||||
$comment = "removing for test";
|
||||
$restrictDeletedVersions = false;
|
||||
$status = FileDeleteForm::doDelete( $title, $file, $noOldArchive, $comment, $restrictDeletedVersions );
|
||||
if ( !$status->isGood() ) {
|
||||
return false;
|
||||
}
|
||||
$article = new Article( $title );
|
||||
$article->doDeleteArticle( "removing for test" );
|
||||
|
||||
// see if it now doesn't exist; reload
|
||||
$title = Title::newFromText( $fileName, NS_FILE );
|
||||
}
|
||||
return ! ( $title && $title instanceof Title && $title->exists() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function -- remove files and associated articles with a particular filename
|
||||
* @param $fileName String: filename to be removed
|
||||
*/
|
||||
public function deleteFileByFileName( $fileName ) {
|
||||
return $this->deleteFileByTitle( Title::newFromText( $fileName, NS_FILE ) );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Helper function -- given a file on the filesystem, find matching content in the db (and associated articles) and remove them.
|
||||
* @param $filePath String: path to file on the filesystem
|
||||
*/
|
||||
public function deleteFileByContent( $filePath ) {
|
||||
$hash = File::sha1Base36( $filePath );
|
||||
$dupes = RepoGroup::singleton()->findBySha1( $hash );
|
||||
$success = true;
|
||||
foreach ( $dupes as $dupe ) {
|
||||
$success &= $this->deleteFileByTitle( $dupe->getTitle() );
|
||||
}
|
||||
return $success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fake an upload by dumping the file into temp space, and adding info to $_FILES.
|
||||
* (This is what PHP would normally do).
|
||||
* @param $fieldName String: name this would have in the upload form
|
||||
* @param $fileName String: name to title this
|
||||
* @param $type String: mime type
|
||||
* @param $filePath String: path where to find file contents
|
||||
*/
|
||||
function fakeUploadFile( $fieldName, $fileName, $type, $filePath ) {
|
||||
$tmpName = tempnam( wfTempDir(), "" );
|
||||
if ( !file_exists( $filePath ) ) {
|
||||
throw new Exception( "$filePath doesn't exist!" );
|
||||
};
|
||||
|
||||
if ( !copy( $filePath, $tmpName ) ) {
|
||||
throw new Exception( "couldn't copy $filePath 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
|
||||
);
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove traces of previous fake uploads
|
||||
*/
|
||||
function clearFakeUploads() {
|
||||
$_FILES = array();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
59
tests/phpunit/includes/api/ApiTestUser.php
Normal file
59
tests/phpunit/includes/api/ApiTestUser.php
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
<?php
|
||||
|
||||
/* Wraps the user object, so we can also retain full access to properties like password if we log in via the API */
|
||||
class ApiTestUser {
|
||||
public $username;
|
||||
public $password;
|
||||
public $email;
|
||||
public $groups;
|
||||
public $user;
|
||||
|
||||
function __construct( $username, $realname = 'Real Name', $email = 'sample@sample.com', $groups = array() ) {
|
||||
$this->username = $username;
|
||||
$this->realname = $realname;
|
||||
$this->email = $email;
|
||||
$this->groups = $groups;
|
||||
|
||||
// don't allow user to hardcode or select passwords -- people sometimes run tests
|
||||
// on live wikis. Sometimes we create sysop users in these tests. A sysop user with
|
||||
// a known password would be a Bad Thing.
|
||||
$this->password = User::randomPassword();
|
||||
|
||||
$this->user = User::newFromName( $this->username );
|
||||
$this->user->load();
|
||||
|
||||
// In an ideal world we'd have a new wiki (or mock data store) for every single test.
|
||||
// But for now, we just need to create or update the user with the desired properties.
|
||||
// we particularly need the new password, since we just generated it randomly.
|
||||
// In core MediaWiki, there is no functionality to delete users, so this is the best we can do.
|
||||
if ( !$this->user->getID() ) {
|
||||
// create the user
|
||||
$this->user = User::createNew(
|
||||
$this->username, array(
|
||||
"email" => $this->email,
|
||||
"real_name" => $this->realname
|
||||
)
|
||||
);
|
||||
if ( !$this->user ) {
|
||||
throw new Exception( "error creating user" );
|
||||
}
|
||||
}
|
||||
|
||||
// update the user to use the new random password and other details
|
||||
$this->user->setPassword( $this->password );
|
||||
$this->user->setEmail( $this->email );
|
||||
$this->user->setRealName( $this->realname );
|
||||
// remove all groups, replace with any groups specified
|
||||
foreach ( $this->user->getGroups() as $group ) {
|
||||
$this->user->removeGroup( $group );
|
||||
}
|
||||
if ( count( $this->groups ) ) {
|
||||
foreach ( $this->groups as $group ) {
|
||||
$this->user->addGroup( $group );
|
||||
}
|
||||
}
|
||||
$this->user->saveSettings();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -14,129 +14,9 @@
|
|||
// This framework works better IMO and has less strangeness (such as test cases inheriting from "ApiSetup"...)
|
||||
// (and in the case of the other Upload tests, this flat out just actually works... )
|
||||
|
||||
// TODO: refactor into several files
|
||||
// TODO: port the other Upload tests, and other API tests to this framework
|
||||
|
||||
/* Wraps the user object, so we can also retain full access to properties like password if we log in via the API */
|
||||
class ApiTestUser {
|
||||
public $username;
|
||||
public $password;
|
||||
public $email;
|
||||
public $groups;
|
||||
public $user;
|
||||
|
||||
function __construct( $username, $realname = 'Real Name', $email = 'sample@sample.com', $groups = array() ) {
|
||||
$this->username = $username;
|
||||
$this->realname = $realname;
|
||||
$this->email = $email;
|
||||
$this->groups = $groups;
|
||||
|
||||
// don't allow user to hardcode or select passwords -- people sometimes run tests
|
||||
// on live wikis. Sometimes we create sysop users in these tests. A sysop user with
|
||||
// a known password would be a Bad Thing.
|
||||
$this->password = User::randomPassword();
|
||||
|
||||
$this->user = User::newFromName( $this->username );
|
||||
$this->user->load();
|
||||
|
||||
// In an ideal world we'd have a new wiki (or mock data store) for every single test.
|
||||
// But for now, we just need to create or update the user with the desired properties.
|
||||
// we particularly need the new password, since we just generated it randomly.
|
||||
// In core MediaWiki, there is no functionality to delete users, so this is the best we can do.
|
||||
if ( !$this->user->getID() ) {
|
||||
// create the user
|
||||
$this->user = User::createNew(
|
||||
$this->username, array(
|
||||
"email" => $this->email,
|
||||
"real_name" => $this->realname
|
||||
)
|
||||
);
|
||||
if ( !$this->user ) {
|
||||
throw new Exception( "error creating user" );
|
||||
}
|
||||
}
|
||||
|
||||
// update the user to use the new random password and other details
|
||||
$this->user->setPassword( $this->password );
|
||||
$this->user->setEmail( $this->email );
|
||||
$this->user->setRealName( $this->realname );
|
||||
// remove all groups, replace with any groups specified
|
||||
foreach ( $this->user->getGroups() as $group ) {
|
||||
$this->user->removeGroup( $group );
|
||||
}
|
||||
if ( count( $this->groups ) ) {
|
||||
foreach ( $this->groups as $group ) {
|
||||
$this->user->addGroup( $group );
|
||||
}
|
||||
}
|
||||
$this->user->saveSettings();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
abstract class ApiTestCase extends MediaWikiTestCase {
|
||||
public static $users;
|
||||
|
||||
function setUp() {
|
||||
global $wgContLang, $wgAuth, $wgMemc, $wgRequest, $wgUser;
|
||||
|
||||
$wgMemc = new EmptyBagOStuff();
|
||||
$wgContLang = Language::factory( 'en' );
|
||||
$wgAuth = new StubObject( 'wgAuth', 'AuthPlugin' );
|
||||
$wgRequest = new FauxRequest( array() );
|
||||
|
||||
self::$users = array(
|
||||
'sysop' => new ApiTestUser(
|
||||
'Apitestsysop',
|
||||
'Api Test Sysop',
|
||||
'api_test_sysop@sample.com',
|
||||
array( 'sysop' )
|
||||
),
|
||||
'uploader' => new ApiTestUser(
|
||||
'Apitestuser',
|
||||
'Api Test User',
|
||||
'api_test_user@sample.com',
|
||||
array()
|
||||
)
|
||||
);
|
||||
|
||||
$wgUser = self::$users['sysop']->user;
|
||||
|
||||
}
|
||||
|
||||
protected function doApiRequest( $params, $session = null, $appendModule = false ) {
|
||||
if ( is_null( $session ) ) {
|
||||
$session = array();
|
||||
}
|
||||
|
||||
$request = new FauxRequest( $params, true, $session );
|
||||
$module = new ApiMain( $request, true );
|
||||
$module->execute();
|
||||
|
||||
return array( $module->getResultData(), $request, $request->getSessionArray() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an edit token to the API request
|
||||
* This is cheating a bit -- we grab a token in the correct format and then add it to the pseudo-session and to the
|
||||
* request, without actually requesting a "real" edit token
|
||||
* @param $params: key-value API params
|
||||
* @param $session: session array
|
||||
*/
|
||||
protected function doApiRequestWithToken( $params, $session ) {
|
||||
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 );
|
||||
} else {
|
||||
throw new Exception( "request data not in right format" );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
require_once( 'ApiTestCaseUpload.php' );
|
||||
|
||||
/**
|
||||
* @group Database
|
||||
|
|
@ -144,32 +24,7 @@ abstract class ApiTestCase extends MediaWikiTestCase {
|
|||
*
|
||||
* This is pretty sucky... needs to be prettified.
|
||||
*/
|
||||
class ApiUploadTest extends ApiTestCase {
|
||||
/**
|
||||
* Fixture -- run before every test
|
||||
*/
|
||||
public function setUp() {
|
||||
global $wgEnableUploads, $wgEnableAPI;
|
||||
parent::setUp();
|
||||
|
||||
$wgEnableUploads = true;
|
||||
$wgEnableAPI = true;
|
||||
wfSetupSession();
|
||||
|
||||
ini_set( 'log_errors', 1 );
|
||||
ini_set( 'error_reporting', 1 );
|
||||
ini_set( 'display_errors', 1 );
|
||||
|
||||
$this->clearFakeUploads();
|
||||
}
|
||||
|
||||
/**
|
||||
* Fixture -- run after every test
|
||||
* Clean up temporary files etc.
|
||||
*/
|
||||
function tearDown() {
|
||||
}
|
||||
|
||||
class ApiUploadTest extends ApiTestCaseUpload {
|
||||
|
||||
/**
|
||||
* Testing login
|
||||
|
|
@ -575,98 +430,5 @@ class ApiUploadTest extends ApiTestCase {
|
|||
$this->deleteFileByFilename( $fileName );
|
||||
unlink( $filePath );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Helper function -- remove files and associated articles by Title
|
||||
* @param $title Title: title to be removed
|
||||
*/
|
||||
public function deleteFileByTitle( $title ) {
|
||||
if ( $title->exists() ) {
|
||||
$file = wfFindFile( $title, array( 'ignoreRedirect' => true ) );
|
||||
$noOldArchive = ""; // yes this really needs to be set this way
|
||||
$comment = "removing for test";
|
||||
$restrictDeletedVersions = false;
|
||||
$status = FileDeleteForm::doDelete( $title, $file, $noOldArchive, $comment, $restrictDeletedVersions );
|
||||
if ( !$status->isGood() ) {
|
||||
return false;
|
||||
}
|
||||
$article = new Article( $title );
|
||||
$article->doDeleteArticle( "removing for test" );
|
||||
|
||||
// see if it now doesn't exist; reload
|
||||
$title = Title::newFromText( $fileName, NS_FILE );
|
||||
}
|
||||
return ! ( $title && $title instanceof Title && $title->exists() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function -- remove files and associated articles with a particular filename
|
||||
* @param $fileName String: filename to be removed
|
||||
*/
|
||||
public function deleteFileByFileName( $fileName ) {
|
||||
return $this->deleteFileByTitle( Title::newFromText( $fileName, NS_FILE ) );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Helper function -- given a file on the filesystem, find matching content in the db (and associated articles) and remove them.
|
||||
* @param $filePath String: path to file on the filesystem
|
||||
*/
|
||||
public function deleteFileByContent( $filePath ) {
|
||||
$hash = File::sha1Base36( $filePath );
|
||||
$dupes = RepoGroup::singleton()->findBySha1( $hash );
|
||||
$success = true;
|
||||
foreach ( $dupes as $dupe ) {
|
||||
$success &= $this->deleteFileByTitle( $dupe->getTitle() );
|
||||
}
|
||||
return $success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fake an upload by dumping the file into temp space, and adding info to $_FILES.
|
||||
* (This is what PHP would normally do).
|
||||
* @param $fieldName String: name this would have in the upload form
|
||||
* @param $fileName String: name to title this
|
||||
* @param $type String: mime type
|
||||
* @param $filePath String: path where to find file contents
|
||||
*/
|
||||
function fakeUploadFile( $fieldName, $fileName, $type, $filePath ) {
|
||||
$tmpName = tempnam( wfTempDir(), "" );
|
||||
if ( !file_exists( $filePath ) ) {
|
||||
throw new Exception( "$filePath doesn't exist!" );
|
||||
};
|
||||
|
||||
if ( !copy( $filePath, $tmpName ) ) {
|
||||
throw new Exception( "couldn't copy $filePath 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
|
||||
);
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove traces of previous fake uploads
|
||||
*/
|
||||
function clearFakeUploads() {
|
||||
$_FILES = array();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue