Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
Total | |
0.00% |
0 / 1 |
|
0.00% |
0 / 2 |
CRAP | |
53.66% |
44 / 82 |
TestFileReader | |
0.00% |
0 / 1 |
|
0.00% |
0 / 2 |
133.91 | |
53.66% |
44 / 82 |
read | |
0.00% |
0 / 1 |
12 | |
0.00% |
0 / 9 |
|||
__construct | |
0.00% |
0 / 1 |
81.73 | |
60.27% |
44 / 73 |
<?php | |
declare( strict_types = 1 ); | |
namespace Wikimedia\Parsoid\ParserTests; | |
class TestFileReader { | |
/** @var array File-level options and requirements for these parser tests */ | |
public $fileOptions = []; | |
/** @var Test[] */ | |
public $testCases = []; | |
/** @var Article[] */ | |
public $articles = []; | |
/** | |
* @var ?string Path to known failures file, or null if does not exist | |
* or is not readable. | |
*/ | |
public $knownFailuresPath; | |
/** | |
* Read and parse a parserTest file. | |
* @param string $testFilePath The parserTest file to read | |
* @param ?callable(string) $warnFunc An optional function to use to | |
* report the use of deprecated test section names | |
* @param ?callable(string):string $normalizeFunc An optional function | |
* to use to normalize article titles for uniqueness testing | |
* @return TestFileReader | |
*/ | |
public static function read( | |
string $testFilePath, | |
?callable $warnFunc = null, | |
?callable $normalizeFunc = null | |
): TestFileReader { | |
$info = pathinfo( $testFilePath ); | |
$knownFailuresPath = $info['dirname'] . '/' . $info['filename'] . | |
'-knownFailures.json'; | |
$reader = new self( | |
$testFilePath, | |
$knownFailuresPath, | |
$warnFunc, | |
$normalizeFunc | |
); | |
return $reader; | |
} | |
/** | |
* @param string $testFilePath The parserTest file to read | |
* @param ?string $knownFailuresPath The known failures file to read | |
* (or null, if there is no readable known failures file) | |
* @param ?callable(string) $warnFunc An optional function to use to | |
* report the use of deprecated test section names | |
* @param ?callable(string):string $normalizeFunc An optional function | |
* to use to normalize article titles for uniqueness testing | |
*/ | |
private function __construct( | |
string $testFilePath, ?string $knownFailuresPath, | |
?callable $warnFunc = null, ?callable $normalizeFunc = null | |
) { | |
$this->knownFailuresPath = $knownFailuresPath && is_readable( $knownFailuresPath ) ? | |
$knownFailuresPath : null; | |
$parsedTests = Grammar::load( $testFilePath ); | |
// Start off with any comments before `!! format` | |
$rawTestItems = $parsedTests[0]; | |
$testFormat = $parsedTests[1]; | |
if ( $testFormat != null ) { | |
// If `!!format` was present, existing comments applied to the | |
// format declaration, not the first item. | |
$rawTestItems = []; | |
} | |
// Add any comments after `!! format` | |
array_splice( $rawTestItems, count( $rawTestItems ), 0, $parsedTests[2] ); | |
if ( $parsedTests[3] == null ) { | |
$this->fileOptions = []; | |
} else { | |
$this->fileOptions = $parsedTests[3]['text']; | |
// If `!!options` was present, existing comments applied to the | |
// file options, not the first item. | |
$rawTestItems = []; | |
} | |
// Add the rest of the comments and items appearing after `!!options` | |
array_splice( $rawTestItems, count( $rawTestItems ), 0, $parsedTests[4] ); | |
if ( $testFormat !== null ) { | |
if ( isset( $this->fileOptions['version'] ) ) { | |
( new Item( $parsedTests[3] ) )->error( 'Duplicate version specification' ); | |
} else { | |
$this->fileOptions['version'] = $testFormat['text']; | |
} | |
} | |
if ( !isset( $this->fileOptions['version'] ) ) { | |
$this->fileOptions['version'] = '1'; | |
} | |
$knownFailures = $this->knownFailuresPath !== null ? | |
json_decode( file_get_contents( $knownFailuresPath ), true ) : | |
null; | |
$testNames = []; | |
$articleTitles = []; | |
$lastComment = ''; | |
foreach ( $rawTestItems as $item ) { | |
if ( $item['type'] === 'article' ) { | |
$art = new Article( $item, $lastComment ); | |
$key = $normalizeFunc ? $normalizeFunc( $art->title ) : $art->title; | |
if ( isset( $articleTitles[$key] ) ) { | |
$art->error( 'Duplicate article', $art->title ); | |
} | |
$articleTitles[$key] = true; | |
$this->articles[] = $art; | |
$lastComment = ''; | |
} elseif ( $item['type'] === 'test' ) { | |
$test = new Test( | |
$item, | |
$knownFailures[$item['testName']] ?? [], | |
$lastComment, | |
$warnFunc | |
); | |
if ( isset( $testNames[$test->testName] ) ) { | |
$test->error( 'Duplicate test name', $test->testName ); | |
} | |
$testNames[$test->testName] = true; | |
$this->testCases[] = $test; | |
$lastComment = ''; | |
} elseif ( $item['type'] === 'comment' ) { | |
$lastComment .= $item['text']; | |
} elseif ( $item['type'] === 'hooks' ) { | |
foreach ( explode( "\n", $item['text'] ) as $line ) { | |
$this->fileOptions['requirements'][] = [ | |
'type' => 'hook', | |
'name' => trim( $line ), | |
]; | |
} | |
$lastComment = ''; | |
} elseif ( $item['type'] === 'functionhooks' ) { | |
foreach ( explode( "\n", $item['text'] ) as $line ) { | |
$this->fileOptions['requirements'][] = [ | |
'type' => 'functionHook', | |
'name' => trim( $line ), | |
]; | |
} | |
$lastComment = ''; | |
} elseif ( $item['type'] === 'line' ) { | |
if ( !empty( trim( $item['text'] ) ) ) { | |
( new Item( $item ) )->error( 'Invalid line', $item['text'] ); | |
} | |
} else { | |
( new Item( $item ) )->error( 'Unknown item type', $item['type'] ); | |
} | |
} | |
// Convenience function to expand 'requirements' | |
if ( isset( $this->fileOptions['requirements'] ) ) { | |
if ( !is_array( $this->fileOptions['requirements'] ) ) { | |
$this->fileOptions['requirements'] = [ | |
$this->fileOptions['requirements'] | |
]; | |
} | |
foreach ( $this->fileOptions['requirements'] as &$item ) { | |
if ( is_string( $item ) ) { | |
$item = [ | |
'type' => 'hook', | |
'name' => "$item", | |
]; | |
} | |
} | |
unset( $item ); | |
} | |
} | |
} |