mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/Scribunto
synced 2024-12-21 04:13:33 +00:00
1000d322e5
mw.loadData() allows for optimizing the loading Lua tables by requiring only one parse and lookup. However it's often easier for people to write/maintain bulk data in JSON rather than Lua tables. mw.loadJsonData() has roughly the same characteristics as mw.loadData() and it can be used on JSON content model pages in any namespace. As noted on the linked bug report, it's possible to already implement this by writing a wrapper Lua module that loads and parses the JSON content. But that requires a dummy module for each JSON page, which is just annoying and inconvenient. Test cases are copied from the mw.loadData() ones, with a few omissions for syntax not supported in JSON (e.g. NaN, infinity, etc.). Bug: T217500 Change-Id: I1b35ad27a37b94064707bb8c9b7108c7078ed4d1
216 lines
6 KiB
PHP
216 lines
6 KiB
PHP
<?php
|
|
|
|
namespace MediaWiki\Extension\Scribunto\Tests\Engines\LuaCommon;
|
|
|
|
use MediaWiki\Extension\Scribunto\Engines\LuaCommon\LuaInterpreterNotFoundError;
|
|
use MediaWiki\Extension\Scribunto\Engines\LuaSandbox\LuaSandboxEngine;
|
|
use MediaWiki\Extension\Scribunto\Engines\LuaStandalone\LuaStandaloneEngine;
|
|
use MediaWiki\Extension\Scribunto\ScribuntoEngineBase;
|
|
use MediaWiki\MediaWikiServices;
|
|
use Parser;
|
|
use ParserOptions;
|
|
use PHPUnit\Framework\DataProviderTestSuite;
|
|
use PHPUnit\Framework\TestSuite;
|
|
use PHPUnit\Framework\WarningTestCase;
|
|
use PHPUnit\Util\Test;
|
|
use ReflectionClass;
|
|
use Title;
|
|
|
|
/**
|
|
* Trait that helps LuaEngineTestBase and LuaEngineUnitTestBase
|
|
*/
|
|
trait LuaEngineTestHelper {
|
|
/** @var array[] */
|
|
private static $engineConfigurations = [
|
|
'LuaSandbox' => [
|
|
'class' => LuaSandboxEngine::class,
|
|
'memoryLimit' => 50000000,
|
|
'cpuLimit' => 30,
|
|
'allowEnvFuncs' => true,
|
|
'maxLangCacheSize' => 30,
|
|
],
|
|
'LuaStandalone' => [
|
|
'class' => LuaStandaloneEngine::class,
|
|
'errorFile' => null,
|
|
'luaPath' => null,
|
|
'memoryLimit' => 50000000,
|
|
'cpuLimit' => 30,
|
|
'allowEnvFuncs' => true,
|
|
'maxLangCacheSize' => 30,
|
|
],
|
|
];
|
|
/** @var int[] */
|
|
protected $templateLoadCounts = [];
|
|
|
|
/**
|
|
* Create a PHPUnit test suite to run the test against all engines
|
|
* @param string $className Test class name
|
|
* @param string|null $group Engine to run with, or null to run all engines
|
|
* @return TestSuite
|
|
*/
|
|
protected static function makeSuite( $className, $group = null ) {
|
|
$suite = new TestSuite;
|
|
$suite->setName( $className );
|
|
|
|
$class = new ReflectionClass( $className );
|
|
|
|
foreach ( self::$engineConfigurations as $engineName => $opts ) {
|
|
if ( $group !== null && $group !== $engineName ) {
|
|
continue;
|
|
}
|
|
|
|
try {
|
|
$parser = MediaWikiServices::getInstance()->getParserFactory()->create();
|
|
$parser->startExternalParse(
|
|
Title::newMainPage(),
|
|
ParserOptions::newFromAnon(),
|
|
Parser::OT_HTML,
|
|
true
|
|
);
|
|
$engineClass = $opts['class'];
|
|
$engine = new $engineClass(
|
|
self::$engineConfigurations[$engineName] + [ 'parser' => $parser ]
|
|
);
|
|
$parser->scribunto_engine = $engine;
|
|
$engine->setTitle( $parser->getTitle() );
|
|
$engine->getInterpreter();
|
|
} catch ( LuaInterpreterNotFoundError $e ) {
|
|
$suite->addTest(
|
|
new LuaEngineTestSkip(
|
|
$className, "interpreter for $engineName is not available"
|
|
), [ 'Lua', $engineName ]
|
|
);
|
|
continue;
|
|
}
|
|
|
|
// Work around PHPUnit breakage: the only straightforward way to
|
|
// get the data provider is to call Test::getProvidedData, but that
|
|
// instantiates the class without passing any parameters to the
|
|
// constructor. But we *need* that engine name.
|
|
self::$staticEngineName = $engineName;
|
|
|
|
$engineSuite = new DataProviderTestSuite;
|
|
$engineSuite->setName( "$engineName: $className" );
|
|
|
|
foreach ( $class->getMethods() as $method ) {
|
|
if ( Test::isTestMethod( $method ) && $method->isPublic() ) {
|
|
$name = $method->getName();
|
|
$groups = Test::getGroups( $className, $name );
|
|
$groups[] = 'Lua';
|
|
$groups[] = $engineName;
|
|
// Only run tests locally if the engine isn't the MW sandbox T125050
|
|
if ( $engineName !== 'LuaSandbox' ) {
|
|
$groups[] = 'Standalone';
|
|
}
|
|
$groups = array_unique( $groups );
|
|
|
|
$data = Test::getProvidedData( $className, $name );
|
|
if ( is_iterable( $data ) ) {
|
|
// with @dataProvider
|
|
$dataSuite = new DataProviderTestSuite(
|
|
$className . '::' . $name
|
|
);
|
|
foreach ( $data as $k => $v ) {
|
|
$dataSuite->addTest(
|
|
new $className( $name, $v, $k, $engineName ),
|
|
$groups
|
|
);
|
|
}
|
|
$engineSuite->addTest( $dataSuite );
|
|
} elseif ( $data === false ) {
|
|
// invalid @dataProvider
|
|
$engineSuite->addTest( new WarningTestCase(
|
|
"The data provider specified for {$className}::$name is invalid."
|
|
) );
|
|
} else {
|
|
// no @dataProvider
|
|
$engineSuite->addTest(
|
|
new $className( $name, [], '', $engineName ),
|
|
$groups
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
$suite->addTest( $engineSuite );
|
|
}
|
|
|
|
return $suite;
|
|
}
|
|
|
|
/**
|
|
* @return ScribuntoEngineBase
|
|
*/
|
|
protected function getEngine() {
|
|
if ( !$this->engine ) {
|
|
$parser = MediaWikiServices::getInstance()->getParserFactory()->create();
|
|
$options = ParserOptions::newFromAnon();
|
|
$options->setTemplateCallback( [ $this, 'templateCallback' ] );
|
|
$parser->startExternalParse( $this->getTestTitle(), $options, Parser::OT_HTML, true );
|
|
|
|
// HACK
|
|
if ( $this->engineName === 'LuaSandbox' ) {
|
|
$class = LuaSandboxEngine::class;
|
|
} elseif ( $this->engineName === 'LuaStandalone' ) {
|
|
$class = LuaStandaloneEngine::class;
|
|
}
|
|
|
|
$this->engine = new $class(
|
|
self::$engineConfigurations[$this->engineName] + [ 'parser' => $parser ]
|
|
);
|
|
$parser->scribunto_engine = $this->engine;
|
|
$this->engine->setTitle( $parser->getTitle() );
|
|
}
|
|
return $this->engine;
|
|
}
|
|
|
|
/**
|
|
* @see Parser::statelessFetchTemplate
|
|
* @param Title $title
|
|
* @param Parser|false $parser
|
|
* @return array
|
|
*/
|
|
public function templateCallback( $title, $parser ) {
|
|
$this->templateLoadCounts[$title->getFullText()] =
|
|
( $this->templateLoadCounts[$title->getFullText()] ?? 0 ) + 1;
|
|
if ( isset( $this->extraModules[$title->getFullText()] ) ) {
|
|
return [
|
|
'text' => $this->extraModules[$title->getFullText()],
|
|
'finalTitle' => $title,
|
|
'deps' => []
|
|
];
|
|
}
|
|
|
|
$modules = $this->getTestModules();
|
|
foreach ( $modules as $name => $fileName ) {
|
|
$modTitle = Title::makeTitle( NS_MODULE, $name );
|
|
if ( $modTitle->equals( $title ) ) {
|
|
return [
|
|
'text' => file_get_contents( $fileName ),
|
|
'finalTitle' => $title,
|
|
'deps' => []
|
|
];
|
|
}
|
|
}
|
|
return Parser::statelessFetchTemplate( $title, $parser );
|
|
}
|
|
|
|
/**
|
|
* Get the title used for unit tests
|
|
*
|
|
* @return Title
|
|
*/
|
|
protected function getTestTitle() {
|
|
return Title::newMainPage();
|
|
}
|
|
|
|
/**
|
|
* Reset the cached engine. The next call to getEngine() will return a new
|
|
* object.
|
|
*/
|
|
protected function resetEngine() {
|
|
$this->engine = null;
|
|
}
|
|
|
|
}
|