ParserTestTopLevelSuite.php 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. <?php
  2. use Wikimedia\ScopedCallback;
  3. /**
  4. * The UnitTest must be either a class that inherits from MediaWikiTestCase
  5. * or a class that provides a public static suite() method which returns
  6. * an PHPUnit_Framework_Test object
  7. *
  8. * @group Parser
  9. * @group ParserTests
  10. * @group Database
  11. */
  12. class ParserTestTopLevelSuite extends PHPUnit_Framework_TestSuite {
  13. /** @var ParserTestRunner */
  14. private $ptRunner;
  15. /** @var ScopedCallback */
  16. private $ptTeardownScope;
  17. private $oldTablePrefix = '';
  18. /**
  19. * @defgroup filtering_constants Filtering constants
  20. *
  21. * Limit inclusion of parser tests files coming from MediaWiki core
  22. * @{
  23. */
  24. /** Include files shipped with MediaWiki core */
  25. const CORE_ONLY = 1;
  26. /** Include non core files as set in $wgParserTestFiles */
  27. const NO_CORE = 2;
  28. /** Include anything set via $wgParserTestFiles */
  29. const WITH_ALL = self::CORE_ONLY | self::NO_CORE;
  30. /** @} */
  31. /**
  32. * Get a PHPUnit test suite of parser tests. Optionally filtered with
  33. * $flags.
  34. *
  35. * @par Examples:
  36. * Get a suite of parser tests shipped by MediaWiki core:
  37. * @code
  38. * ParserTestTopLevelSuite::suite( ParserTestTopLevelSuite::CORE_ONLY );
  39. * @endcode
  40. * Get a suite of various parser tests, like extensions:
  41. * @code
  42. * ParserTestTopLevelSuite::suite( ParserTestTopLevelSuite::NO_CORE );
  43. * @endcode
  44. * Get any test defined via $wgParserTestFiles:
  45. * @code
  46. * ParserTestTopLevelSuite::suite( ParserTestTopLevelSuite::WITH_ALL );
  47. * @endcode
  48. *
  49. * @param int $flags Bitwise flag to filter out the $wgParserTestFiles that
  50. * will be included. Default: ParserTestTopLevelSuite::CORE_ONLY
  51. *
  52. * @return PHPUnit_Framework_TestSuite
  53. */
  54. public static function suite( $flags = self::CORE_ONLY ) {
  55. return new self( $flags );
  56. }
  57. function __construct( $flags ) {
  58. parent::__construct();
  59. $this->ptRecorder = new PhpunitTestRecorder;
  60. $this->ptRunner = new ParserTestRunner( $this->ptRecorder );
  61. if ( is_string( $flags ) ) {
  62. $flags = self::CORE_ONLY;
  63. }
  64. global $IP;
  65. $mwTestDir = $IP . '/tests/';
  66. # Human friendly helpers
  67. $wantsCore = ( $flags & self::CORE_ONLY );
  68. $wantsRest = ( $flags & self::NO_CORE );
  69. # Will hold the .txt parser test files we will include
  70. $filesToTest = [];
  71. # Filter out .txt files
  72. $files = ParserTestRunner::getParserTestFiles();
  73. foreach ( $files as $extName => $parserTestFile ) {
  74. $isCore = ( 0 === strpos( $parserTestFile, $mwTestDir ) );
  75. if ( $isCore && $wantsCore ) {
  76. self::debug( "included core parser tests: $parserTestFile" );
  77. $filesToTest[$extName] = $parserTestFile;
  78. } elseif ( !$isCore && $wantsRest ) {
  79. self::debug( "included non core parser tests: $parserTestFile" );
  80. $filesToTest[$extName] = $parserTestFile;
  81. } else {
  82. self::debug( "skipped parser tests: $parserTestFile" );
  83. }
  84. }
  85. self::debug( 'parser tests files: '
  86. . implode( ' ', $filesToTest ) );
  87. $testList = [];
  88. $counter = 0;
  89. foreach ( $filesToTest as $extensionName => $fileName ) {
  90. if ( is_int( $extensionName ) ) {
  91. // If there's no extension name because this is coming
  92. // from the legacy global, then assume the next level directory
  93. // is the extension name (e.g. extensions/FooBar/parserTests.txt).
  94. $extensionName = basename( dirname( $fileName ) );
  95. }
  96. $testsName = $extensionName . '__' . basename( $fileName, '.txt' );
  97. $parserTestClassName = ucfirst( $testsName );
  98. // Official spec for class names: https://secure.php.net/manual/en/language.oop5.basic.php
  99. // Prepend 'ParserTest_' to be paranoid about it not starting with a number
  100. $parserTestClassName = 'ParserTest_' .
  101. preg_replace( '/[^a-zA-Z0-9_\x7f-\xff]/', '_', $parserTestClassName );
  102. if ( isset( $testList[$parserTestClassName] ) ) {
  103. // If there is a conflict, append a number.
  104. $counter++;
  105. $parserTestClassName .= $counter;
  106. }
  107. $testList[$parserTestClassName] = true;
  108. // Previously we actually created a class here, with eval(). We now
  109. // just override the name.
  110. self::debug( "Adding test class $parserTestClassName" );
  111. $this->addTest( new ParserTestFileSuite(
  112. $this->ptRunner, $parserTestClassName, $fileName ) );
  113. }
  114. }
  115. public function setUp() {
  116. wfDebug( __METHOD__ );
  117. $db = wfGetDB( DB_MASTER );
  118. $type = $db->getType();
  119. $prefix = $type === 'oracle' ?
  120. MediaWikiTestCase::ORA_DB_PREFIX : MediaWikiTestCase::DB_PREFIX;
  121. $this->oldTablePrefix = $db->tablePrefix();
  122. MediaWikiTestCase::setupTestDB( $db, $prefix );
  123. CloneDatabase::changePrefix( $prefix );
  124. $this->ptRunner->setDatabase( $db );
  125. MediaWikiTestCase::resetNonServiceCaches();
  126. MediaWikiTestCase::installMockMwServices();
  127. $teardown = new ScopedCallback( function () {
  128. MediaWikiTestCase::restoreMwServices();
  129. } );
  130. $teardown = $this->ptRunner->setupUploads( $teardown );
  131. $this->ptTeardownScope = $teardown;
  132. }
  133. public function tearDown() {
  134. wfDebug( __METHOD__ );
  135. if ( $this->ptTeardownScope ) {
  136. ScopedCallback::consume( $this->ptTeardownScope );
  137. }
  138. CloneDatabase::changePrefix( $this->oldTablePrefix );
  139. }
  140. /**
  141. * Write $msg under log group 'tests-parser'
  142. * @param string $msg Message to log
  143. */
  144. protected static function debug( $msg ) {
  145. wfDebugLog( 'tests-parser', wfGetCaller() . ' ' . $msg );
  146. }
  147. }