diff options
Diffstat (limited to 'www/wiki/extensions/Scribunto/tests/phpunit/engines/LuaSandbox/SandboxTest.php')
-rw-r--r-- | www/wiki/extensions/Scribunto/tests/phpunit/engines/LuaSandbox/SandboxTest.php | 101 |
1 files changed, 101 insertions, 0 deletions
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; + } + +} |