summaryrefslogtreecommitdiff
path: root/www/wiki/extensions/Scribunto/tests/phpunit/engines/LuaCommon/LuaEnvironmentComparisonTest.php
blob: 641722075b34b8b39e1bfa2ba3ffe1bbaca65a81 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
<?php

/**
 * @group Lua
 * @group LuaSandbox
 * @group LuaStandalone
 */
// @codingStandardsIgnoreLine Squiz.Classes.ValidClassName.NotCamelCaps
class Scribunto_LuaEnvironmentComparisonTest extends MediaWikiTestCase {
	public $sandboxOpts = [
		'memoryLimit' => 50000000,
		'cpuLimit' => 30,
		'allowEnvFuncs' => true,
	];
	public $standaloneOpts = [
		'errorFile' => null,
		'luaPath' => null,
		'memoryLimit' => 50000000,
		'cpuLimit' => 30,
		'allowEnvFuncs' => true,
	];

	protected $engines = [];

	private function makeEngine( $class, $opts ) {
		$parser = new Parser;
		$options = new ParserOptions;
		$options->setTemplateCallback( [ $this, 'templateCallback' ] );
		$parser->startExternalParse( Title::newMainPage(), $options, Parser::OT_HTML, true );
		$engine = new $class ( [ 'parser' => $parser ] + $opts );
		$parser->scribunto_engine = $engine;
		$engine->setTitle( $parser->getTitle() );
		$engine->getInterpreter();
		return $engine;
	}

	protected function setUp() {
		parent::setUp();

		try {
			$this->engines['LuaSandbox'] = $this->makeEngine(
				'Scribunto_LuaSandboxEngine', $this->sandboxOpts
			);
		} catch ( Scribunto_LuaInterpreterNotFoundError $e ) {
			$this->markTestSkipped( "LuaSandbox interpreter not available" );
			return;
		}

		try {
			$this->engines['LuaStandalone'] = $this->makeEngine(
				'Scribunto_LuaStandaloneEngine', $this->standaloneOpts
			);
		} catch ( Scribunto_LuaInterpreterNotFoundError $e ) {
			$this->markTestSkipped( "LuaStandalone interpreter not available" );
			return;
		}
	}

	protected function tearDown() {
		foreach ( $this->engines as $engine ) {
			$engine->destroy();
		}
		$this->engines = [];
		parent::tearDown();
	}

	private function getGlobalEnvironment( $engine ) {
		static $script = <<<LUA
			xxxseen = {}
			function xxxGetTable( t )
				if xxxseen[t] then
					return 'table'
				end
				local ret = {}
				xxxseen[t] = ret
				for k, v in pairs( t ) do
					if k ~= '_G' and string.sub( k, 1, 3 ) ~= 'xxx' then
						if type( v ) == 'table' then
							ret[k] = xxxGetTable( v )
						elseif type( v ) == 'string'
							or type( v ) == 'number'
							or type( v ) == 'boolean'
							or type( v ) == 'nil'
						then
							ret[k] = v
						else
							ret[k] = type( v )
						end
					end
				end
				return ret
			end
			return xxxGetTable( _G )
LUA;
		$func = $engine->getInterpreter()->loadString( $script, 'script' );
		return $engine->getInterpreter()->callFunction( $func );
	}

	public function testGlobalEnvironment() {
		// Grab the first engine as the "standard"
		$firstEngine = reset( $this->engines );
		$firstName = key( $this->engines );
		$firstEnv = $this->getGlobalEnvironment( $firstEngine );

		// Test all others against it
		foreach ( $this->engines as $secondName => $secondEngine ) {
			if ( $secondName !== $firstName ) {
				$secondEnv = $this->getGlobalEnvironment( $secondEngine );
				$this->assertEquals( $firstEnv, $secondEnv,
					"Environments for $firstName and $secondName are not equivalent" );
			}
		}
	}
}