Proyectos de Subversion Moodle

Rev

Rev 1 | | Comparar con el anterior | 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
 
1441 ariadna 19
use core\plugininfo\base;
20
use core\tests\fake_plugins_test_trait;
1 efrain 21
use core_plugin_manager;
22
use testable_core_plugin_manager;
23
use testable_plugininfo_base;
24
 
25
/**
26
 * Unit tests for plugin manager class.
27
 *
28
 * @package   core
29
 * @category  test
30
 * @copyright 2013 Petr Skoda {@link http://skodak.org}
31
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
32
 * @covers \core_plugin_manager
33
 */
34
final class plugin_manager_test extends \advanced_testcase {
1441 ariadna 35
 
36
    use fake_plugins_test_trait;
37
 
1 efrain 38
    public static function setUpBeforeClass(): void {
39
        global $CFG;
40
        require_once($CFG->dirroot . '/lib/tests/fixtures/testable_plugin_manager.php');
41
        require_once($CFG->dirroot . '/lib/tests/fixtures/testable_plugininfo_base.php');
1441 ariadna 42
        parent::setUpBeforeClass();
1 efrain 43
    }
44
 
45
    public function tearDown(): void {
46
        // The caches of the testable singleton must be reset explicitly. It is
47
        // safer to kill the whole testable singleton at the end of every test.
48
        testable_core_plugin_manager::reset_caches();
1441 ariadna 49
        parent::tearDown();
1 efrain 50
    }
51
 
52
    public function test_instance(): void {
53
        $pluginman1 = core_plugin_manager::instance();
54
        $this->assertInstanceOf('core_plugin_manager', $pluginman1);
55
        $pluginman2 = core_plugin_manager::instance();
56
        $this->assertSame($pluginman1, $pluginman2);
57
        $pluginman3 = testable_core_plugin_manager::instance();
58
        $this->assertInstanceOf('core_plugin_manager', $pluginman3);
59
        $this->assertInstanceOf('testable_core_plugin_manager', $pluginman3);
60
        $pluginman4 = testable_core_plugin_manager::instance();
61
        $this->assertSame($pluginman3, $pluginman4);
62
        $this->assertNotSame($pluginman1, $pluginman3);
63
    }
64
 
65
    public function test_reset_caches(): void {
66
        // Make sure there are no warnings or errors.
67
        core_plugin_manager::reset_caches();
68
        testable_core_plugin_manager::reset_caches();
69
    }
70
 
71
    /**
72
     * Make sure that the tearDown() really kills the singleton after this test.
73
     */
74
    public function test_teardown_works_precheck(): void {
75
        $pluginman = testable_core_plugin_manager::instance();
76
        $pluginfo = testable_plugininfo_base::fake_plugin_instance(
77
            'fake',
78
            '/dev/null',
79
            'one',
80
            '/dev/null/fake',
81
            'testable_plugininfo_base',
82
            $pluginman
83
        );
84
        $pluginman->inject_testable_plugininfo('fake', 'one', $pluginfo);
85
 
86
        $this->assertInstanceOf('\core\plugininfo\base', $pluginman->get_plugin_info('fake_one'));
87
        $this->assertNull($pluginman->get_plugin_info('fake_two'));
88
    }
89
 
90
    public function test_teardown_works_postcheck(): void {
91
        $pluginman = testable_core_plugin_manager::instance();
92
        $this->assertNull($pluginman->get_plugin_info('fake_one'));
93
        $this->assertNull($pluginman->get_plugin_info('fake_two'));
94
    }
95
 
96
    public function test_get_plugin_types(): void {
97
        // Make sure there are no warnings or errors.
98
        $types = core_plugin_manager::instance()->get_plugin_types();
99
        $this->assertIsArray($types);
100
        foreach ($types as $type => $fulldir) {
101
            $this->assertFileExists($fulldir);
102
        }
103
    }
104
 
105
    public function test_get_installed_plugins(): void {
106
        $types = core_plugin_manager::instance()->get_plugin_types();
107
        foreach ($types as $type => $fulldir) {
108
            $installed = core_plugin_manager::instance()->get_installed_plugins($type);
109
            foreach ($installed as $plugin => $version) {
110
                $this->assertMatchesRegularExpression('/^[a-z]+[a-z0-9_]*$/', $plugin);
111
                $this->assertTrue(
112
                    is_numeric($version),
113
                    'All plugins should have a version, plugin ' . $type . '_' . $plugin . ' does not have version info.'
114
                );
115
            }
116
        }
117
    }
118
 
119
    public function test_get_enabled_plugins(): void {
120
        $types = core_plugin_manager::instance()->get_plugin_types();
121
        foreach ($types as $type => $fulldir) {
122
            $enabled = core_plugin_manager::instance()->get_enabled_plugins($type);
123
            if (is_array($enabled)) {
124
                foreach ($enabled as $key => $val) {
125
                    $this->assertMatchesRegularExpression('/^[a-z]+[a-z0-9_]*$/', $key);
126
                    $this->assertSame($key, $val);
127
                }
128
            } else {
129
                $this->assertNull($enabled);
130
            }
131
        }
132
    }
133
 
134
    public function test_get_present_plugins(): void {
135
        $types = core_plugin_manager::instance()->get_plugin_types();
136
        foreach ($types as $type => $fulldir) {
137
            $present = core_plugin_manager::instance()->get_present_plugins($type);
138
            if (is_array($present)) {
139
                foreach ($present as $plugin => $version) {
140
                    $this->assertMatchesRegularExpression(
141
                        '/^[a-z]+[a-z0-9_]*$/',
142
                        $plugin,
143
                        'All plugins are supposed to have version.php file.'
144
                    );
145
                    $this->assertIsObject($version);
146
                    $this->assertTrue(
147
                        is_numeric($version->version),
148
                        'All plugins should have a version, plugin ' . $type . '_' . $plugin . ' does not have version info.'
149
                    );
150
                }
151
            } else {
152
                // No plugins of this type exist.
153
                $this->assertNull($present);
154
            }
155
        }
156
    }
157
 
158
    public function test_get_plugins(): void {
159
        $plugininfos1 = core_plugin_manager::instance()->get_plugins();
160
        foreach ($plugininfos1 as $type => $infos) {
161
            foreach ($infos as $name => $info) {
162
                $this->assertInstanceOf('\core\plugininfo\base', $info);
163
            }
164
        }
165
 
166
        // The testable variant of the manager holds its own tree of the
167
        // plugininfo objects.
168
        $plugininfos2 = testable_core_plugin_manager::instance()->get_plugins();
169
        $this->assertNotSame($plugininfos1['mod']['forum'], $plugininfos2['mod']['forum']);
170
 
171
        // Singletons of each manager class share the same tree.
172
        $plugininfos3 = core_plugin_manager::instance()->get_plugins();
173
        $this->assertSame($plugininfos1['mod']['forum'], $plugininfos3['mod']['forum']);
174
        $plugininfos4 = testable_core_plugin_manager::instance()->get_plugins();
175
        $this->assertSame($plugininfos2['mod']['forum'], $plugininfos4['mod']['forum']);
176
    }
177
 
178
    public function test_plugininfo_back_reference_to_the_plugin_manager(): void {
179
        $plugman1 = core_plugin_manager::instance();
180
        $plugman2 = testable_core_plugin_manager::instance();
181
 
182
        foreach ($plugman1->get_plugins() as $type => $infos) {
183
            foreach ($infos as $info) {
184
                $this->assertSame($info->pluginman, $plugman1);
185
            }
186
        }
187
 
188
        foreach ($plugman2->get_plugins() as $type => $infos) {
189
            foreach ($infos as $info) {
190
                $this->assertSame($info->pluginman, $plugman2);
191
            }
192
        }
193
    }
194
 
195
    public function test_get_plugins_of_type(): void {
196
        $plugininfos = core_plugin_manager::instance()->get_plugins();
197
        foreach ($plugininfos as $type => $infos) {
198
            $this->assertSame($infos, core_plugin_manager::instance()->get_plugins_of_type($type));
199
        }
200
    }
201
 
202
    public function test_get_subplugins_of_plugin(): void {
203
        global $CFG;
204
 
205
        // Any standard plugin with subplugins is suitable.
206
        $this->assertFileExists("$CFG->dirroot/lib/editor/tiny", 'TinyMCE is not present.');
207
 
208
        $subplugins = core_plugin_manager::instance()->get_subplugins_of_plugin('editor_tiny');
209
        foreach ($subplugins as $component => $info) {
210
            $this->assertInstanceOf('\core\plugininfo\base', $info);
211
        }
212
    }
213
 
214
    public function test_get_subplugins(): void {
215
        // Tested already indirectly from test_get_subplugins_of_plugin().
216
        $subplugins = core_plugin_manager::instance()->get_subplugins();
217
        $this->assertIsArray($subplugins);
218
    }
219
 
220
    public function test_get_parent_of_subplugin(): void {
221
        global $CFG;
222
 
223
        // Any standard plugin with subplugins is suitable.
224
        $this->assertFileExists("$CFG->dirroot/lib/editor/tiny", 'TinyMCE is not present.');
225
 
226
        $parent = core_plugin_manager::instance()->get_parent_of_subplugin('tiny');
227
        $this->assertSame('editor_tiny', $parent);
228
    }
229
 
230
    public function test_plugin_name(): void {
231
        global $CFG;
232
 
233
        // Any standard plugin is suitable.
234
        $this->assertFileExists("$CFG->dirroot/lib/editor/tiny", 'TinyMCE is not present.');
235
 
236
        $name = core_plugin_manager::instance()->plugin_name('editor_tiny');
237
        $this->assertSame(get_string('pluginname', 'editor_tiny'), $name);
238
    }
239
 
240
    public function test_plugintype_name(): void {
241
        $name = core_plugin_manager::instance()->plugintype_name('editor');
242
        $this->assertSame(get_string('type_editor', 'core_plugin'), $name);
243
    }
244
 
245
    public function test_plugintype_name_plural(): void {
246
        $name = core_plugin_manager::instance()->plugintype_name_plural('editor');
247
        $this->assertSame(get_string('type_editor_plural', 'core_plugin'), $name);
248
    }
249
 
250
    public function test_get_plugin_info(): void {
251
        global $CFG;
252
 
253
        // Any standard plugin is suitable.
254
        $this->assertFileExists("$CFG->dirroot/lib/editor/tiny", 'TinyMCE is not present.');
255
 
256
        $info = core_plugin_manager::instance()->get_plugin_info('editor_tiny');
257
        $this->assertInstanceOf('\core\plugininfo\editor', $info);
258
    }
259
 
260
    public function test_can_uninstall_plugin(): void {
261
        global $CFG;
262
 
263
        // Any standard plugin that is required by some other standard plugin is ok.
264
        $this->assertFileExists("$CFG->dirroot/report/competency", 'competency report is not present');
265
        $this->assertFileExists("$CFG->dirroot/$CFG->admin/tool/lp", 'tool lp is not present');
266
 
267
        $this->assertFalse(core_plugin_manager::instance()->can_uninstall_plugin('tool_lp'));
268
        $this->assertTrue(core_plugin_manager::instance()->can_uninstall_plugin('report_competency'));
269
    }
270
 
271
    public function test_plugin_states(): void {
272
        global $CFG;
273
        $this->resetAfterTest();
274
 
275
        // Any standard plugin that is ok.
276
        $this->assertFileExists("$CFG->dirroot/mod/assign", 'assign module is not present');
277
        $this->assertFileExists("$CFG->dirroot/mod/forum", 'forum module is not present');
278
        $this->assertFileExists("$CFG->dirroot/$CFG->admin/tool/phpunit", 'phpunit tool is not present');
279
        $this->assertFileDoesNotExist("$CFG->dirroot/mod/xxxxxxx");
280
        $this->assertFileDoesNotExist("$CFG->dirroot/enrol/autorize");
281
 
282
        // Ready for upgrade.
283
        $assignversion = get_config('mod_assign', 'version');
284
        set_config('version', $assignversion - 1, 'mod_assign');
285
        // Downgrade problem.
286
        $forumversion = get_config('mod_forum', 'version');
287
        set_config('version', $forumversion + 1, 'mod_forum');
288
        // Not installed yet.
289
        unset_config('version', 'tool_phpunit');
290
        // Missing already installed.
291
        set_config('version', 2013091300, 'mod_xxxxxxx');
292
        // Deleted present.
293
        set_config('version', 2013091300, 'enrol_authorize');
294
 
295
        core_plugin_manager::reset_caches();
296
 
297
        $plugininfos = core_plugin_manager::instance()->get_plugins();
298
        foreach ($plugininfos as $type => $infos) {
299
            /** @var \core\plugininfo\base $info */
300
            foreach ($infos as $info) {
301
                if ($info->component === 'mod_assign') {
302
                    $this->assertSame(
303
                        core_plugin_manager::PLUGIN_STATUS_UPGRADE,
304
                        $info->get_status(),
305
                        'Invalid ' . $info->component . ' state'
306
                    );
307
                } else if ($info->component === 'mod_forum') {
308
                    $this->assertSame(
309
                        core_plugin_manager::PLUGIN_STATUS_DOWNGRADE,
310
                        $info->get_status(),
311
                        'Invalid ' . $info->component . ' state'
312
                    );
313
                } else if ($info->component === 'tool_phpunit') {
314
                    $this->assertSame(
315
                        core_plugin_manager::PLUGIN_STATUS_NEW,
316
                        $info->get_status(),
317
                        'Invalid ' . $info->component . ' state'
318
                    );
319
                } else if ($info->component === 'mod_xxxxxxx') {
320
                    $this->assertSame(
321
                        core_plugin_manager::PLUGIN_STATUS_MISSING,
322
                        $info->get_status(),
323
                        'Invalid ' . $info->component . ' state'
324
                    );
325
                } else if ($info->component === 'enrol_authorize') {
326
                    $this->assertSame(
327
                        core_plugin_manager::PLUGIN_STATUS_DELETE,
328
                        $info->get_status(),
329
                        'Invalid ' . $info->component . ' state'
330
                    );
331
                } else {
332
                    $this->assertSame(
333
                        core_plugin_manager::PLUGIN_STATUS_UPTODATE,
334
                        $info->get_status(),
335
                        'Invalid ' . $info->component . ' state'
336
                    );
337
                }
338
            }
339
        }
340
    }
341
 
342
    public function test_plugin_available_updates(): void {
343
        $pluginman = testable_core_plugin_manager::instance();
344
 
345
        $foobar = testable_plugininfo_base::fake_plugin_instance(
346
            'foo',
347
            '/dev/null',
348
            'bar',
349
            '/dev/null/fake',
350
            'testable_plugininfo_base',
351
            $pluginman
352
        );
353
        $foobar->versiondb = 2015092900;
354
        $foobar->versiondisk = 2015092900;
355
        $pluginman->inject_testable_plugininfo('foo', 'bar', $foobar);
356
 
357
        $washere = false;
358
        foreach ($pluginman->get_plugins() as $type => $infos) {
359
            foreach ($infos as $name => $plugin) {
360
                $updates = $plugin->available_updates();
361
                if ($plugin->component != 'foo_bar') {
362
                    $this->assertNull($updates);
363
                } else {
364
                    $this->assertTrue(is_array($updates));
365
                    $this->assertEquals(3, count($updates));
366
                    foreach ($updates as $update) {
367
                        $washere = true;
368
                        $this->assertInstanceOf('\core\update\info', $update);
369
                        $this->assertEquals($update->component, $plugin->component);
370
                        $this->assertTrue($update->version > $plugin->versiondb);
371
                    }
372
                }
373
            }
374
        }
375
        $this->assertTrue($washere);
376
    }
377
 
378
    public function test_some_plugins_updatable_none(): void {
379
        $pluginman = testable_core_plugin_manager::instance();
380
        $this->assertFalse($pluginman->some_plugins_updatable());
381
    }
382
 
383
    public function test_some_plugins_updatable_some(): void {
384
        $pluginman = testable_core_plugin_manager::instance();
385
 
386
        $foobar = testable_plugininfo_base::fake_plugin_instance(
387
            'foo',
388
            '/dev/null',
389
            'bar',
390
            '/dev/null/fake',
391
            'testable_plugininfo_base',
392
            $pluginman
393
        );
394
        $foobar->versiondb = 2015092900;
395
        $foobar->versiondisk = 2015092900;
396
        $pluginman->inject_testable_plugininfo('foo', 'bar', $foobar);
397
 
398
        $this->assertTrue($pluginman->some_plugins_updatable());
399
    }
400
 
401
    public function test_available_updates(): void {
402
        $pluginman = testable_core_plugin_manager::instance();
403
 
404
        $foobar = testable_plugininfo_base::fake_plugin_instance(
405
            'foo',
406
            '/dev/null',
407
            'bar',
408
            '/dev/null/fake',
409
            'testable_plugininfo_base',
410
            $pluginman
411
        );
412
        $foobar->versiondb = 2015092900;
413
        $foobar->versiondisk = 2015092900;
414
        $pluginman->inject_testable_plugininfo('foo', 'bar', $foobar);
415
 
416
        $updates = $pluginman->available_updates();
417
 
418
        $this->assertTrue(is_array($updates));
419
        $this->assertEquals(1, count($updates));
420
        $update = $updates['foo_bar'];
421
        $this->assertInstanceOf('\core\update\remote_info', $update);
422
        $this->assertEquals('foo_bar', $update->component);
423
        $this->assertEquals(2015100400, $update->version->version);
424
    }
425
 
426
    public function test_get_remote_plugin_info(): void {
427
        $pluginman = testable_core_plugin_manager::instance();
428
 
429
        $this->assertFalse($pluginman->get_remote_plugin_info('not_exists', ANY_VERSION, false));
430
 
431
        $info = $pluginman->get_remote_plugin_info('foo_bar', 2015093000, true);
432
        $this->assertEquals(2015093000, $info->version->version);
433
 
434
        $info = $pluginman->get_remote_plugin_info('foo_bar', 2015093000, false);
435
        $this->assertEquals(2015100400, $info->version->version);
436
    }
437
 
438
    /**
439
     * The combination of ANY_VERSION + $exactmatch is illegal.
440
     */
441
    public function test_get_remote_plugin_info_exception(): void {
442
        $pluginman = testable_core_plugin_manager::instance();
443
        $this->expectException(\moodle_exception::class);
444
        $pluginman->get_remote_plugin_info('any_thing', ANY_VERSION, true);
445
    }
446
 
447
    public function test_is_remote_plugin_available(): void {
448
        $pluginman = testable_core_plugin_manager::instance();
449
 
450
        $this->assertFalse($pluginman->is_remote_plugin_available('not_exists', ANY_VERSION, false));
451
        $this->assertTrue($pluginman->is_remote_plugin_available('foo_bar', 2013131313, false));
452
        $this->assertFalse($pluginman->is_remote_plugin_available('foo_bar', 2013131313, true));
453
    }
454
 
455
    public function test_resolve_requirements(): void {
456
        $pluginman = testable_core_plugin_manager::instance();
457
 
458
        // Prepare a fake pluginfo instance.
459
        $pluginfo = testable_plugininfo_base::fake_plugin_instance(
460
            'fake',
461
            '/dev/null',
462
            'one',
463
            '/dev/null/fake',
464
            'testable_plugininfo_base',
465
            $pluginman
466
        );
467
        $pluginfo->versiondisk = 2015060600;
468
 
469
        // Test no $plugin->requires is specified in version.php.
470
        $pluginfo->versionrequires = null;
471
        $this->assertTrue($pluginfo->is_core_dependency_satisfied(2015100100));
472
        $reqs = $pluginman->resolve_requirements($pluginfo, 2015100100, 29);
473
        $this->assertEquals(2015100100, $reqs['core']->hasver);
474
        $this->assertEquals(ANY_VERSION, $reqs['core']->reqver);
475
        $this->assertEquals($pluginman::REQUIREMENT_STATUS_OK, $reqs['core']->status);
476
 
477
        // Test plugin requires higher core version.
478
        $pluginfo->versionrequires = 2015110900;
479
        $this->assertFalse($pluginfo->is_core_dependency_satisfied(2015100100));
480
        $reqs = $pluginman->resolve_requirements($pluginfo, 2015100100, 29);
481
        $this->assertEquals(2015100100, $reqs['core']->hasver);
482
        $this->assertEquals(2015110900, $reqs['core']->reqver);
483
        $this->assertEquals($pluginman::REQUIREMENT_STATUS_OUTDATED, $reqs['core']->status);
484
 
485
        // Test plugin requires current core version.
486
        $pluginfo->versionrequires = 2015110900;
487
        $this->assertTrue($pluginfo->is_core_dependency_satisfied(2015110900));
488
        $reqs = $pluginman->resolve_requirements($pluginfo, 2015110900, 30);
489
        $this->assertEquals(2015110900, $reqs['core']->hasver);
490
        $this->assertEquals(2015110900, $reqs['core']->reqver);
491
        $this->assertEquals($pluginman::REQUIREMENT_STATUS_OK, $reqs['core']->status);
492
 
493
        // Test plugin requires lower core version.
494
        $pluginfo->versionrequires = 2014122400;
495
        $this->assertTrue($pluginfo->is_core_dependency_satisfied(2015100100));
496
        $reqs = $pluginman->resolve_requirements($pluginfo, 2015100100, 29);
497
        $this->assertEquals(2015100100, $reqs['core']->hasver);
498
        $this->assertEquals(2014122400, $reqs['core']->reqver);
499
        $this->assertEquals($pluginman::REQUIREMENT_STATUS_OK, $reqs['core']->status);
500
 
501
        // Test plugin dependencies and their availability.
502
        // See {@link \core\update\testable_api} class.
503
 
504
        $pluginfo->dependencies = ['foo_bar' => ANY_VERSION, 'not_exists' => ANY_VERSION];
505
        $reqs = $pluginman->resolve_requirements($pluginfo, 2015110900, 30);
506
        $this->assertNull($reqs['foo_bar']->hasver);
507
        $this->assertEquals(ANY_VERSION, $reqs['foo_bar']->reqver);
508
        $this->assertEquals($pluginman::REQUIREMENT_STATUS_MISSING, $reqs['foo_bar']->status);
509
        $this->assertEquals($pluginman::REQUIREMENT_AVAILABLE, $reqs['foo_bar']->availability);
510
        $this->assertEquals($pluginman::REQUIREMENT_UNAVAILABLE, $reqs['not_exists']->availability);
511
 
512
        $pluginfo->dependencies = ['foo_bar' => 2013122400];
513
        $reqs = $pluginman->resolve_requirements($pluginfo, 2015110900, 30);
514
        $this->assertEquals($pluginman::REQUIREMENT_AVAILABLE, $reqs['foo_bar']->availability);
515
 
516
        $pluginfo->dependencies = ['foo_bar' => 2015093000];
517
        $reqs = $pluginman->resolve_requirements($pluginfo, 2015110900, 30);
518
        $this->assertEquals($pluginman::REQUIREMENT_AVAILABLE, $reqs['foo_bar']->availability);
519
 
520
        $pluginfo->dependencies = ['foo_bar' => 2015100500];
521
        $reqs = $pluginman->resolve_requirements($pluginfo, 2015110900, 30);
522
        $this->assertEquals($pluginman::REQUIREMENT_AVAILABLE, $reqs['foo_bar']->availability);
523
 
524
        $pluginfo->dependencies = ['foo_bar' => 2025010100];
525
        $reqs = $pluginman->resolve_requirements($pluginfo, 2015110900, 30);
526
        $this->assertEquals($pluginman::REQUIREMENT_UNAVAILABLE, $reqs['foo_bar']->availability);
527
 
528
        // Plugin missing from disk - no version.php available.
529
        $pluginfo = testable_plugininfo_base::fake_plugin_instance(
530
            'fake',
531
            '/dev/null',
532
            'missing',
533
            '/dev/null/fake',
534
            'testable_plugininfo_base',
535
            $pluginman
536
        );
537
        $pluginfo->versiondisk = null;
538
        $this->assertEmpty($pluginman->resolve_requirements($pluginfo, 2015110900, 30));
539
 
540
        // Test plugin fails for incompatible version.
541
        $pluginfo = testable_plugininfo_base::fake_plugin_instance(
542
            'fake',
543
            '/dev/null',
544
            'two',
545
            '/dev/null/fake',
546
            'testable_plugininfo_base',
547
            $pluginman
548
        );
549
        $pluginfo->versiondisk = 2015060600;
550
        $pluginfo->pluginincompatible = 30;
551
        $reqs = $pluginman->resolve_requirements($pluginfo, 2015110900, 30);
552
        $this->assertEquals($pluginman::REQUIREMENT_STATUS_NEWER, $reqs['core']->status);
553
 
554
        // Test no failure for no incompatible version.
555
        $pluginfo->pluginincompatible = 30;
556
        $reqs = $pluginman->resolve_requirements($pluginfo, 2015110900, 29);
557
        $this->assertEquals($pluginman::REQUIREMENT_STATUS_OK, $reqs['core']->status);
558
    }
559
 
560
    public function test_missing_dependencies(): void {
561
        $pluginman = testable_core_plugin_manager::instance();
562
 
563
        $one = testable_plugininfo_base::fake_plugin_instance(
564
            'fake',
565
            '/dev/null',
566
            'one',
567
            '/dev/null/fake',
568
            'testable_plugininfo_base',
569
            $pluginman
570
        );
571
        $one->versiondisk = 2015070800;
572
 
573
        $two = testable_plugininfo_base::fake_plugin_instance(
574
            'fake',
575
            '/dev/null',
576
            'two',
577
            '/dev/null/fake',
578
            'testable_plugininfo_base',
579
            $pluginman
580
        );
581
        $two->versiondisk = 2015070900;
582
 
583
        $pluginman->inject_testable_plugininfo('fake', 'one', $one);
584
        $pluginman->inject_testable_plugininfo('fake', 'two', $two);
585
 
586
        $this->assertEmpty($pluginman->missing_dependencies());
587
 
588
        $one->dependencies = ['foo_bar' => ANY_VERSION];
589
        $misdeps = $pluginman->missing_dependencies();
590
        $this->assertInstanceOf('\core\update\remote_info', $misdeps['foo_bar']);
591
        $this->assertEquals(2015100400, $misdeps['foo_bar']->version->version);
592
 
593
        $two->dependencies = ['foo_bar' => 2015100500];
594
        $misdeps = $pluginman->missing_dependencies();
595
        $this->assertInstanceOf('\core\update\remote_info', $misdeps['foo_bar']);
596
        $this->assertEquals(2015100500, $misdeps['foo_bar']->version->version);
597
    }
598
 
599
    /**
600
     * Tests for check_explicitly_supported function to ensure that versions are correctly reported.
601
     *
602
     * @dataProvider check_explicitly_supported_provider
603
     * @param array|null $supported Supported versions to inject
604
     * @param string|int|null $incompatible Incompatible version to inject.
605
     * @param int $version Version to test
606
     * @param int $expected
607
     * @return void
608
     */
609
    public function test_explicitly_supported($supported, $incompatible, $version, $expected): void {
610
        $pluginman = testable_core_plugin_manager::instance();
611
 
612
        // Prepare a fake pluginfo instance.
613
        $plugininfo = new testable_plugininfo_base();
614
        $plugininfo->type = 'fake';
615
        $plugininfo->typerootdir = '/dev/null';
616
        $plugininfo->name = 'example';
617
        $plugininfo->rootdir = '/dev/null/fake';
618
        $plugininfo->pluginman = $pluginman;
619
        $plugininfo->versiondisk = 2015060600;
620
        $plugininfo->supported = $supported;
621
        $plugininfo->incompatible = $incompatible;
622
 
623
        $pluginman->add_fake_plugin_info($plugininfo);
624
 
625
        $plugininfo->load_disk_version();
626
 
627
        $this->assertEquals($expected, $pluginman->check_explicitly_supported($plugininfo, $version));
628
    }
629
 
630
    /**
631
     * Data provider for check_explicitly_supported with a range of correctly defined version support values.
632
     *
633
     * @return array
634
     */
635
    public static function check_explicitly_supported_provider(): array {
636
        return [
637
            'Range, branch in support, lowest' => [
638
                'supported' => [29, 31],
639
                'incompatible' => null,
640
                'version' => 29,
641
                'expected' => core_plugin_manager::VERSION_SUPPORTED,
642
            ],
643
            'Range, branch in support, mid' => [
644
                'supported' => [29, 31],
645
                'incompatible' => null,
646
                'version' => 30,
647
                'expected' => core_plugin_manager::VERSION_SUPPORTED,
648
            ],
649
            'Range, branch in support, highest' => [
650
                'supported' => [29, 31],
651
                'incompatible' => null,
652
                'version' => 31,
653
                'expected' => core_plugin_manager::VERSION_SUPPORTED,
654
            ],
655
 
656
            'Range, branch not in support, high' => [
657
                'supported' => [29, 31],
658
                'incompatible' => null,
659
                'version' => 32,
660
                'expected' => core_plugin_manager::VERSION_NOT_SUPPORTED,
661
            ],
662
            'Range, branch not in support, low' => [
663
                'supported' => [29, 31],
664
                'incompatible' => null,
665
                'version' => 28,
666
                'expected' => core_plugin_manager::VERSION_NOT_SUPPORTED,
667
            ],
668
            'Range, incompatible, high.' => [
669
                'supported' => [29, 31],
670
                'incompatible' => 32,
671
                'version' => 33,
672
                'expected' => core_plugin_manager::VERSION_NOT_SUPPORTED,
673
            ],
674
            'Range, incompatible, low.' => [
675
                'supported' => [29, 31],
676
                'incompatible' => 32,
677
                'version' => 31,
678
                'expected' => core_plugin_manager::VERSION_SUPPORTED,
679
            ],
680
            'Range, incompatible, equal.' => [
681
                'supported' => [29, 31],
682
                'incompatible' => 32,
683
                'version' => 32,
684
                'expected' => core_plugin_manager::VERSION_NOT_SUPPORTED,
685
            ],
686
            'No supports' => [
687
                'supported' => null,
688
                'incompatible' => null,
689
                'version' => 32,
690
                'expected' => core_plugin_manager::VERSION_NO_SUPPORTS,
691
            ],
692
            'No supports, but incompatible, older' => [
693
                'supported' => null,
694
                'incompatible' => 30,
695
                'version' => 32,
696
                'expected' => core_plugin_manager::VERSION_NOT_SUPPORTED,
697
            ],
698
            'No supports, but incompatible, equal' => [
699
                'supported' => null,
700
                'incompatible' => 32,
701
                'version' => 32,
702
                'expected' => core_plugin_manager::VERSION_NOT_SUPPORTED,
703
            ],
704
            'No supports, but incompatible, newer' => [
705
                'supported' => null,
706
                'incompatible' => 34,
707
                'version' => 32,
708
                'expected' => core_plugin_manager::VERSION_NO_SUPPORTS,
709
            ],
710
        ];
711
    }
712
 
713
    /**
714
     * @dataProvider is_deleted_standard_plugin_provider
715
     */
716
    public function test_is_deleted_standard_plugin(
717
        mixed $type,
718
        mixed $name,
719
        bool $expected,
720
    ): void {
721
        $this->assertEquals(
722
            $expected,
723
            \core_plugin_manager::is_deleted_standard_plugin($type, $name),
724
        );
725
    }
726
 
727
    public static function is_deleted_standard_plugin_provider(): array {
728
        return [
729
            // Valid deleted plugin.
730
            ['h5plib', 'v124', true],
731
            // Valid type, but not a valid plugin.
732
            ['h5plib', 'v99', false],
733
            // Invalid type.
734
            ['marmelade', 'paddington', false],
735
        ];
736
    }
737
 
738
    public function test_get_deleted_plugins(): void {
739
        $plugins = core_plugin_manager::get_deleted_plugins();
740
        $this->assertIsArray($plugins);
741
 
742
        // Pick a couple we know should be there.
743
        $this->assertContains('h5plib_v124', $plugins);
744
        $this->assertNotContains('h5plib_v99', $plugins);
745
 
746
        $this->assertContains('editor_tinymce', $plugins);
747
        $this->assertNotContains('editor_tiny', $plugins);
748
    }
749
 
750
    public function test_standard_plugins_list_no_type(): void {
751
        $plugins = core_plugin_manager::standard_plugins_list('typo');
752
        $this->assertFalse($plugins);
753
    }
754
 
755
    /**
756
     * @dataProvider standard_plugins_list_provider
757
     */
758
    public function test_standard_plugins_list(
759
        string $type,
760
        array $expectedplugins,
761
    ): void {
762
        $plugins = core_plugin_manager::standard_plugins_list($type);
763
        $this->assertIsArray($plugins);
764
        foreach ($expectedplugins as $expected) {
765
            $this->assertContains($expected, $plugins);
766
        }
767
    }
768
 
769
    public static function standard_plugins_list_provider(): array {
770
        return [
771
            [
772
                'mod',
773
                ['forum', 'assign', 'book', 'choice'],
774
            ],
775
            [
776
                'block',
777
                ['starredcourses', 'badges'],
778
            ],
779
            [
780
                'tiny',
781
                ['autosave', 'h5p'],
782
            ],
783
        ];
784
    }
785
 
786
    public function test_get_standard_plugins(): void {
787
        $plugins = core_plugin_manager::get_standard_plugins();
788
        $this->assertIsArray($plugins);
789
 
790
        $this->assertContains('mod_forum', $plugins);
791
        $this->assertContains('block_badges', $plugins);
792
        $this->assertNotContains('marmelade_paddington', $plugins);
793
    }
1441 ariadna 794
 
795
    /**
796
     * Test core_plugin_manager when dealing with deprecated plugin (not subplugin) types.
797
     *
798
     * @runInSeparateProcess
799
     * @return void
800
     */
801
    public function test_plugin_manager_deprecated_plugintype(): void {
802
        $this->resetAfterTest();
803
 
804
        // Inject the mock plugin 'fake_fullfeatured' and deprecate it.
805
        $this->add_full_mocked_plugintype(
806
            plugintype: 'fake',
807
            path: 'lib/tests/fixtures/fakeplugins/fake',
808
        );
809
        $this->deprecate_full_mocked_plugintype('fake');
810
 
811
        // Use testable_plugin_manager, as this properly loads the mocked fake_plugininfo class, meaning the fake plugins are
812
        // recognised by the plugin manager. See testable_plugin_manager::resolve_plugininfo_class().
813
        $pluginman = testable_core_plugin_manager::instance();
814
 
815
        // Deprecated plugin type are excluded from the following for B/C.
816
        $this->assertArrayNotHasKey('fake', $pluginman->get_plugin_types());
817
        $this->assertNull($pluginman->get_enabled_plugins('fake'));
818
 
819
        // Deprecated plugins excluded by default for B/C, but can be included by request.
820
        $this->assertArrayNotHasKey('fake', $pluginman->get_plugins());
821
        $plugins = $pluginman->get_plugins(true);
822
        $this->assertArrayHasKey('fake', $plugins);
823
 
824
        /** @var base $plugininfo */
825
        $plugininfo = $plugins['fake']['fullfeatured'];
826
        $this->assertNull($plugininfo->is_enabled());
827
        $this->assertTrue($plugininfo->is_deprecated());
828
        $this->assertFalse($plugininfo->is_deleted());
829
        $this->assertTrue($plugininfo->is_uninstall_allowed());
830
        $this->assertIsString($plugininfo->full_path('version.php'));
831
        $this->assertEquals(\core_plugin_manager::PLUGIN_STATUS_UPTODATE, $plugininfo->get_status());
832
        $this->assertFalse($plugininfo->get_parent_plugin());
833
        $this->assertNotEmpty($plugininfo->versiondisk);
834
        $this->assertStringContainsString('/fake/', $plugininfo->get_dir());
835
 
836
        $this->assertArrayNotHasKey('fullfeatured', $pluginman->get_plugins_of_type('fake'));
837
        $this->assertArrayHasKey('fullfeatured', $pluginman->get_plugins_of_type('fake', true));
838
 
839
        // Deprecated plugins included in the following.
840
        $this->assertArrayHasKey('fullfeatured', $pluginman->get_present_plugins('fake')); // Plugins on disk.
841
        $this->assertArrayHasKey('fullfeatured', $pluginman->get_installed_plugins('fake')); // Plugins with DB config.
842
        $this->assertInstanceOf(\fake_plugininfo::class, $pluginman->get_plugin_info('fake_fullfeatured'));
843
        $this->assertIsString($pluginman->get_plugintype_root('fake'));
844
        $this->assertTrue($pluginman->can_uninstall_plugin('fake_fullfeatured'));
845
        $uninstallurl = $pluginman->get_uninstall_url('fake_fullfeatured');
846
        $this->assertInstanceOf(\moodle_url::class, $uninstallurl);
847
        $this->assertEquals('fake_fullfeatured', $uninstallurl->param('uninstall'));
848
 
849
        // Strings are supported for deprecated plugins.
850
        $this->assertEquals('Fake full featured plugin', $pluginman->plugin_name('fake_fullfeatured'));
851
        $this->assertEquals('fake', $pluginman->plugintype_name('fake'));
852
        $this->assertEquals('fake', $pluginman->plugintype_name_plural('fake'));
853
    }
854
 
855
    /**
856
     * Test core_plugin_manager when dealing with deprecated subplugin types.
857
     *
858
     * @runInSeparateProcess
859
     * @return void
860
     */
861
    public function test_plugin_manager_deprecated_subplugintype(): void {
862
        $this->resetAfterTest();
863
 
864
        // Inject the 'fake' plugin type. This includes three mock subplugins:
865
        // 1. fullsubtype_example: a regular plugin type, not deprecated, nor deleted.
866
        // 2. fulldeprecatedsubtype_test: a deprecated subplugin type.
867
        // 3. fulldeletedsubtype_demo: a deleted subplugin type.
868
        $this->add_full_mocked_plugintype(
869
            plugintype: 'fake',
870
            path: 'lib/tests/fixtures/fakeplugins/fake',
871
            subpluginsupport: true
872
        );
873
 
874
        // Use testable_plugin_manager, as this properly loads the mocked fake_plugininfo class, meaning the fake plugins are
875
        // recognised by the plugin manager. See testable_plugin_manager::resolve_plugininfo_class().
876
        $pluginman = testable_core_plugin_manager::instance();
877
 
878
        // Deprecated plugin type are excluded from the following for B/C.
879
        $this->assertArrayNotHasKey('fulldeprecatedsubtype', $pluginman->get_plugin_types());
880
        $this->assertNull($pluginman->get_enabled_plugins('fulldeprecatedsubtype'));
881
        $subplugins = $pluginman->get_subplugins();
882
        $this->assertArrayHasKey('fake_fullfeatured', $subplugins);
883
        $fullfeaturedplug = $subplugins['fake_fullfeatured'];
884
        $this->assertArrayHasKey('fullsubtype', $fullfeaturedplug);
885
        $this->assertArrayNotHasKey('fulldeprecatedsubtype', $fullfeaturedplug);
886
        $this->assertArrayHasKey('fullsubtype_example', $pluginman->get_subplugins_of_plugin('fake_fullfeatured'));
887
        $this->assertArrayNotHasKey('fulldeprecatedsubtype_test', $pluginman->get_subplugins_of_plugin('fake_fullfeatured'));
888
 
889
        // Deprecated plugins excluded by default for B/C, but can be included by request.
890
        $this->assertArrayNotHasKey('fulldeprecatedsubtype', $pluginman->get_plugins());
891
        $plugins = $pluginman->get_plugins(true);
892
        $this->assertArrayHasKey('fulldeprecatedsubtype', $plugins);
893
 
894
        /** @var base $plugininfo */
895
        $plugininfo = $plugins['fulldeprecatedsubtype']['test'];
896
        $this->assertNull($plugininfo->is_enabled());
897
        $this->assertTrue($plugininfo->is_deprecated());
898
        $this->assertFalse($plugininfo->is_deleted());
899
        $this->assertTrue($plugininfo->is_uninstall_allowed());
900
        $this->assertIsString($plugininfo->full_path('version.php'));
901
        $this->assertEquals(\core_plugin_manager::PLUGIN_STATUS_UPTODATE, $plugininfo->get_status());
902
        $this->assertEquals('fake_fullfeatured', $plugininfo->get_parent_plugin());
903
        $this->assertNotEmpty($plugininfo->versiondisk);
904
        $this->assertStringContainsString('/fulldeprecatedsubtype/', $plugininfo->get_dir());
905
 
906
        $this->assertArrayNotHasKey('test', $pluginman->get_plugins_of_type('fulldeprecatedsubtype'));
907
        $this->assertArrayHasKey('test', $pluginman->get_plugins_of_type('fulldeprecatedsubtype', true));
908
 
909
        $this->assertFalse($pluginman->get_parent_of_subplugin('fulldeprecatedsubtype'));
910
        $this->assertEquals('fake_fullfeatured', $pluginman->get_parent_of_subplugin('fulldeprecatedsubtype', true));
911
 
912
        // Deprecated plugins included in the following.
913
        $this->assertArrayHasKey('test', $pluginman->get_present_plugins('fulldeprecatedsubtype')); // Plugins on disk.
914
        $this->assertArrayHasKey('test', $pluginman->get_installed_plugins('fulldeprecatedsubtype')); // Plugins with DB config.
915
        $this->assertInstanceOf(\fake_fullfeatured\plugininfo\fulldeprecatedsubtype::class,
916
            $pluginman->get_plugin_info('fulldeprecatedsubtype_test'));
917
        $this->assertEquals('Full deprecated subtype test', $pluginman->plugin_name('fulldeprecatedsubtype_test'));
918
        $this->assertIsString($pluginman->get_plugintype_root('fulldeprecatedsubtype'));
919
        $this->assertTrue($pluginman->can_uninstall_plugin('fulldeprecatedsubtype_test'));
920
        $uninstallurl = $pluginman->get_uninstall_url('fulldeprecatedsubtype_test');
921
        $this->assertInstanceOf(\moodle_url::class, $uninstallurl);
922
        $this->assertEquals('fulldeprecatedsubtype_test', $uninstallurl->param('uninstall'));
923
    }
924
 
925
    /**
926
     * Test core_plugin_manager when dealing with deleted plugin (not subplugin) types.
927
     *
928
     * @runInSeparateProcess
929
     * @return void
930
     */
931
    public function test_plugin_manager_deleted_plugintype(): void {
932
        $this->resetAfterTest();
933
 
934
        // Inject the mock plugin 'fake_fullfeatured', and deprecate it.
935
        $this->add_full_mocked_plugintype(
936
            plugintype: 'fake',
937
            path: 'lib/tests/fixtures/fakeplugins/fake',
938
        );
939
        $this->delete_full_mocked_plugintype('fake');
940
 
941
        // Use testable_plugin_manager, as this properly loads the mocked fake_plugininfo class, meaning the fake plugins are
942
        // recognised by the plugin manager. See testable_plugin_manager::resolve_plugininfo_class().
943
        $pluginman = testable_core_plugin_manager::instance();
944
 
945
        // Deleted plugins are excluded from the following for B/C.
946
        $this->assertArrayNotHasKey('fake', $pluginman->get_plugin_types());
947
        $this->assertNull($pluginman->get_enabled_plugins('fake'));
948
 
949
        // Deleted plugins excluded by default for B/C, but can be included by request.
950
        $this->assertArrayNotHasKey('fake', $pluginman->get_plugins());
951
        $plugins = $pluginman->get_plugins(true);
952
        $this->assertArrayHasKey('fake', $plugins);
953
 
954
        /** @var base $plugininfo */
955
        $plugininfo = $plugins['fake']['fullfeatured'];
956
        $this->assertNull($plugininfo->is_enabled());
957
        $this->assertFalse($plugininfo->is_deprecated());
958
        $this->assertTrue($plugininfo->is_deleted());
959
        $this->assertTrue($plugininfo->is_uninstall_allowed());
960
        $this->assertIsString($plugininfo->full_path('version.php'));
961
        $this->assertEquals(\core_plugin_manager::PLUGIN_STATUS_UPTODATE, $plugininfo->get_status());
962
        $this->assertFalse($plugininfo->get_parent_plugin());
963
        $this->assertNotEmpty($plugininfo->versiondisk);
964
        $this->assertStringContainsString('/fake/', $plugininfo->get_dir());
965
 
966
        $this->assertArrayNotHasKey('fullfeatured', $pluginman->get_plugins_of_type('fake'));
967
        $this->assertArrayHasKey('fullfeatured', $pluginman->get_plugins_of_type('fake', true));
968
 
969
        // Deleted plugins included in the following.
970
        $this->assertArrayHasKey('fullfeatured', $pluginman->get_present_plugins('fake')); // Plugins on disk.
971
        $this->assertArrayHasKey('fullfeatured', $pluginman->get_installed_plugins('fake')); // Plugins with DB config.
972
        $this->assertInstanceOf(\fake_plugininfo::class, $pluginman->get_plugin_info('fake_fullfeatured'));
973
        $this->assertIsString($pluginman->get_plugintype_root('fake'));
974
        $this->assertTrue($pluginman->can_uninstall_plugin('fake_fullfeatured'));
975
        $uninstallurl = $pluginman->get_uninstall_url('fake_fullfeatured');
976
        $this->assertInstanceOf(\moodle_url::class, $uninstallurl);
977
        $this->assertEquals('fake_fullfeatured', $uninstallurl->param('uninstall'));
978
 
979
        // Included, but there is no string support for deleted plugin types.
980
        // Without string support, the type name defaults to the plugin type,
981
        // while plugin name is set in \core\plugininfo\base::init_is_deprecated().
982
        $this->assertEquals('fullfeatured', $pluginman->plugin_name('fake_fullfeatured'));
983
        $this->assertEquals('fake', $pluginman->plugintype_name('fake'));
984
        $this->assertEquals('fake', $pluginman->plugintype_name_plural('fake'));
985
    }
986
 
987
    /**
988
     * Test core_plugin_manager when dealing with deleted subplugin types.
989
     *
990
     * @runInSeparateProcess
991
     * @return void
992
     */
993
    public function test_plugin_manager_deleted_subplugintype(): void {
994
        $this->resetAfterTest();
995
 
996
        // Inject the 'fake' plugin type. This includes three mock subplugins:
997
        // 1. fullsubtype_example: a regular plugin type, not deprecated, nor deleted.
998
        // 2. fulldeprecatedsubtype_test: a deprecated subplugin type.
999
        // 3. fulldeletedsubtype_demo: a deleted subplugin type.
1000
        $this->add_full_mocked_plugintype(
1001
            plugintype: 'fake',
1002
            path: 'lib/tests/fixtures/fakeplugins/fake',
1003
            subpluginsupport: true
1004
        );
1005
 
1006
        // Use testable_plugin_manager, as this properly loads the mocked fake_plugininfo class, meaning the fake plugins are
1007
        // recognised by the plugin manager. See testable_plugin_manager::resolve_plugininfo_class().
1008
        $pluginman = testable_core_plugin_manager::instance();
1009
 
1010
        // Deleted plugin type are excluded from the following for B/C.
1011
        $this->assertArrayNotHasKey('fulldeletedsubtype', $pluginman->get_plugin_types());
1012
        $this->assertNull($pluginman->get_enabled_plugins('fulldeletedsubtype'));
1013
        $subplugins = $pluginman->get_subplugins();
1014
        $this->assertArrayHasKey('fake_fullfeatured', $subplugins);
1015
        $fullfeaturedplug = $subplugins['fake_fullfeatured'];
1016
        $this->assertArrayHasKey('fullsubtype', $fullfeaturedplug);
1017
        $this->assertArrayNotHasKey('fulldeletedsubtype', $fullfeaturedplug);
1018
        $this->assertArrayHasKey('fullsubtype_example', $pluginman->get_subplugins_of_plugin('fake_fullfeatured'));
1019
        $this->assertArrayNotHasKey('fulldeletedsubtype_demo', $pluginman->get_subplugins_of_plugin('fake_fullfeatured'));
1020
 
1021
        // Deleted plugins excluded by default for B/C, but can be included by request.
1022
        $this->assertArrayNotHasKey('fulldeletedsubtype', $pluginman->get_plugins());
1023
        $plugins = $pluginman->get_plugins(true);
1024
        $this->assertArrayHasKey('fulldeletedsubtype', $plugins);
1025
 
1026
        /** @var base $plugininfo */
1027
        $plugininfo = $plugins['fulldeletedsubtype']['demo'];
1028
        $this->assertNull($plugininfo->is_enabled());
1029
        $this->assertFalse($plugininfo->is_deprecated());
1030
        $this->assertTrue($plugininfo->is_deleted());
1031
        $this->assertTrue($plugininfo->is_uninstall_allowed());
1032
        $this->assertIsString($plugininfo->full_path('version.php'));
1033
        $this->assertEquals(\core_plugin_manager::PLUGIN_STATUS_UPTODATE, $plugininfo->get_status());
1034
        $this->assertEquals('fake_fullfeatured', $plugininfo->get_parent_plugin());
1035
        $this->assertNotEmpty($plugininfo->versiondisk);
1036
        $this->assertStringContainsString('/fulldeletedsubtype/', $plugininfo->get_dir());
1037
 
1038
        $this->assertArrayNotHasKey('demo', $pluginman->get_plugins_of_type('fulldeletedsubtype'));
1039
        $this->assertArrayHasKey('demo', $pluginman->get_plugins_of_type('fulldeletedsubtype', true));
1040
 
1041
        $this->assertFalse($pluginman->get_parent_of_subplugin('fulldeletedsubtype'));
1042
        $this->assertEquals('fake_fullfeatured', $pluginman->get_parent_of_subplugin('fulldeletedsubtype', true));
1043
 
1044
        // Deprecated plugins included in the following.
1045
        $this->assertArrayHasKey('demo', $pluginman->get_present_plugins('fulldeletedsubtype')); // Plugins on disk.
1046
        $this->assertArrayHasKey('demo', $pluginman->get_installed_plugins('fulldeletedsubtype')); // Plugins with DB config.
1047
        $this->assertInstanceOf(\fake_fullfeatured\plugininfo\fulldeletedsubtype::class,
1048
            $pluginman->get_plugin_info('fulldeletedsubtype_demo'));
1049
        $this->assertIsString($pluginman->get_plugintype_root('fulldeletedsubtype'));
1050
        $this->assertTrue($pluginman->can_uninstall_plugin('fulldeletedsubtype_demo'));
1051
        $uninstallurl = $pluginman->get_uninstall_url('fulldeletedsubtype_demo');
1052
        $this->assertInstanceOf(\moodle_url::class, $uninstallurl);
1053
        $this->assertEquals('fulldeletedsubtype_demo', $uninstallurl->param('uninstall'));
1054
 
1055
        // Included, but there is no string support for deleted plugin types.
1056
        // Without string support, the type name defaults to the plugin type,
1057
        // while plugin name is set in \core\plugininfo\base::init_is_deprecated().
1058
        $this->assertEquals('demo', $pluginman->plugin_name('fulldeletedsubtype_demo'));
1059
        $this->assertEquals('fulldeletedsubtype', $pluginman->plugintype_name('fulldeletedsubtype'));
1060
        $this->assertEquals('fulldeletedsubtype', $pluginman->plugintype_name_plural('fulldeletedsubtype'));
1061
    }
1 efrain 1062
}