Merge "Require $key in msg() functions"
[lhc/web/wiklou.git] / tests / phpunit / includes / parser / ParserOptionsTest.php
1 <?php
2
3 use Wikimedia\TestingAccessWrapper;
4 use Wikimedia\ScopedCallback;
5
6 class ParserOptionsTest extends MediaWikiTestCase {
7
8 /**
9 * @dataProvider provideIsSafeToCache
10 * @param bool $expect Expected value
11 * @param array $options Options to set
12 */
13 public function testIsSafeToCache( $expect, $options ) {
14 $popt = ParserOptions::newCanonical();
15 foreach ( $options as $name => $value ) {
16 $popt->setOption( $name, $value );
17 }
18 $this->assertSame( $expect, $popt->isSafeToCache() );
19 }
20
21 public static function provideIsSafeToCache() {
22 return [
23 'No overrides' => [ true, [] ],
24 'In-key options are ok' => [ true, [
25 'thumbsize' => 1e100,
26 'wrapclass' => false,
27 ] ],
28 'Non-in-key options are not ok' => [ false, [
29 'removeComments' => false,
30 ] ],
31 'Canonical override, not default (1)' => [ true, [
32 'tidy' => true,
33 ] ],
34 'Canonical override, not default (2)' => [ false, [
35 'tidy' => false,
36 ] ],
37 ];
38 }
39
40 /**
41 * @dataProvider provideOptionsHashPre30
42 * @param array $usedOptions Used options
43 * @param string $expect Expected value
44 * @param array $options Options to set
45 * @param array $globals Globals to set
46 */
47 public function testOptionsHashPre30( $usedOptions, $expect, $options, $globals = [] ) {
48 global $wgHooks;
49
50 $globals += [
51 'wgRenderHashAppend' => '',
52 'wgHooks' => [],
53 ];
54 $globals['wgHooks'] += [
55 'PageRenderingHash' => [],
56 ] + $wgHooks;
57 $this->setMwGlobals( $globals );
58
59 $popt = new ParserOptions();
60 foreach ( $options as $setter => $value ) {
61 $popt->$setter( $value );
62 }
63 $this->assertSame( $expect, $popt->optionsHashPre30( $usedOptions ) );
64 }
65
66 public static function provideOptionsHashPre30() {
67 $used = [ 'wrapclass', 'printable' ];
68
69 return [
70 'Canonical options, nothing used' => [ [], '*!*!*!*!*!*', [] ],
71 'Canonical options, used some options' => [ $used, '*!*!*!*!*!*', [] ],
72 'Used some options, non-default values' => [
73 $used,
74 '*!*!*!*!*!*!printable=1!wrapclass=foobar',
75 [
76 'setWrapOutputClass' => 'foobar',
77 'setIsPrintable' => true,
78 ]
79 ],
80 'Canonical options, nothing used, but with hooks and $wgRenderHashAppend' => [
81 [],
82 '*!*!*!*!*!wgRenderHashAppend!*!onPageRenderingHash',
83 [],
84 [
85 'wgRenderHashAppend' => '!wgRenderHashAppend',
86 'wgHooks' => [ 'PageRenderingHash' => [ [ __CLASS__ . '::onPageRenderingHash' ] ] ],
87 ]
88 ],
89
90 // Test weird historical behavior is still weird
91 'Canonical options, editsection=true used' => [ [ 'editsection' ], '*!*!*!*!*', [
92 'setEditSection' => true,
93 ] ],
94 'Canonical options, editsection=false used' => [ [ 'editsection' ], '*!*!*!*!*!edit=0', [
95 'setEditSection' => false,
96 ] ],
97 ];
98 }
99
100 /**
101 * @dataProvider provideOptionsHash
102 * @param array $usedOptions Used options
103 * @param string $expect Expected value
104 * @param array $options Options to set
105 * @param array $globals Globals to set
106 */
107 public function testOptionsHash( $usedOptions, $expect, $options, $globals = [] ) {
108 global $wgHooks;
109
110 $globals += [
111 'wgRenderHashAppend' => '',
112 'wgHooks' => [],
113 ];
114 $globals['wgHooks'] += [
115 'PageRenderingHash' => [],
116 ] + $wgHooks;
117 $this->setMwGlobals( $globals );
118
119 $popt = ParserOptions::newCanonical();
120 foreach ( $options as $name => $value ) {
121 $popt->setOption( $name, $value );
122 }
123 $this->assertSame( $expect, $popt->optionsHash( $usedOptions ) );
124 }
125
126 public static function provideOptionsHash() {
127 $used = [ 'wrapclass', 'printable' ];
128
129 $classWrapper = TestingAccessWrapper::newFromClass( ParserOptions::class );
130 $classWrapper->getDefaults();
131 $allUsableOptions = array_diff(
132 array_keys( $classWrapper->inCacheKey ),
133 array_keys( $classWrapper->lazyOptions )
134 );
135
136 return [
137 'Canonical options, nothing used' => [ [], 'canonical', [] ],
138 'Canonical options, used some options' => [ $used, 'canonical', [] ],
139 'Used some options, non-default values' => [
140 $used,
141 'printable=1!wrapclass=foobar',
142 [
143 'wrapclass' => 'foobar',
144 'printable' => true,
145 ]
146 ],
147 'Canonical options, used all non-lazy options' => [ $allUsableOptions, 'canonical', [] ],
148 'Canonical options, nothing used, but with hooks and $wgRenderHashAppend' => [
149 [],
150 'canonical!wgRenderHashAppend!onPageRenderingHash',
151 [],
152 [
153 'wgRenderHashAppend' => '!wgRenderHashAppend',
154 'wgHooks' => [ 'PageRenderingHash' => [ [ __CLASS__ . '::onPageRenderingHash' ] ] ],
155 ]
156 ],
157 ];
158 }
159
160 public static function onPageRenderingHash( &$confstr ) {
161 $confstr .= '!onPageRenderingHash';
162 }
163
164 // Test weird historical behavior is still weird
165 public function testOptionsHashEditSection() {
166 global $wgHooks;
167
168 $this->setMwGlobals( [
169 'wgRenderHashAppend' => '',
170 'wgHooks' => [ 'PageRenderingHash' => [] ] + $wgHooks,
171 ] );
172
173 $popt = ParserOptions::newCanonical();
174 $popt->registerWatcher( function ( $name ) {
175 $this->assertNotEquals( 'editsection', $name );
176 } );
177
178 $this->assertTrue( $popt->getEditSection() );
179 $this->assertSame( 'canonical', $popt->optionsHash( [] ) );
180 $this->assertSame( 'canonical', $popt->optionsHash( [ 'editsection' ] ) );
181
182 $popt->setEditSection( false );
183 $this->assertFalse( $popt->getEditSection() );
184 $this->assertSame( 'canonical', $popt->optionsHash( [] ) );
185 $this->assertSame( 'editsection=0', $popt->optionsHash( [ 'editsection' ] ) );
186 }
187
188 /**
189 * @expectedException InvalidArgumentException
190 * @expectedExceptionMessage Unknown parser option bogus
191 */
192 public function testGetInvalidOption() {
193 $popt = ParserOptions::newCanonical();
194 $popt->getOption( 'bogus' );
195 }
196
197 /**
198 * @expectedException InvalidArgumentException
199 * @expectedExceptionMessage Unknown parser option bogus
200 */
201 public function testSetInvalidOption() {
202 $popt = ParserOptions::newCanonical();
203 $popt->setOption( 'bogus', true );
204 }
205
206 public function testMatches() {
207 $classWrapper = TestingAccessWrapper::newFromClass( ParserOptions::class );
208 $oldDefaults = $classWrapper->defaults;
209 $oldLazy = $classWrapper->lazyOptions;
210 $reset = new ScopedCallback( function () use ( $classWrapper, $oldDefaults, $oldLazy ) {
211 $classWrapper->defaults = $oldDefaults;
212 $classWrapper->lazyOptions = $oldLazy;
213 } );
214
215 $popt1 = ParserOptions::newCanonical();
216 $popt2 = ParserOptions::newCanonical();
217 $this->assertTrue( $popt1->matches( $popt2 ) );
218
219 $popt1->enableLimitReport( true );
220 $popt2->enableLimitReport( false );
221 $this->assertTrue( $popt1->matches( $popt2 ) );
222
223 $popt2->setTidy( !$popt2->getTidy() );
224 $this->assertFalse( $popt1->matches( $popt2 ) );
225
226 $ctr = 0;
227 $classWrapper->defaults += [ __METHOD__ => null ];
228 $classWrapper->lazyOptions += [ __METHOD__ => function () use ( &$ctr ) {
229 return ++$ctr;
230 } ];
231 $popt1 = ParserOptions::newCanonical();
232 $popt2 = ParserOptions::newCanonical();
233 $this->assertFalse( $popt1->matches( $popt2 ) );
234
235 ScopedCallback::consume( $reset );
236 }
237
238 }