Merge "Type hint against LinkTarget in WatchedItemStore"
[lhc/web/wiklou.git] / tests / phpunit / unit / includes / registration / VersionCheckerTest.php
1 <?php
2
3 /**
4 * @covers VersionChecker
5 */
6 class VersionCheckerTest extends MediaWikiUnitTestCase {
7
8 /**
9 * @dataProvider provideMediaWikiCheck
10 */
11 public function testMediaWikiCheck( $coreVersion, $constraint, $expected ) {
12 $checker = new VersionChecker( $coreVersion, '7.0.0', [] );
13 $this->assertEquals( $expected, !(bool)$checker->checkArray( [
14 'FakeExtension' => [
15 'MediaWiki' => $constraint,
16 ],
17 ] ) );
18 }
19
20 public static function provideMediaWikiCheck() {
21 return [
22 // [ $wgVersion, constraint, expected ]
23 [ '1.25alpha', '>= 1.26', false ],
24 [ '1.25.0', '>= 1.26', false ],
25 [ '1.26alpha', '>= 1.26', true ],
26 [ '1.26alpha', '>= 1.26.0', true ],
27 [ '1.26alpha', '>= 1.26.0-stable', false ],
28 [ '1.26.0', '>= 1.26.0-stable', true ],
29 [ '1.26.1', '>= 1.26.0-stable', true ],
30 [ '1.27.1', '>= 1.26.0-stable', true ],
31 [ '1.26alpha', '>= 1.26.1', false ],
32 [ '1.26alpha', '>= 1.26alpha', true ],
33 [ '1.26alpha', '>= 1.25', true ],
34 [ '1.26.0-alpha.14', '>= 1.26.0-alpha.15', false ],
35 [ '1.26.0-alpha.14', '>= 1.26.0-alpha.10', true ],
36 [ '1.26.1', '>= 1.26.2, <=1.26.0', false ],
37 [ '1.26.1', '^1.26.2', false ],
38 // Accept anything for un-parsable version strings
39 [ '1.26mwf14', '== 1.25alpha', true ],
40 [ 'totallyinvalid', '== 1.0', true ],
41 ];
42 }
43
44 /**
45 * @dataProvider providePhpValidCheck
46 */
47 public function testPhpValidCheck( $phpVersion, $constraint, $expected ) {
48 $checker = new VersionChecker( '1.0.0', $phpVersion, [] );
49 $this->assertEquals( $expected, !(bool)$checker->checkArray( [
50 'FakeExtension' => [
51 'platform' => [
52 'php' => $constraint,
53 ],
54 ],
55 ] ) );
56 }
57
58 public static function providePhpValidCheck() {
59 return [
60 // [ phpVersion, constraint, expected ]
61 [ '7.0.23', '>= 7.0.0', true ],
62 [ '7.0.23', '^7.1.0', false ],
63 [ '7.0.23', '7.0.23', true ],
64 ];
65 }
66
67 /**
68 * @expectedException UnexpectedValueException
69 */
70 public function testPhpInvalidConstraint() {
71 $checker = new VersionChecker( '1.0.0', '7.0.0', [] );
72 $checker->checkArray( [
73 'FakeExtension' => [
74 'platform' => [
75 'php' => 'totallyinvalid',
76 ],
77 ],
78 ] );
79 }
80
81 /**
82 * @dataProvider providePhpInvalidVersion
83 * @expectedException UnexpectedValueException
84 */
85 public function testPhpInvalidVersion( $phpVersion ) {
86 $checker = new VersionChecker( '1.0.0', $phpVersion, [] );
87 }
88
89 public static function providePhpInvalidVersion() {
90 return [
91 // [ phpVersion ]
92 [ '7.abc' ],
93 [ '5.a.x' ],
94 ];
95 }
96
97 /**
98 * @dataProvider provideType
99 */
100 public function testType( $given, $expected ) {
101 $checker = new VersionChecker(
102 '1.0.0',
103 '7.0.0',
104 [ 'phpLoadedExtension' ],
105 [
106 'presentAbility' => true,
107 'presentAbilityWithMessage' => true,
108 'missingAbility' => false,
109 'missingAbilityWithMessage' => false,
110 ],
111 [
112 'presentAbilityWithMessage' => 'Present.',
113 'missingAbilityWithMessage' => 'Missing.',
114 ]
115 );
116 $checker->setLoadedExtensionsAndSkins( [
117 'FakeDependency' => [
118 'version' => '1.0.0',
119 ],
120 'NoVersionGiven' => [],
121 ] );
122 $this->assertEquals( $expected, $checker->checkArray( [
123 'FakeExtension' => $given,
124 ] ) );
125 }
126
127 public static function provideType() {
128 return [
129 // valid type
130 [
131 [
132 'extensions' => [
133 'FakeDependency' => '1.0.0',
134 ],
135 ],
136 [],
137 ],
138 [
139 [
140 'MediaWiki' => '1.0.0',
141 ],
142 [],
143 ],
144 [
145 [
146 'extensions' => [
147 'NoVersionGiven' => '*',
148 ],
149 ],
150 [],
151 ],
152 [
153 [
154 'extensions' => [
155 'NoVersionGiven' => '1.0',
156 ],
157 ],
158 [
159 [
160 'incompatible' => 'FakeExtension',
161 'type' => 'incompatible-extensions',
162 'msg' => 'NoVersionGiven does not expose its version, but FakeExtension requires: 1.0.',
163 ],
164 ],
165 ],
166 [
167 [
168 'extensions' => [
169 'Missing' => '*',
170 ],
171 ],
172 [
173 [
174 'missing' => 'Missing',
175 'type' => 'missing-extensions',
176 'msg' => 'FakeExtension requires Missing to be installed.',
177 ],
178 ],
179 ],
180 [
181 [
182 'extensions' => [
183 'FakeDependency' => '2.0.0',
184 ],
185 ],
186 [
187 [
188 'incompatible' => 'FakeExtension',
189 'type' => 'incompatible-extensions',
190 // phpcs:ignore Generic.Files.LineLength.TooLong
191 'msg' => 'FakeExtension is not compatible with the current installed version of FakeDependency (1.0.0), it requires: 2.0.0.',
192 ],
193 ],
194 ],
195 [
196 [
197 'skins' => [
198 'FakeSkin' => '*',
199 ],
200 ],
201 [
202 [
203 'missing' => 'FakeSkin',
204 'type' => 'missing-skins',
205 'msg' => 'FakeExtension requires FakeSkin to be installed.',
206 ],
207 ],
208 ],
209 [
210 [
211 'platform' => [
212 'ext-phpLoadedExtension' => '*',
213 ],
214 ],
215 [],
216 ],
217 [
218 [
219 'platform' => [
220 'ext-phpMissingExtension' => '*',
221 ],
222 ],
223 [
224 [
225 'missing' => 'phpMissingExtension',
226 'type' => 'missing-phpExtension',
227 // phpcs:ignore Generic.Files.LineLength.TooLong
228 'msg' => 'FakeExtension requires phpMissingExtension PHP extension to be installed.',
229 ],
230 ],
231 ],
232 [
233 [
234 'platform' => [
235 'ability-presentAbility' => true,
236 ],
237 ],
238 [],
239 ],
240 [
241 [
242 'platform' => [
243 'ability-presentAbilityWithMessage' => true,
244 ],
245 ],
246 [],
247 ],
248 [
249 [
250 'platform' => [
251 'ability-presentAbility' => false,
252 ],
253 ],
254 [],
255 ],
256 [
257 [
258 'platform' => [
259 'ability-presentAbilityWithMessage' => false,
260 ],
261 ],
262 [],
263 ],
264 [
265 [
266 'platform' => [
267 'ability-missingAbility' => true,
268 ],
269 ],
270 [
271 [
272 'missing' => 'missingAbility',
273 'type' => 'missing-ability',
274 'msg' => 'FakeExtension requires "missingAbility" ability',
275 ],
276 ],
277 ],
278 [
279 [
280 'platform' => [
281 'ability-missingAbilityWithMessage' => true,
282 ],
283 ],
284 [
285 [
286 'missing' => 'missingAbilityWithMessage',
287 'type' => 'missing-ability',
288 // phpcs:ignore Generic.Files.LineLength.TooLong
289 'msg' => 'FakeExtension requires "missingAbilityWithMessage" ability: Missing.',
290 ],
291 ],
292 ],
293 [
294 [
295 'platform' => [
296 'ability-missingAbility' => false,
297 ],
298 ],
299 [],
300 ],
301 [
302 [
303 'platform' => [
304 'ability-missingAbilityWithMessage' => false,
305 ],
306 ],
307 [],
308 ],
309 ];
310 }
311
312 /**
313 * Check, if a non-parsable version constraint does not throw an exception or
314 * returns any error message.
315 */
316 public function testInvalidConstraint() {
317 $checker = new VersionChecker( '1.0.0', '7.0.0', [] );
318 $checker->setLoadedExtensionsAndSkins( [
319 'FakeDependency' => [
320 'version' => 'not really valid',
321 ],
322 ] );
323 $this->assertEquals( [
324 [
325 'type' => 'invalid-version',
326 'msg' => "FakeDependency does not have a valid version string.",
327 ],
328 ], $checker->checkArray( [
329 'FakeExtension' => [
330 'extensions' => [
331 'FakeDependency' => '1.24.3',
332 ],
333 ],
334 ] ) );
335
336 $checker = new VersionChecker( '1.0.0', '7.0.0', [] );
337 $checker->setLoadedExtensionsAndSkins( [
338 'FakeDependency' => [
339 'version' => '1.24.3',
340 ],
341 ] );
342
343 $this->setExpectedException( UnexpectedValueException::class );
344 $checker->checkArray( [
345 'FakeExtension' => [
346 'FakeDependency' => 'not really valid',
347 ],
348 ] );
349 }
350
351 public function provideInvalidDependency() {
352 return [
353 [
354 [
355 'FakeExtension' => [
356 'platform' => [
357 'undefinedPlatformDependency' => '*',
358 ],
359 ],
360 ],
361 'undefinedPlatformDependency',
362 ],
363 [
364 [
365 'FakeExtension' => [
366 'platform' => [
367 'phpLoadedExtension' => '*',
368 ],
369 ],
370 ],
371 'phpLoadedExtension',
372 ],
373 [
374 [
375 'FakeExtension' => [
376 'platform' => [
377 'ability-invalidAbility' => true,
378 ],
379 ],
380 ],
381 'ability-invalidAbility',
382 ],
383 [
384 [
385 'FakeExtension' => [
386 'platform' => [
387 'presentAbility' => true,
388 ],
389 ],
390 ],
391 'presentAbility',
392 ],
393 [
394 [
395 'FakeExtension' => [
396 'undefinedDependencyType' => '*',
397 ],
398 ],
399 'undefinedDependencyType',
400 ],
401 // T197478
402 [
403 [
404 'FakeExtension' => [
405 'skin' => [
406 'FakeSkin' => '*',
407 ],
408 ],
409 ],
410 'skin',
411 ],
412 ];
413 }
414
415 /**
416 * @dataProvider provideInvalidDependency
417 */
418 public function testInvalidDependency( $depencency, $type ) {
419 $checker = new VersionChecker(
420 '1.0.0',
421 '7.0.0',
422 [ 'phpLoadedExtension' ],
423 [
424 'presentAbility' => true,
425 'missingAbility' => false,
426 ]
427 );
428 $this->setExpectedException(
429 UnexpectedValueException::class,
430 "Dependency type $type unknown in FakeExtension"
431 );
432 $checker->checkArray( $depencency );
433 }
434
435 public function testInvalidPhpExtensionConstraint() {
436 $checker = new VersionChecker( '1.0.0', '7.0.0', [ 'phpLoadedExtension' ] );
437 $this->setExpectedException(
438 UnexpectedValueException::class,
439 'Version constraints for PHP extensions are not supported in FakeExtension'
440 );
441 $checker->checkArray( [
442 'FakeExtension' => [
443 'platform' => [
444 'ext-phpLoadedExtension' => '1.0.0',
445 ],
446 ],
447 ] );
448 }
449
450 /**
451 * @dataProvider provideInvalidAbilityType
452 */
453 public function testInvalidAbilityType( $value ) {
454 $checker = new VersionChecker( '1.0.0', '7.0.0', [], [ 'presentAbility' => true ] );
455 $this->setExpectedException(
456 UnexpectedValueException::class,
457 'Only booleans are allowed to to indicate the presence of abilities in FakeExtension'
458 );
459 $checker->checkArray( [
460 'FakeExtension' => [
461 'platform' => [
462 'ability-presentAbility' => $value,
463 ],
464 ],
465 ] );
466 }
467
468 public function provideInvalidAbilityType() {
469 return [
470 [ null ],
471 [ 1 ],
472 [ '1' ],
473 ];
474 }
475
476 }