* @ingroup Testing
*/
-class TestFileReader implements Iterator {
+class TestFileReader {
private $file;
private $fh;
- /**
- * @var ParserTestRunner|ParserTestTopLevelSuite An instance of ParserTestRunner
- * (parserTests.php) or ParserTestTopLevelSuite (phpunit)
- */
- private $parserTest;
- private $index = 0;
- private $test;
private $section = null;
/** String|null: current test section being analyzed */
private $sectionData = [];
- private $lineNum;
- private $eof;
- # Create a fake parser tests which never run anything unless
- # asked to do so. This will avoid running hooks for a disabled test
- private $delayedParserTest;
- private $nextSubTest = 0;
-
- function __construct( $file, $parserTest ) {
- $this->file = $file;
- $this->fh = fopen( $this->file, "rt" );
-
- if ( !$this->fh ) {
- throw new MWException( "Couldn't open file '$file'\n" );
- }
-
- $this->parserTest = $parserTest;
- $this->delayedParserTest = new DelayedParserTest();
-
- $this->lineNum = $this->index = 0;
- }
-
- function rewind() {
- if ( fseek( $this->fh, 0 ) ) {
- throw new MWException( "Couldn't fseek to the start of '$this->file'\n" );
+ private $lineNum = 0;
+ private $runDisabled;
+ private $runParsoid;
+ private $regex;
+
+ private $articles = [];
+ private $requirements = [];
+ private $tests = [];
+
+ public static function read( $file, array $options = [] ) {
+ $reader = new self( $file, $options );
+ $reader->execute();
+
+ $requirements = [];
+ foreach ( $reader->requirements as $type => $reqsOfType ) {
+ foreach ( $reqsOfType as $name => $unused ) {
+ $requirements[] = [
+ 'type' => $type,
+ 'name' => $name
+ ];
+ }
}
- $this->index = -1;
- $this->lineNum = 0;
- $this->eof = false;
- $this->next();
-
- return true;
- }
-
- function current() {
- return $this->test;
+ return [
+ 'requirements' => $requirements,
+ 'tests' => $reader->tests,
+ 'articles' => $reader->articles
+ ];
}
- function key() {
- return $this->index;
- }
+ private function __construct( $file, $options ) {
+ $this->file = $file;
+ $this->fh = fopen( $this->file, "rt" );
- function next() {
- if ( $this->readNextTest() ) {
- $this->index++;
- return true;
- } else {
- $this->eof = true;
+ if ( !$this->fh ) {
+ throw new MWException( "Couldn't open file '$file'\n" );
}
- }
- function valid() {
- return $this->eof != true;
+ $options = $options + [
+ 'runDisabled' => false,
+ 'runParsoid' => false,
+ 'regex' => '//',
+ ];
+ $this->runDisabled = $options['runDisabled'];
+ $this->runParsoid = $options['runParsoid'];
+ $this->regex = $options['regex'];
}
- function setupCurrentTest() {
+ private function addCurrentTest() {
// "input" and "result" are old section names allowed
// for backwards-compatibility.
$input = $this->checkSection( [ 'wikitext', 'input' ], false );
$result = $this->checkSection( [ 'html/php', 'html/*', 'html', 'result' ], false );
- // some tests have "with tidy" and "without tidy" variants
+ // Some tests have "with tidy" and "without tidy" variants
$tidy = $this->checkSection( [ 'html/php+tidy', 'html+tidy' ], false );
- if ( $tidy != false ) {
- if ( $this->nextSubTest == 0 ) {
- if ( $result != false ) {
- $this->nextSubTest = 1; // rerun non-tidy variant later
- }
- $result = $tidy;
- } else {
- $this->nextSubTest = 0; // go on to next test after this
- $tidy = false;
- }
- }
if ( !isset( $this->sectionData['options'] ) ) {
$this->sectionData['options'] = '';
}
$isDisabled = preg_match( '/\\bdisabled\\b/i', $this->sectionData['options'] ) &&
- !$this->parserTest->runDisabled;
+ !$this->runDisabled;
$isParsoidOnly = preg_match( '/\\bparsoid\\b/i', $this->sectionData['options'] ) &&
$result == 'html' &&
- !$this->parserTest->runParsoid;
- $isFiltered = !preg_match( "/" . $this->parserTest->regex . "/i", $this->sectionData['test'] );
+ !$this->runParsoid;
+ $isFiltered = !preg_match( $this->regex, $this->sectionData['test'] );
if ( $input == false || $result == false || $isDisabled || $isParsoidOnly || $isFiltered ) {
- # disabled test
- return false;
+ // Disabled test
+ return;
}
- # We are really going to run the test, run pending hooks and hooks function
- wfDebug( __METHOD__ . " unleashing delayed test for: {$this->sectionData['test']}" );
- $hooksResult = $this->delayedParserTest->unleash( $this->parserTest );
- if ( !$hooksResult ) {
- # Some hook reported an issue. Abort.
- throw new MWException( "Problem running requested parser hook from the test file" );
- }
-
- $this->test = [
+ $test = [
'test' => ParserTestRunner::chomp( $this->sectionData['test'] ),
- 'subtest' => $this->nextSubTest,
'input' => ParserTestRunner::chomp( $this->sectionData[$input] ),
'result' => ParserTestRunner::chomp( $this->sectionData[$result] ),
'options' => ParserTestRunner::chomp( $this->sectionData['options'] ),
'config' => ParserTestRunner::chomp( $this->sectionData['config'] ),
];
- if ( $tidy != false ) {
- $this->test['options'] .= " tidy";
+ $test['desc'] = $test['test'];
+ $this->tests[] = $test;
+
+ if ( $tidy !== false ) {
+ $test['options'] .= " tidy";
+ $test['desc'] .= ' (with tidy)';
+ $test['result'] = ParserTestRunner::chomp( $this->sectionData[$tidy] );
+ $this->tests[] = $test;
}
- return true;
}
- function readNextTest() {
- # Run additional subtests of previous test
- while ( $this->nextSubTest > 0 ) {
- if ( $this->setupCurrentTest() ) {
- return true;
- }
- }
-
- $this->clearSection();
- # Reset hooks for the delayed test object
- $this->delayedParserTest->reset();
-
+ private function execute() {
while ( false !== ( $line = fgets( $this->fh ) ) ) {
$this->lineNum++;
$matches = [];
$this->checkSection( 'text' );
$this->checkSection( 'article' );
- $this->parserTest->addArticle(
+ $this->addArticle(
ParserTestRunner::chomp( $this->sectionData['article'] ),
$this->sectionData['text'], $this->lineNum );
$line = trim( $line );
if ( $line ) {
- $this->delayedParserTest->requireHook( $line );
+ $this->addRequirement( 'hook', $line );
}
}
$line = trim( $line );
if ( $line ) {
- $this->delayedParserTest->requireFunctionHook( $line );
+ $this->addRequirement( 'functionHook', $line );
}
}
$line = trim( $line );
if ( $line ) {
- $this->delayedParserTest->requireTransparentHook( $line );
+ $this->addRequirement( 'transparentHook', $line );
}
}
if ( $this->section == 'end' ) {
$this->checkSection( 'test' );
- do {
- if ( $this->setupCurrentTest() ) {
- return true;
- }
- } while ( $this->nextSubTest > 0 );
- # go on to next test (since this was disabled)
+ $this->addCurrentTest();
$this->clearSection();
- $this->delayedParserTest->reset();
continue;
}
$this->sectionData[$this->section] .= $line;
}
}
-
- return false;
}
/**
return array_values( $tokens )[0];
}
+
+ private function addArticle( $name, $text, $line ) {
+ $this->articles[] = [
+ 'name' => $name,
+ 'text' => $text,
+ 'line' => $line,
+ 'file' => $this->file
+ ];
+ }
+
+ private function addRequirement( $type, $name ) {
+ $this->requirements[$type][$name] = true;
+ }
}