PageRenderTime 26ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/tests/phpunit/MediaWikiTestCase.php

https://github.com/daevid/MWFork
PHP | 250 lines | 165 code | 55 blank | 30 comment | 27 complexity | b569efd6a974eeecae08356d5f2c9212 MD5 | raw file
  1. <?php
  2. abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
  3. public $suite;
  4. public $regex = '';
  5. public $runDisabled = false;
  6. /**
  7. * @var DatabaseBase
  8. */
  9. protected $db;
  10. protected $oldTablePrefix;
  11. protected $useTemporaryTables = true;
  12. private static $dbSetup = false;
  13. /**
  14. * Table name prefixes. Oracle likes it shorter.
  15. */
  16. const DB_PREFIX = 'unittest_';
  17. const ORA_DB_PREFIX = 'ut_';
  18. protected $supportedDBs = array(
  19. 'mysql',
  20. 'sqlite',
  21. 'oracle'
  22. );
  23. function __construct( $name = null, array $data = array(), $dataName = '' ) {
  24. parent::__construct( $name, $data, $dataName );
  25. $this->backupGlobals = false;
  26. $this->backupStaticAttributes = false;
  27. }
  28. function run( PHPUnit_Framework_TestResult $result = NULL ) {
  29. /* Some functions require some kind of caching, and will end up using the db,
  30. * which we can't allow, as that would open a new connection for mysql.
  31. * Replace with a HashBag. They would not be going to persist anyway.
  32. */
  33. ObjectCache::$instances[CACHE_DB] = new HashBagOStuff;
  34. if( $this->needsDB() ) {
  35. global $wgDBprefix;
  36. $this->db = wfGetDB( DB_MASTER );
  37. $this->checkDbIsSupported();
  38. $this->oldTablePrefix = $wgDBprefix;
  39. if( !self::$dbSetup ) {
  40. $this->initDB();
  41. self::$dbSetup = true;
  42. }
  43. $this->addCoreDBData();
  44. $this->addDBData();
  45. parent::run( $result );
  46. $this->resetDB();
  47. } else {
  48. parent::run( $result );
  49. }
  50. }
  51. function dbPrefix() {
  52. return $this->db->getType() == 'oracle' ? self::ORA_DB_PREFIX : self::DB_PREFIX;
  53. }
  54. function needsDB() {
  55. $rc = new ReflectionClass( $this );
  56. return strpos( $rc->getDocComment(), '@group Database' ) !== false;
  57. }
  58. /**
  59. * Stub. If a test needs to add additional data to the database, it should
  60. * implement this method and do so
  61. */
  62. function addDBData() {}
  63. private function addCoreDBData() {
  64. User::resetIdByNameCache();
  65. //Make sysop user
  66. $user = User::newFromName( 'UTSysop' );
  67. if ( $user->idForName() == 0 ) {
  68. $user->addToDatabase();
  69. $user->setPassword( 'UTSysopPassword' );
  70. $user->addGroup( 'sysop' );
  71. $user->addGroup( 'bureaucrat' );
  72. $user->saveSettings();
  73. }
  74. //Make 1 page with 1 revision
  75. $article = new Article( Title::newFromText( 'UTPage' ) );
  76. $article->doEdit( 'UTContent',
  77. 'UTPageSummary',
  78. EDIT_NEW,
  79. false,
  80. User::newFromName( 'UTSysop' ) );
  81. }
  82. private function initDB() {
  83. global $wgDBprefix;
  84. if ( $wgDBprefix === $this->dbPrefix() ) {
  85. throw new MWException( 'Cannot run unit tests, the database prefix is already "unittest_"' );
  86. }
  87. $dbClone = new CloneDatabase( $this->db, $this->listTables(), $this->dbPrefix() );
  88. $dbClone->useTemporaryTables( $this->useTemporaryTables );
  89. $dbClone->cloneTableStructure();
  90. if ( $this->db->getType() == 'oracle' ) {
  91. $this->db->query( 'BEGIN FILL_WIKI_INFO; END;' );
  92. # Insert 0 user to prevent FK violations
  93. # Anonymous user
  94. $this->db->insert( 'user', array(
  95. 'user_id' => 0,
  96. 'user_name' => 'Anonymous' ) );
  97. }
  98. }
  99. /**
  100. * Empty all tables so they can be repopulated for tests
  101. */
  102. private function resetDB() {
  103. if( $this->db ) {
  104. foreach( $this->listTables() as $tbl ) {
  105. if( $tbl == 'interwiki' || $tbl == 'user' ) continue;
  106. $this->db->delete( $tbl, '*', __METHOD__ );
  107. }
  108. }
  109. }
  110. protected function destroyDB() {
  111. if ( $this->useTemporaryTables || is_null( $this->db ) ) {
  112. # Don't need to do anything
  113. return;
  114. }
  115. $tables = $this->db->listTables( $this->dbPrefix(), __METHOD__ );
  116. foreach ( $tables as $table ) {
  117. try {
  118. $sql = $this->db->getType() == 'oracle' ? "DROP TABLE $table CASCADE CONSTRAINTS PURGE" : "DROP TABLE `$table`";
  119. $this->db->query( $sql, __METHOD__ );
  120. } catch( MWException $mwe ) {}
  121. }
  122. if ( $this->db->getType() == 'oracle' )
  123. $this->db->query( 'BEGIN FILL_WIKI_INFO; END;', __METHOD__ );
  124. CloneDatabase::changePrefix( $this->oldTablePrefix );
  125. }
  126. function __call( $func, $args ) {
  127. static $compatibility = array(
  128. 'assertInternalType' => 'assertType',
  129. 'assertNotInternalType' => 'assertNotType',
  130. 'assertInstanceOf' => 'assertType',
  131. 'assertEmpty' => 'assertEmpty2',
  132. );
  133. if ( method_exists( $this->suite, $func ) ) {
  134. return call_user_func_array( array( $this->suite, $func ), $args);
  135. } elseif ( isset( $compatibility[$func] ) ) {
  136. return call_user_func_array( array( $this, $compatibility[$func] ), $args);
  137. } else {
  138. throw new MWException( "Called non-existant $func method on "
  139. . get_class( $this ) );
  140. }
  141. }
  142. private function assertEmpty2( $value, $msg ) {
  143. return $this->assertTrue( $value == '', $msg );
  144. }
  145. static private function unprefixTable( $tableName ) {
  146. global $wgDBprefix;
  147. return substr( $tableName, strlen( $wgDBprefix ) );
  148. }
  149. static private function isNotUnittest( $table ) {
  150. return strpos( $table, 'unittest_' ) !== 0;
  151. }
  152. protected function listTables() {
  153. global $wgDBprefix;
  154. $tables = $this->db->listTables( $wgDBprefix, __METHOD__ );
  155. $tables = array_map( array( __CLASS__, 'unprefixTable' ), $tables );
  156. // Don't duplicate test tables from the previous fataled run
  157. $tables = array_filter( $tables, array( __CLASS__, 'isNotUnittest' ) );
  158. if ( $this->db->getType() == 'sqlite' ) {
  159. $tables = array_flip( $tables );
  160. // these are subtables of searchindex and don't need to be duped/dropped separately
  161. unset( $tables['searchindex_content'] );
  162. unset( $tables['searchindex_segdir'] );
  163. unset( $tables['searchindex_segments'] );
  164. $tables = array_flip( $tables );
  165. }
  166. return $tables;
  167. }
  168. protected function checkDbIsSupported() {
  169. if( !in_array( $this->db->getType(), $this->supportedDBs ) ) {
  170. throw new MWException( $this->db->getType() . " is not currently supported for unit testing." );
  171. }
  172. }
  173. public function getCliArg( $offset ) {
  174. if( isset( MediaWikiPHPUnitCommand::$additionalOptions[$offset] ) ) {
  175. return MediaWikiPHPUnitCommand::$additionalOptions[$offset];
  176. }
  177. }
  178. public function setCliArg( $offset, $value ) {
  179. MediaWikiPHPUnitCommand::$additionalOptions[$offset] = $value;
  180. }
  181. public static function disableInterwikis( $prefix, &$data ) {
  182. return false;
  183. }
  184. /**
  185. * Don't throw a warning if $function is deprecated and called later
  186. *
  187. * @param $function String
  188. * @return null
  189. */
  190. function hideDeprecated( $function ) {
  191. wfSuppressWarnings();
  192. wfDeprecated( $function );
  193. wfRestoreWarnings();
  194. }
  195. }