Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
// This file is part of Moodle - http://moodle.org/
3
//
4
// Moodle is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8
//
9
// Moodle is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13
//
14
// You should have received a copy of the GNU General Public License
15
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
16
 
17
namespace core;
18
 
19
use core_plugin_manager;
20
use testable_core_plugin_manager;
21
use testable_plugininfo_base;
22
 
23
/**
24
 * Unit tests for plugin manager class.
25
 *
26
 * @package   core
27
 * @category  test
28
 * @copyright 2013 Petr Skoda {@link http://skodak.org}
29
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
30
 * @covers \core_plugin_manager
31
 */
32
final class plugin_manager_test extends \advanced_testcase {
33
    public static function setUpBeforeClass(): void {
34
        global $CFG;
35
        require_once($CFG->dirroot . '/lib/tests/fixtures/testable_plugin_manager.php');
36
        require_once($CFG->dirroot . '/lib/tests/fixtures/testable_plugininfo_base.php');
37
    }
38
 
39
    public function tearDown(): void {
40
        // The caches of the testable singleton must be reset explicitly. It is
41
        // safer to kill the whole testable singleton at the end of every test.
42
        testable_core_plugin_manager::reset_caches();
43
    }
44
 
45
    public function test_instance(): void {
46
        $pluginman1 = core_plugin_manager::instance();
47
        $this->assertInstanceOf('core_plugin_manager', $pluginman1);
48
        $pluginman2 = core_plugin_manager::instance();
49
        $this->assertSame($pluginman1, $pluginman2);
50
        $pluginman3 = testable_core_plugin_manager::instance();
51
        $this->assertInstanceOf('core_plugin_manager', $pluginman3);
52
        $this->assertInstanceOf('testable_core_plugin_manager', $pluginman3);
53
        $pluginman4 = testable_core_plugin_manager::instance();
54
        $this->assertSame($pluginman3, $pluginman4);
55
        $this->assertNotSame($pluginman1, $pluginman3);
56
    }
57
 
58
    public function test_reset_caches(): void {
59
        // Make sure there are no warnings or errors.
60
        core_plugin_manager::reset_caches();
61
        testable_core_plugin_manager::reset_caches();
62
    }
63
 
64
    /**
65
     * Make sure that the tearDown() really kills the singleton after this test.
66
     */
67
    public function test_teardown_works_precheck(): void {
68
        $pluginman = testable_core_plugin_manager::instance();
69
        $pluginfo = testable_plugininfo_base::fake_plugin_instance(
70
            'fake',
71
            '/dev/null',
72
            'one',
73
            '/dev/null/fake',
74
            'testable_plugininfo_base',
75
            $pluginman
76
        );
77
        $pluginman->inject_testable_plugininfo('fake', 'one', $pluginfo);
78
 
79
        $this->assertInstanceOf('\core\plugininfo\base', $pluginman->get_plugin_info('fake_one'));
80
        $this->assertNull($pluginman->get_plugin_info('fake_two'));
81
    }
82
 
83
    public function test_teardown_works_postcheck(): void {
84
        $pluginman = testable_core_plugin_manager::instance();
85
        $this->assertNull($pluginman->get_plugin_info('fake_one'));
86
        $this->assertNull($pluginman->get_plugin_info('fake_two'));
87
    }
88
 
89
    public function test_get_plugin_types(): void {
90
        // Make sure there are no warnings or errors.
91
        $types = core_plugin_manager::instance()->get_plugin_types();
92
        $this->assertIsArray($types);
93
        foreach ($types as $type => $fulldir) {
94
            $this->assertFileExists($fulldir);
95
        }
96
    }
97
 
98
    public function test_get_installed_plugins(): void {
99
        $types = core_plugin_manager::instance()->get_plugin_types();
100
        foreach ($types as $type => $fulldir) {
101
            $installed = core_plugin_manager::instance()->get_installed_plugins($type);
102
            foreach ($installed as $plugin => $version) {
103
                $this->assertMatchesRegularExpression('/^[a-z]+[a-z0-9_]*$/', $plugin);
104
                $this->assertTrue(
105
                    is_numeric($version),
106
                    'All plugins should have a version, plugin ' . $type . '_' . $plugin . ' does not have version info.'
107
                );
108
            }
109
        }
110
    }
111
 
112
    public function test_get_enabled_plugins(): void {
113
        $types = core_plugin_manager::instance()->get_plugin_types();
114
        foreach ($types as $type => $fulldir) {
115
            $enabled = core_plugin_manager::instance()->get_enabled_plugins($type);
116
            if (is_array($enabled)) {
117
                foreach ($enabled as $key => $val) {
118
                    $this->assertMatchesRegularExpression('/^[a-z]+[a-z0-9_]*$/', $key);
119
                    $this->assertSame($key, $val);
120
                }
121
            } else {
122
                $this->assertNull($enabled);
123
            }
124
        }
125
    }
126
 
127
    public function test_get_present_plugins(): void {
128
        $types = core_plugin_manager::instance()->get_plugin_types();
129
        foreach ($types as $type => $fulldir) {
130
            $present = core_plugin_manager::instance()->get_present_plugins($type);
131
            if (is_array($present)) {
132
                foreach ($present as $plugin => $version) {
133
                    $this->assertMatchesRegularExpression(
134
                        '/^[a-z]+[a-z0-9_]*$/',
135
                        $plugin,
136
                        'All plugins are supposed to have version.php file.'
137
                    );
138
                    $this->assertIsObject($version);
139
                    $this->assertTrue(
140
                        is_numeric($version->version),
141
                        'All plugins should have a version, plugin ' . $type . '_' . $plugin . ' does not have version info.'
142
                    );
143
                }
144
            } else {
145
                // No plugins of this type exist.
146
                $this->assertNull($present);
147
            }
148
        }
149
    }
150
 
151
    public function test_get_plugins(): void {
152
        $plugininfos1 = core_plugin_manager::instance()->get_plugins();
153
        foreach ($plugininfos1 as $type => $infos) {
154
            foreach ($infos as $name => $info) {
155
                $this->assertInstanceOf('\core\plugininfo\base', $info);
156
            }
157
        }
158
 
159
        // The testable variant of the manager holds its own tree of the
160
        // plugininfo objects.
161
        $plugininfos2 = testable_core_plugin_manager::instance()->get_plugins();
162
        $this->assertNotSame($plugininfos1['mod']['forum'], $plugininfos2['mod']['forum']);
163
 
164
        // Singletons of each manager class share the same tree.
165
        $plugininfos3 = core_plugin_manager::instance()->get_plugins();
166
        $this->assertSame($plugininfos1['mod']['forum'], $plugininfos3['mod']['forum']);
167
        $plugininfos4 = testable_core_plugin_manager::instance()->get_plugins();
168
        $this->assertSame($plugininfos2['mod']['forum'], $plugininfos4['mod']['forum']);
169
    }
170
 
171
    public function test_plugininfo_back_reference_to_the_plugin_manager(): void {
172
        $plugman1 = core_plugin_manager::instance();
173
        $plugman2 = testable_core_plugin_manager::instance();
174
 
175
        foreach ($plugman1->get_plugins() as $type => $infos) {
176
            foreach ($infos as $info) {
177
                $this->assertSame($info->pluginman, $plugman1);
178
            }
179
        }
180
 
181
        foreach ($plugman2->get_plugins() as $type => $infos) {
182
            foreach ($infos as $info) {
183
                $this->assertSame($info->pluginman, $plugman2);
184
            }
185
        }
186
    }
187
 
188
    public function test_get_plugins_of_type(): void {
189
        $plugininfos = core_plugin_manager::instance()->get_plugins();
190
        foreach ($plugininfos as $type => $infos) {
191
            $this->assertSame($infos, core_plugin_manager::instance()->get_plugins_of_type($type));
192
        }
193
    }
194
 
195
    public function test_get_subplugins_of_plugin(): void {
196
        global $CFG;
197
 
198
        // Any standard plugin with subplugins is suitable.
199
        $this->assertFileExists("$CFG->dirroot/lib/editor/tiny", 'TinyMCE is not present.');
200
 
201
        $subplugins = core_plugin_manager::instance()->get_subplugins_of_plugin('editor_tiny');
202
        foreach ($subplugins as $component => $info) {
203
            $this->assertInstanceOf('\core\plugininfo\base', $info);
204
        }
205
    }
206
 
207
    public function test_get_subplugins(): void {
208
        // Tested already indirectly from test_get_subplugins_of_plugin().
209
        $subplugins = core_plugin_manager::instance()->get_subplugins();
210
        $this->assertIsArray($subplugins);
211
    }
212
 
213
    public function test_get_parent_of_subplugin(): void {
214
        global $CFG;
215
 
216
        // Any standard plugin with subplugins is suitable.
217
        $this->assertFileExists("$CFG->dirroot/lib/editor/tiny", 'TinyMCE is not present.');
218
 
219
        $parent = core_plugin_manager::instance()->get_parent_of_subplugin('tiny');
220
        $this->assertSame('editor_tiny', $parent);
221
    }
222
 
223
    public function test_plugin_name(): void {
224
        global $CFG;
225
 
226
        // Any standard plugin is suitable.
227
        $this->assertFileExists("$CFG->dirroot/lib/editor/tiny", 'TinyMCE is not present.');
228
 
229
        $name = core_plugin_manager::instance()->plugin_name('editor_tiny');
230
        $this->assertSame(get_string('pluginname', 'editor_tiny'), $name);
231
    }
232
 
233
    public function test_plugintype_name(): void {
234
        $name = core_plugin_manager::instance()->plugintype_name('editor');
235
        $this->assertSame(get_string('type_editor', 'core_plugin'), $name);
236
    }
237
 
238
    public function test_plugintype_name_plural(): void {
239
        $name = core_plugin_manager::instance()->plugintype_name_plural('editor');
240
        $this->assertSame(get_string('type_editor_plural', 'core_plugin'), $name);
241
    }
242
 
243
    public function test_get_plugin_info(): void {
244
        global $CFG;
245
 
246
        // Any standard plugin is suitable.
247
        $this->assertFileExists("$CFG->dirroot/lib/editor/tiny", 'TinyMCE is not present.');
248
 
249
        $info = core_plugin_manager::instance()->get_plugin_info('editor_tiny');
250
        $this->assertInstanceOf('\core\plugininfo\editor', $info);
251
    }
252
 
253
    public function test_can_uninstall_plugin(): void {
254
        global $CFG;
255
 
256
        // Any standard plugin that is required by some other standard plugin is ok.
257
        $this->assertFileExists("$CFG->dirroot/report/competency", 'competency report is not present');
258
        $this->assertFileExists("$CFG->dirroot/$CFG->admin/tool/lp", 'tool lp is not present');
259
 
260
        $this->assertFalse(core_plugin_manager::instance()->can_uninstall_plugin('tool_lp'));
261
        $this->assertTrue(core_plugin_manager::instance()->can_uninstall_plugin('report_competency'));
262
    }
263
 
264
    public function test_plugin_states(): void {
265
        global $CFG;
266
        $this->resetAfterTest();
267
 
268
        // Any standard plugin that is ok.
269
        $this->assertFileExists("$CFG->dirroot/mod/assign", 'assign module is not present');
270
        $this->assertFileExists("$CFG->dirroot/mod/forum", 'forum module is not present');
271
        $this->assertFileExists("$CFG->dirroot/$CFG->admin/tool/phpunit", 'phpunit tool is not present');
272
        $this->assertFileDoesNotExist("$CFG->dirroot/mod/xxxxxxx");
273
        $this->assertFileDoesNotExist("$CFG->dirroot/enrol/autorize");
274
 
275
        // Ready for upgrade.
276
        $assignversion = get_config('mod_assign', 'version');
277
        set_config('version', $assignversion - 1, 'mod_assign');
278
        // Downgrade problem.
279
        $forumversion = get_config('mod_forum', 'version');
280
        set_config('version', $forumversion + 1, 'mod_forum');
281
        // Not installed yet.
282
        unset_config('version', 'tool_phpunit');
283
        // Missing already installed.
284
        set_config('version', 2013091300, 'mod_xxxxxxx');
285
        // Deleted present.
286
        set_config('version', 2013091300, 'enrol_authorize');
287
 
288
        core_plugin_manager::reset_caches();
289
 
290
        $plugininfos = core_plugin_manager::instance()->get_plugins();
291
        foreach ($plugininfos as $type => $infos) {
292
            /** @var \core\plugininfo\base $info */
293
            foreach ($infos as $info) {
294
                if ($info->component === 'mod_assign') {
295
                    $this->assertSame(
296
                        core_plugin_manager::PLUGIN_STATUS_UPGRADE,
297
                        $info->get_status(),
298
                        'Invalid ' . $info->component . ' state'
299
                    );
300
                } else if ($info->component === 'mod_forum') {
301
                    $this->assertSame(
302
                        core_plugin_manager::PLUGIN_STATUS_DOWNGRADE,
303
                        $info->get_status(),
304
                        'Invalid ' . $info->component . ' state'
305
                    );
306
                } else if ($info->component === 'tool_phpunit') {
307
                    $this->assertSame(
308
                        core_plugin_manager::PLUGIN_STATUS_NEW,
309
                        $info->get_status(),
310
                        'Invalid ' . $info->component . ' state'
311
                    );
312
                } else if ($info->component === 'mod_xxxxxxx') {
313
                    $this->assertSame(
314
                        core_plugin_manager::PLUGIN_STATUS_MISSING,
315
                        $info->get_status(),
316
                        'Invalid ' . $info->component . ' state'
317
                    );
318
                } else if ($info->component === 'enrol_authorize') {
319
                    $this->assertSame(
320
                        core_plugin_manager::PLUGIN_STATUS_DELETE,
321
                        $info->get_status(),
322
                        'Invalid ' . $info->component . ' state'
323
                    );
324
                } else {
325
                    $this->assertSame(
326
                        core_plugin_manager::PLUGIN_STATUS_UPTODATE,
327
                        $info->get_status(),
328
                        'Invalid ' . $info->component . ' state'
329
                    );
330
                }
331
            }
332
        }
333
    }
334
 
335
    public function test_plugin_available_updates(): void {
336
        $pluginman = testable_core_plugin_manager::instance();
337
 
338
        $foobar = testable_plugininfo_base::fake_plugin_instance(
339
            'foo',
340
            '/dev/null',
341
            'bar',
342
            '/dev/null/fake',
343
            'testable_plugininfo_base',
344
            $pluginman
345
        );
346
        $foobar->versiondb = 2015092900;
347
        $foobar->versiondisk = 2015092900;
348
        $pluginman->inject_testable_plugininfo('foo', 'bar', $foobar);
349
 
350
        $washere = false;
351
        foreach ($pluginman->get_plugins() as $type => $infos) {
352
            foreach ($infos as $name => $plugin) {
353
                $updates = $plugin->available_updates();
354
                if ($plugin->component != 'foo_bar') {
355
                    $this->assertNull($updates);
356
                } else {
357
                    $this->assertTrue(is_array($updates));
358
                    $this->assertEquals(3, count($updates));
359
                    foreach ($updates as $update) {
360
                        $washere = true;
361
                        $this->assertInstanceOf('\core\update\info', $update);
362
                        $this->assertEquals($update->component, $plugin->component);
363
                        $this->assertTrue($update->version > $plugin->versiondb);
364
                    }
365
                }
366
            }
367
        }
368
        $this->assertTrue($washere);
369
    }
370
 
371
    public function test_some_plugins_updatable_none(): void {
372
        $pluginman = testable_core_plugin_manager::instance();
373
        $this->assertFalse($pluginman->some_plugins_updatable());
374
    }
375
 
376
    public function test_some_plugins_updatable_some(): void {
377
        $pluginman = testable_core_plugin_manager::instance();
378
 
379
        $foobar = testable_plugininfo_base::fake_plugin_instance(
380
            'foo',
381
            '/dev/null',
382
            'bar',
383
            '/dev/null/fake',
384
            'testable_plugininfo_base',
385
            $pluginman
386
        );
387
        $foobar->versiondb = 2015092900;
388
        $foobar->versiondisk = 2015092900;
389
        $pluginman->inject_testable_plugininfo('foo', 'bar', $foobar);
390
 
391
        $this->assertTrue($pluginman->some_plugins_updatable());
392
    }
393
 
394
    public function test_available_updates(): void {
395
        $pluginman = testable_core_plugin_manager::instance();
396
 
397
        $foobar = testable_plugininfo_base::fake_plugin_instance(
398
            'foo',
399
            '/dev/null',
400
            'bar',
401
            '/dev/null/fake',
402
            'testable_plugininfo_base',
403
            $pluginman
404
        );
405
        $foobar->versiondb = 2015092900;
406
        $foobar->versiondisk = 2015092900;
407
        $pluginman->inject_testable_plugininfo('foo', 'bar', $foobar);
408
 
409
        $updates = $pluginman->available_updates();
410
 
411
        $this->assertTrue(is_array($updates));
412
        $this->assertEquals(1, count($updates));
413
        $update = $updates['foo_bar'];
414
        $this->assertInstanceOf('\core\update\remote_info', $update);
415
        $this->assertEquals('foo_bar', $update->component);
416
        $this->assertEquals(2015100400, $update->version->version);
417
    }
418
 
419
    public function test_get_remote_plugin_info(): void {
420
        $pluginman = testable_core_plugin_manager::instance();
421
 
422
        $this->assertFalse($pluginman->get_remote_plugin_info('not_exists', ANY_VERSION, false));
423
 
424
        $info = $pluginman->get_remote_plugin_info('foo_bar', 2015093000, true);
425
        $this->assertEquals(2015093000, $info->version->version);
426
 
427
        $info = $pluginman->get_remote_plugin_info('foo_bar', 2015093000, false);
428
        $this->assertEquals(2015100400, $info->version->version);
429
    }
430
 
431
    /**
432
     * The combination of ANY_VERSION + $exactmatch is illegal.
433
     */
434
    public function test_get_remote_plugin_info_exception(): void {
435
        $pluginman = testable_core_plugin_manager::instance();
436
        $this->expectException(\moodle_exception::class);
437
        $pluginman->get_remote_plugin_info('any_thing', ANY_VERSION, true);
438
    }
439
 
440
    public function test_is_remote_plugin_available(): void {
441
        $pluginman = testable_core_plugin_manager::instance();
442
 
443
        $this->assertFalse($pluginman->is_remote_plugin_available('not_exists', ANY_VERSION, false));
444
        $this->assertTrue($pluginman->is_remote_plugin_available('foo_bar', 2013131313, false));
445
        $this->assertFalse($pluginman->is_remote_plugin_available('foo_bar', 2013131313, true));
446
    }
447
 
448
    public function test_resolve_requirements(): void {
449
        $pluginman = testable_core_plugin_manager::instance();
450
 
451
        // Prepare a fake pluginfo instance.
452
        $pluginfo = testable_plugininfo_base::fake_plugin_instance(
453
            'fake',
454
            '/dev/null',
455
            'one',
456
            '/dev/null/fake',
457
            'testable_plugininfo_base',
458
            $pluginman
459
        );
460
        $pluginfo->versiondisk = 2015060600;
461
 
462
        // Test no $plugin->requires is specified in version.php.
463
        $pluginfo->versionrequires = null;
464
        $this->assertTrue($pluginfo->is_core_dependency_satisfied(2015100100));
465
        $reqs = $pluginman->resolve_requirements($pluginfo, 2015100100, 29);
466
        $this->assertEquals(2015100100, $reqs['core']->hasver);
467
        $this->assertEquals(ANY_VERSION, $reqs['core']->reqver);
468
        $this->assertEquals($pluginman::REQUIREMENT_STATUS_OK, $reqs['core']->status);
469
 
470
        // Test plugin requires higher core version.
471
        $pluginfo->versionrequires = 2015110900;
472
        $this->assertFalse($pluginfo->is_core_dependency_satisfied(2015100100));
473
        $reqs = $pluginman->resolve_requirements($pluginfo, 2015100100, 29);
474
        $this->assertEquals(2015100100, $reqs['core']->hasver);
475
        $this->assertEquals(2015110900, $reqs['core']->reqver);
476
        $this->assertEquals($pluginman::REQUIREMENT_STATUS_OUTDATED, $reqs['core']->status);
477
 
478
        // Test plugin requires current core version.
479
        $pluginfo->versionrequires = 2015110900;
480
        $this->assertTrue($pluginfo->is_core_dependency_satisfied(2015110900));
481
        $reqs = $pluginman->resolve_requirements($pluginfo, 2015110900, 30);
482
        $this->assertEquals(2015110900, $reqs['core']->hasver);
483
        $this->assertEquals(2015110900, $reqs['core']->reqver);
484
        $this->assertEquals($pluginman::REQUIREMENT_STATUS_OK, $reqs['core']->status);
485
 
486
        // Test plugin requires lower core version.
487
        $pluginfo->versionrequires = 2014122400;
488
        $this->assertTrue($pluginfo->is_core_dependency_satisfied(2015100100));
489
        $reqs = $pluginman->resolve_requirements($pluginfo, 2015100100, 29);
490
        $this->assertEquals(2015100100, $reqs['core']->hasver);
491
        $this->assertEquals(2014122400, $reqs['core']->reqver);
492
        $this->assertEquals($pluginman::REQUIREMENT_STATUS_OK, $reqs['core']->status);
493
 
494
        // Test plugin dependencies and their availability.
495
        // See {@link \core\update\testable_api} class.
496
 
497
        $pluginfo->dependencies = ['foo_bar' => ANY_VERSION, 'not_exists' => ANY_VERSION];
498
        $reqs = $pluginman->resolve_requirements($pluginfo, 2015110900, 30);
499
        $this->assertNull($reqs['foo_bar']->hasver);
500
        $this->assertEquals(ANY_VERSION, $reqs['foo_bar']->reqver);
501
        $this->assertEquals($pluginman::REQUIREMENT_STATUS_MISSING, $reqs['foo_bar']->status);
502
        $this->assertEquals($pluginman::REQUIREMENT_AVAILABLE, $reqs['foo_bar']->availability);
503
        $this->assertEquals($pluginman::REQUIREMENT_UNAVAILABLE, $reqs['not_exists']->availability);
504
 
505
        $pluginfo->dependencies = ['foo_bar' => 2013122400];
506
        $reqs = $pluginman->resolve_requirements($pluginfo, 2015110900, 30);
507
        $this->assertEquals($pluginman::REQUIREMENT_AVAILABLE, $reqs['foo_bar']->availability);
508
 
509
        $pluginfo->dependencies = ['foo_bar' => 2015093000];
510
        $reqs = $pluginman->resolve_requirements($pluginfo, 2015110900, 30);
511
        $this->assertEquals($pluginman::REQUIREMENT_AVAILABLE, $reqs['foo_bar']->availability);
512
 
513
        $pluginfo->dependencies = ['foo_bar' => 2015100500];
514
        $reqs = $pluginman->resolve_requirements($pluginfo, 2015110900, 30);
515
        $this->assertEquals($pluginman::REQUIREMENT_AVAILABLE, $reqs['foo_bar']->availability);
516
 
517
        $pluginfo->dependencies = ['foo_bar' => 2025010100];
518
        $reqs = $pluginman->resolve_requirements($pluginfo, 2015110900, 30);
519
        $this->assertEquals($pluginman::REQUIREMENT_UNAVAILABLE, $reqs['foo_bar']->availability);
520
 
521
        // Plugin missing from disk - no version.php available.
522
        $pluginfo = testable_plugininfo_base::fake_plugin_instance(
523
            'fake',
524
            '/dev/null',
525
            'missing',
526
            '/dev/null/fake',
527
            'testable_plugininfo_base',
528
            $pluginman
529
        );
530
        $pluginfo->versiondisk = null;
531
        $this->assertEmpty($pluginman->resolve_requirements($pluginfo, 2015110900, 30));
532
 
533
        // Test plugin fails for incompatible version.
534
        $pluginfo = testable_plugininfo_base::fake_plugin_instance(
535
            'fake',
536
            '/dev/null',
537
            'two',
538
            '/dev/null/fake',
539
            'testable_plugininfo_base',
540
            $pluginman
541
        );
542
        $pluginfo->versiondisk = 2015060600;
543
        $pluginfo->pluginincompatible = 30;
544
        $reqs = $pluginman->resolve_requirements($pluginfo, 2015110900, 30);
545
        $this->assertEquals($pluginman::REQUIREMENT_STATUS_NEWER, $reqs['core']->status);
546
 
547
        // Test no failure for no incompatible version.
548
        $pluginfo->pluginincompatible = 30;
549
        $reqs = $pluginman->resolve_requirements($pluginfo, 2015110900, 29);
550
        $this->assertEquals($pluginman::REQUIREMENT_STATUS_OK, $reqs['core']->status);
551
    }
552
 
553
    public function test_missing_dependencies(): void {
554
        $pluginman = testable_core_plugin_manager::instance();
555
 
556
        $one = testable_plugininfo_base::fake_plugin_instance(
557
            'fake',
558
            '/dev/null',
559
            'one',
560
            '/dev/null/fake',
561
            'testable_plugininfo_base',
562
            $pluginman
563
        );
564
        $one->versiondisk = 2015070800;
565
 
566
        $two = testable_plugininfo_base::fake_plugin_instance(
567
            'fake',
568
            '/dev/null',
569
            'two',
570
            '/dev/null/fake',
571
            'testable_plugininfo_base',
572
            $pluginman
573
        );
574
        $two->versiondisk = 2015070900;
575
 
576
        $pluginman->inject_testable_plugininfo('fake', 'one', $one);
577
        $pluginman->inject_testable_plugininfo('fake', 'two', $two);
578
 
579
        $this->assertEmpty($pluginman->missing_dependencies());
580
 
581
        $one->dependencies = ['foo_bar' => ANY_VERSION];
582
        $misdeps = $pluginman->missing_dependencies();
583
        $this->assertInstanceOf('\core\update\remote_info', $misdeps['foo_bar']);
584
        $this->assertEquals(2015100400, $misdeps['foo_bar']->version->version);
585
 
586
        $two->dependencies = ['foo_bar' => 2015100500];
587
        $misdeps = $pluginman->missing_dependencies();
588
        $this->assertInstanceOf('\core\update\remote_info', $misdeps['foo_bar']);
589
        $this->assertEquals(2015100500, $misdeps['foo_bar']->version->version);
590
    }
591
 
592
    /**
593
     * Tests for check_explicitly_supported function to ensure that versions are correctly reported.
594
     *
595
     * @dataProvider check_explicitly_supported_provider
596
     * @param array|null $supported Supported versions to inject
597
     * @param string|int|null $incompatible Incompatible version to inject.
598
     * @param int $version Version to test
599
     * @param int $expected
600
     * @return void
601
     */
602
    public function test_explicitly_supported($supported, $incompatible, $version, $expected): void {
603
        $pluginman = testable_core_plugin_manager::instance();
604
 
605
        // Prepare a fake pluginfo instance.
606
        $plugininfo = new testable_plugininfo_base();
607
        $plugininfo->type = 'fake';
608
        $plugininfo->typerootdir = '/dev/null';
609
        $plugininfo->name = 'example';
610
        $plugininfo->rootdir = '/dev/null/fake';
611
        $plugininfo->pluginman = $pluginman;
612
        $plugininfo->versiondisk = 2015060600;
613
        $plugininfo->supported = $supported;
614
        $plugininfo->incompatible = $incompatible;
615
 
616
        $pluginman->add_fake_plugin_info($plugininfo);
617
 
618
        $plugininfo->load_disk_version();
619
 
620
        $this->assertEquals($expected, $pluginman->check_explicitly_supported($plugininfo, $version));
621
    }
622
 
623
    /**
624
     * Data provider for check_explicitly_supported with a range of correctly defined version support values.
625
     *
626
     * @return array
627
     */
628
    public static function check_explicitly_supported_provider(): array {
629
        return [
630
            'Range, branch in support, lowest' => [
631
                'supported' => [29, 31],
632
                'incompatible' => null,
633
                'version' => 29,
634
                'expected' => core_plugin_manager::VERSION_SUPPORTED,
635
            ],
636
            'Range, branch in support, mid' => [
637
                'supported' => [29, 31],
638
                'incompatible' => null,
639
                'version' => 30,
640
                'expected' => core_plugin_manager::VERSION_SUPPORTED,
641
            ],
642
            'Range, branch in support, highest' => [
643
                'supported' => [29, 31],
644
                'incompatible' => null,
645
                'version' => 31,
646
                'expected' => core_plugin_manager::VERSION_SUPPORTED,
647
            ],
648
 
649
            'Range, branch not in support, high' => [
650
                'supported' => [29, 31],
651
                'incompatible' => null,
652
                'version' => 32,
653
                'expected' => core_plugin_manager::VERSION_NOT_SUPPORTED,
654
            ],
655
            'Range, branch not in support, low' => [
656
                'supported' => [29, 31],
657
                'incompatible' => null,
658
                'version' => 28,
659
                'expected' => core_plugin_manager::VERSION_NOT_SUPPORTED,
660
            ],
661
            'Range, incompatible, high.' => [
662
                'supported' => [29, 31],
663
                'incompatible' => 32,
664
                'version' => 33,
665
                'expected' => core_plugin_manager::VERSION_NOT_SUPPORTED,
666
            ],
667
            'Range, incompatible, low.' => [
668
                'supported' => [29, 31],
669
                'incompatible' => 32,
670
                'version' => 31,
671
                'expected' => core_plugin_manager::VERSION_SUPPORTED,
672
            ],
673
            'Range, incompatible, equal.' => [
674
                'supported' => [29, 31],
675
                'incompatible' => 32,
676
                'version' => 32,
677
                'expected' => core_plugin_manager::VERSION_NOT_SUPPORTED,
678
            ],
679
            'No supports' => [
680
                'supported' => null,
681
                'incompatible' => null,
682
                'version' => 32,
683
                'expected' => core_plugin_manager::VERSION_NO_SUPPORTS,
684
            ],
685
            'No supports, but incompatible, older' => [
686
                'supported' => null,
687
                'incompatible' => 30,
688
                'version' => 32,
689
                'expected' => core_plugin_manager::VERSION_NOT_SUPPORTED,
690
            ],
691
            'No supports, but incompatible, equal' => [
692
                'supported' => null,
693
                'incompatible' => 32,
694
                'version' => 32,
695
                'expected' => core_plugin_manager::VERSION_NOT_SUPPORTED,
696
            ],
697
            'No supports, but incompatible, newer' => [
698
                'supported' => null,
699
                'incompatible' => 34,
700
                'version' => 32,
701
                'expected' => core_plugin_manager::VERSION_NO_SUPPORTS,
702
            ],
703
        ];
704
    }
705
 
706
    /**
707
     * @dataProvider is_deleted_standard_plugin_provider
708
     */
709
    public function test_is_deleted_standard_plugin(
710
        mixed $type,
711
        mixed $name,
712
        bool $expected,
713
    ): void {
714
        $this->assertEquals(
715
            $expected,
716
            \core_plugin_manager::is_deleted_standard_plugin($type, $name),
717
        );
718
    }
719
 
720
    public static function is_deleted_standard_plugin_provider(): array {
721
        return [
722
            // Valid deleted plugin.
723
            ['h5plib', 'v124', true],
724
            // Valid type, but not a valid plugin.
725
            ['h5plib', 'v99', false],
726
            // Invalid type.
727
            ['marmelade', 'paddington', false],
728
        ];
729
    }
730
 
731
    public function test_get_deleted_plugins(): void {
732
        $plugins = core_plugin_manager::get_deleted_plugins();
733
        $this->assertIsArray($plugins);
734
 
735
        // Pick a couple we know should be there.
736
        $this->assertContains('h5plib_v124', $plugins);
737
        $this->assertNotContains('h5plib_v99', $plugins);
738
 
739
        $this->assertContains('editor_tinymce', $plugins);
740
        $this->assertNotContains('editor_tiny', $plugins);
741
    }
742
 
743
    public function test_standard_plugins_list_no_type(): void {
744
        $plugins = core_plugin_manager::standard_plugins_list('typo');
745
        $this->assertFalse($plugins);
746
    }
747
 
748
    /**
749
     * @dataProvider standard_plugins_list_provider
750
     */
751
    public function test_standard_plugins_list(
752
        string $type,
753
        array $expectedplugins,
754
    ): void {
755
        $plugins = core_plugin_manager::standard_plugins_list($type);
756
        $this->assertIsArray($plugins);
757
        foreach ($expectedplugins as $expected) {
758
            $this->assertContains($expected, $plugins);
759
        }
760
    }
761
 
762
    public static function standard_plugins_list_provider(): array {
763
        return [
764
            [
765
                'mod',
766
                ['forum', 'assign', 'book', 'choice'],
767
            ],
768
            [
769
                'block',
770
                ['starredcourses', 'badges'],
771
            ],
772
            [
773
                'tiny',
774
                ['autosave', 'h5p'],
775
            ],
776
        ];
777
    }
778
 
779
    public function test_get_standard_plugins(): void {
780
        $plugins = core_plugin_manager::get_standard_plugins();
781
        $this->assertIsArray($plugins);
782
 
783
        $this->assertContains('mod_forum', $plugins);
784
        $this->assertContains('block_badges', $plugins);
785
        $this->assertNotContains('marmelade_paddington', $plugins);
786
    }
787
}