diff options
Diffstat (limited to 'www/wiki/extensions/Scribunto/tests/phpunit/engines/LuaSandbox')
3 files changed, 153 insertions, 0 deletions
diff --git a/www/wiki/extensions/Scribunto/tests/phpunit/engines/LuaSandbox/LuaSandboxInterpreterTest.php b/www/wiki/extensions/Scribunto/tests/phpunit/engines/LuaSandbox/LuaSandboxInterpreterTest.php new file mode 100644 index 00000000..256e8c6a --- /dev/null +++ b/www/wiki/extensions/Scribunto/tests/phpunit/engines/LuaSandbox/LuaSandboxInterpreterTest.php @@ -0,0 +1,34 @@ +<?php + +if ( !wfIsCLI() ) { + exit; +} + +require_once __DIR__ . '/../LuaCommon/LuaInterpreterTest.php'; + +/** + * @group Lua + * @group LuaSandbox + */ +// @codingStandardsIgnoreLine Squiz.Classes.ValidClassName.NotCamelCaps +class Scribunto_LuaSandboxInterpreterTest extends Scribunto_LuaInterpreterTest { + public $stdOpts = [ + 'memoryLimit' => 50000000, + 'cpuLimit' => 30, + ]; + + protected function newInterpreter( $opts = [] ) { + $opts = $opts + $this->stdOpts; + $engine = new Scribunto_LuaSandboxEngine( $this->stdOpts ); + return new Scribunto_LuaSandboxInterpreter( $engine, $opts ); + } + + public function testGetMemoryUsage() { + $interpreter = $this->newInterpreter(); + $chunk = $interpreter->loadString( 's = string.rep("x", 1000000)', 'mem' ); + $interpreter->callFunction( $chunk ); + $mem = $interpreter->getPeakMemoryUsage(); + $this->assertGreaterThan( 1000000, $mem, 'memory usage' ); + $this->assertLessThan( 10000000, $mem, 'memory usage' ); + } +} diff --git a/www/wiki/extensions/Scribunto/tests/phpunit/engines/LuaSandbox/SandboxTest.php b/www/wiki/extensions/Scribunto/tests/phpunit/engines/LuaSandbox/SandboxTest.php new file mode 100644 index 00000000..db80f5cf --- /dev/null +++ b/www/wiki/extensions/Scribunto/tests/phpunit/engines/LuaSandbox/SandboxTest.php @@ -0,0 +1,101 @@ +<?php + +// @codingStandardsIgnoreLine Squiz.Classes.ValidClassName.NotCamelCaps +class Scribunto_LuaSandboxTest extends Scribunto_LuaEngineTestBase { + protected static $moduleName = 'SandboxTests'; + + public static function suite( $className ) { + return self::makeSuite( $className, 'LuaSandbox' ); + } + + protected function getTestModules() { + return parent::getTestModules() + [ + 'SandboxTests' => __DIR__ . '/SandboxTests.lua', + ]; + } + + public function testArgumentParsingTime() { + if ( !wfGetRusage() ) { + $this->markTestSkipped( "getrusage is not available" ); + } + + $engine = $this->getEngine(); + $parser = $engine->getParser(); + $pp = $parser->getPreprocessor(); + $frame = $pp->newFrame(); + + $parser->setHook( 'scribuntodelay', function () { + $endTime = $this->getRuTime() + 0.5; + + // Waste CPU cycles + do { + $t = $this->getRuTime(); + } while ( $t < $endTime ); + + return "ok"; + } ); + $this->extraModules['Module:TestArgumentParsingTime'] = ' + return { + f = function ( frame ) + return frame.args[1] + end, + f2 = function ( frame ) + return frame:preprocess( "{{#invoke:TestArgumentParsingTime|f|}}" ) + end, + f3 = function ( frame ) + return frame:preprocess( "{{#invoke:TestArgumentParsingTime|f|<scribuntodelay/>}}" ) + end, + } + '; + + // Below we assert that the CPU time counted by LuaSandbox is $delta less than + // the CPU time actually spent. + // That way we can make sure that the time spent in the parser hook (which + // must be more than delta) is not taken into account. + $delta = 0.25; + + $u0 = $engine->getInterpreter()->getCPUUsage(); + $uTimeBefore = $this->getRuTime(); + $frame->expand( + $pp->preprocessToObj( + '{{#invoke:TestArgumentParsingTime|f|<scribuntodelay/>}}' + ) + ); + $threshold = $this->getRuTime() - $uTimeBefore - $delta; + $this->assertLessThan( $threshold, $engine->getInterpreter()->getCPUUsage() - $u0, + 'Argument access time was not counted' + ); + + $uTimeBefore = $this->getRuTime(); + $u0 = $engine->getInterpreter()->getCPUUsage(); + $frame->expand( + $pp->preprocessToObj( + '{{#invoke:TestArgumentParsingTime|f2|<scribuntodelay/>}}' + ) + ); + $threshold = $this->getRuTime() - $uTimeBefore - $delta; + $this->assertLessThan( $threshold, $engine->getInterpreter()->getCPUUsage() - $u0, + 'Unused arguments not counted in preprocess' + ); + + $uTimeBefore = $this->getRuTime(); + $u0 = $engine->getInterpreter()->getCPUUsage(); + $frame->expand( + $pp->preprocessToObj( + '{{#invoke:TestArgumentParsingTime|f3}}' + ) + ); + $threshold = $this->getRuTime() - $uTimeBefore - $delta; + // If the underlying node is extremely slow, this test might produce false positives + $this->assertGreaterThan( $threshold, $engine->getInterpreter()->getCPUUsage() - $u0, + 'Recursive argument access time was counted' + ); + } + + private function getRuTime() { + $ru = wfGetRusage(); + return $ru['ru_utime.tv_sec'] + $ru['ru_utime.tv_usec'] / 1e6 + + $ru['ru_stime.tv_sec'] + $ru['ru_stime.tv_usec'] / 1e6; + } + +} diff --git a/www/wiki/extensions/Scribunto/tests/phpunit/engines/LuaSandbox/SandboxTests.lua b/www/wiki/extensions/Scribunto/tests/phpunit/engines/LuaSandbox/SandboxTests.lua new file mode 100644 index 00000000..2ae5a561 --- /dev/null +++ b/www/wiki/extensions/Scribunto/tests/phpunit/engines/LuaSandbox/SandboxTests.lua @@ -0,0 +1,18 @@ +local testframework = require( 'Module:TestFramework' ) + +local function setfenv1() + setfenv( 10, {} ) +end + +local function getfenv1() + assert( getfenv( 10 ) == nil ) +end + +return testframework.getTestProvider( { + { name = 'setfenv invalid level', func = setfenv1, + expect = "bad argument #1 to 'old_getfenv' (invalid level)", + }, + { name = 'getfenv invalid level', func = getfenv1, + expect = "bad argument #1 to 'old_getfenv' (invalid level)", + }, +} ) |