MDL-25290 cache: Added unit tests for admin and fixed up identified issues
[moodle.git] / cache / tests / locallib_test.php
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/>.
17 /**
18  * PHPunit tests for the cache API and in particular things in locallib.php
19  *
20  * This file is part of Moodle's cache API, affectionately called MUC.
21  * It contains the components that are requried in order to use caching.
22  *
23  * @package    core
24  * @category   cache
25  * @copyright  2012 Sam Hemelryk
26  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
27  */
29 defined('MOODLE_INTERNAL') || die();
31 // Include the necessary evils.
32 global $CFG;
33 require_once($CFG->dirroot.'/cache/locallib.php');
34 require_once($CFG->dirroot.'/cache/tests/fixtures/lib.php');
36 /**
37  * PHPunit tests for the cache API and in particular the cache config writer.
38  *
39  * @copyright  2012 Sam Hemelryk
40  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
41  */
42 class cache_config_writer_phpunit_tests extends advanced_testcase {
44     /**
45      * Set things back to the default before each test.
46      */
47     public function setUp() {
48         parent::setUp();
49         cache_factory::reset();
50         cache_config_phpunittest::create_default_configuration();
51     }
53     /**
54      * Test getting an instance. Pretty basic.
55      */
56     public function test_instance() {
57         $config = cache_config_writer::instance();
58         $this->assertInstanceOf('cache_config_writer', $config);
59     }
61     /**
62      * Test the default configuration.
63      */
64     public function test_default_configuration() {
65         $config = cache_config_writer::instance();
67         // First check stores.
68         $stores = $config->get_all_stores();
69         $hasapplication = false;
70         $hassession = false;
71         $hasrequest = false;
72         foreach ($stores as $store) {
73             // Check the required keys.
74             $this->assertArrayHasKey('name', $store);
75             $this->assertArrayHasKey('plugin', $store);
76             $this->assertArrayHasKey('modes', $store);
77             $this->assertArrayHasKey('default', $store);
78             // Check the mode, we need at least one default store of each mode.
79             if (!empty($store['default'])) {
80                 if ($store['modes'] & cache_store::MODE_APPLICATION) {
81                     $hasapplication = true;
82                 }
83                 if ($store['modes'] & cache_store::MODE_SESSION) {
84                     $hassession = true;
85                 }
86                 if ($store['modes'] & cache_store::MODE_REQUEST) {
87                     $hasrequest = true;
88                 }
89             }
90         }
91         $this->assertTrue($hasapplication, 'There is no default application cache store.');
92         $this->assertTrue($hassession, 'There is no default session cache store.');
93         $this->assertTrue($hasrequest, 'There is no default request cache store.');
95         // Next check the definitions.
96         $definitions = $config->get_definitions();
97         $eventinvalidation = false;
98         foreach ($definitions as $definition) {
99             // Check the required keys.
100             $this->assertArrayHasKey('mode', $definition);
101             $this->assertArrayHasKey('component', $definition);
102             $this->assertArrayHasKey('area', $definition);
103             if ($definition['component'] === 'core' && $definition['area'] === 'eventinvalidation') {
104                 $eventinvalidation = true;
105             }
106         }
107         $this->assertTrue($eventinvalidation, 'Missing the event invalidation definition.');
109         // Next mode mappings
110         $mappings = $config->get_mode_mappings();
111         $hasapplication = false;
112         $hassession = false;
113         $hasrequest = false;
114         foreach ($mappings as $mode) {
115             // Check the required keys.
116             $this->assertArrayHasKey('mode', $mode);
117             $this->assertArrayHasKey('store', $mode);
119             if ($mode['mode'] === cache_store::MODE_APPLICATION) {
120                 $hasapplication = true;
121             }
122             if ($mode['mode'] === cache_store::MODE_SESSION) {
123                 $hassession = true;
124             }
125             if ($mode['mode'] === cache_store::MODE_REQUEST) {
126                 $hasrequest = true;
127             }
128         }
129         $this->assertTrue($hasapplication, 'There is no mapping for the application mode.');
130         $this->assertTrue($hassession, 'There is no mapping for the session mode.');
131         $this->assertTrue($hasrequest, 'There is no mapping for the request mode.');
133         // Finally check config locks
134         $locks = $config->get_locks();
135         foreach ($locks as $lock) {
136             $this->assertArrayHasKey('name', $lock);
137             $this->assertArrayHasKey('type', $lock);
138             $this->assertArrayHasKey('default', $lock);
139         }
140         // There has to be at least the default lock.
141         $this->assertTrue(count($locks) > 0);
142     }
144     /**
145      * Test updating the definitions.
146      */
147     public function test_update_definitions() {
148         $config = cache_config_writer::instance();
149         $earlydefinitions = $config->get_definitions();
150         unset($config);
151         cache_factory::reset();
152         cache_config_writer::update_definitions();
154         $config = cache_config_writer::instance();
155         $latedefinitions = $config->get_definitions();
157         $this->assertSame($latedefinitions, $earlydefinitions);
158     }
160     /**
161      * Test adding/editing/deleting store instances.
162      */
163     public function test_add_edit_delete_plugin_instance() {
164         $config = cache_config_writer::instance();
165         $this->assertArrayNotHasKey('addplugintest', $config->get_all_stores());
166         $this->assertArrayNotHasKey('addplugintestwlock', $config->get_all_stores());
167         // Add a default file instance.
168         $config->add_plugin_instance('addplugintest', 'file');
170         cache_factory::reset();
171         $config = cache_config_writer::instance();
172         $this->assertArrayHasKey('addplugintest', $config->get_all_stores());
174         // Add a store with a lock described.
175         $config->add_plugin_instance('addplugintestwlock', 'file', array('lock' => 'default_file_lock'));
176         $this->assertArrayHasKey('addplugintestwlock', $config->get_all_stores());
178         $config->delete_store('addplugintest');
179         $this->assertArrayNotHasKey('addplugintest', $config->get_all_stores());
180         $this->assertArrayHasKey('addplugintestwlock', $config->get_all_stores());
182         $config->delete_store('addplugintestwlock');
183         $this->assertArrayNotHasKey('addplugintest', $config->get_all_stores());
184         $this->assertArrayNotHasKey('addplugintestwlock', $config->get_all_stores());
186         // Add a default file instance.
187         $config->add_plugin_instance('storeconfigtest', 'file', array('test' => 'a', 'one' => 'two'));
188         $stores = $config->get_all_stores();
189         $this->assertArrayHasKey('storeconfigtest', $stores);
190         $this->assertArrayHasKey('configuration', $stores['storeconfigtest']);
191         $this->assertArrayHasKey('test', $stores['storeconfigtest']['configuration']);
192         $this->assertArrayHasKey('one', $stores['storeconfigtest']['configuration']);
193         $this->assertEquals('a', $stores['storeconfigtest']['configuration']['test']);
194         $this->assertEquals('two', $stores['storeconfigtest']['configuration']['one']);
196         $config->edit_plugin_instance('storeconfigtest', 'file', array('test' => 'b', 'one' => 'three'));
197         $stores = $config->get_all_stores();
198         $this->assertArrayHasKey('storeconfigtest', $stores);
199         $this->assertArrayHasKey('configuration', $stores['storeconfigtest']);
200         $this->assertArrayHasKey('test', $stores['storeconfigtest']['configuration']);
201         $this->assertArrayHasKey('one', $stores['storeconfigtest']['configuration']);
202         $this->assertEquals('b', $stores['storeconfigtest']['configuration']['test']);
203         $this->assertEquals('three', $stores['storeconfigtest']['configuration']['one']);
205         $config->delete_store('storeconfigtest');
207         try {
208             $config->delete_store('default_application');
209             $this->fail('Default store deleted. This should not be possible!');
210         } catch (Exception $e) {
211             $this->assertInstanceOf('cache_exception', $e);
212         }
214         try {
215             $config->delete_store('some_crazy_store');
216             $this->fail('You should not be able to delete a store that does not exist.');
217         } catch (Exception $e) {
218             $this->assertInstanceOf('cache_exception', $e);
219         }
221         try {
222             // Try with a plugin that does not exist.
223             $config->add_plugin_instance('storeconfigtest', 'shallowfail', array('test' => 'a', 'one' => 'two'));
224             $this->fail('You should not be able to add an instance of a store that does not exist.');
225         } catch (Exception $e) {
226             $this->assertInstanceOf('cache_exception', $e);
227         }
228     }
230     /**
231      * Test setting some mode mappings.
232      */
233     public function test_set_mode_mappings() {
234         $config = cache_config_writer::instance();
235         $this->assertTrue($config->add_plugin_instance('setmodetest', 'file'));
236         $this->assertTrue($config->set_mode_mappings(array(
237             cache_store::MODE_APPLICATION => array('setmodetest', 'default_application'),
238             cache_store::MODE_SESSION => array('default_session'),
239             cache_store::MODE_REQUEST => array('default_request'),
240         )));
241         $mappings = $config->get_mode_mappings();
242         $setmodetestfound = false;
243         foreach ($mappings as $mapping) {
244             if ($mapping['store'] == 'setmodetest' && $mapping['mode'] == cache_store::MODE_APPLICATION) {
245                 $setmodetestfound = true;
246             }
247         }
248         $this->assertTrue($setmodetestfound, 'Set mapping did not work as expected.');
249     }
251     /**
252      * Test setting some definition mappings.
253      */
254     public function test_set_definition_mappings() {
255         $config = cache_config_phpunittest::instance(true);
256         $config->phpunit_add_definition('phpunit/testdefinition', array(
257             'mode' => cache_store::MODE_APPLICATION,
258             'component' => 'phpunit',
259             'area' => 'testdefinition'
260         ));
262         $config = cache_config_writer::instance();
263         $this->assertTrue($config->add_plugin_instance('setdefinitiontest', 'file'));
264         $this->assertInternalType('array', $config->get_definition_by_id('phpunit/testdefinition'));
265         $config->set_definition_mappings('phpunit/testdefinition', array('setdefinitiontest', 'default_application'));
267         try {
268             $config->set_definition_mappings('phpunit/testdefinition', array('something that does not exist'));
269             $this->fail('You should not be able to set a mapping for a store that does not exist.');
270         } catch (Exception $e) {
271             $this->assertInstanceOf('coding_exception', $e);
272         }
274         try {
275             $config->set_definition_mappings('something/crazy', array('setdefinitiontest'));
276             $this->fail('You should not be able to set a mapping for a definition that does not exist.');
277         } catch (Exception $e) {
278             $this->assertInstanceOf('coding_exception', $e);
279         }
280     }
283 /**
284  * PHPunit tests for the cache API and in particular the cache_administration_helper
285  *
286  * @copyright  2012 Sam Hemelryk
287  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
288  */
289 class cache_administration_helper_phpunit_tests extends advanced_testcase {
291     /**
292      * Set things back to the default before each test.
293      */
294     public function setUp() {
295         parent::setUp();
296         cache_factory::reset();
297         cache_config_phpunittest::create_default_configuration();
298     }
300     /**
301      * Test the numerous summaries the helper can produce.
302      */
303     public function test_get_summaries() {
304         // First the preparation.
305         $config = cache_config_writer::instance();
306         $this->assertTrue($config->add_plugin_instance('summariesstore', 'file'));
307         $config->set_definition_mappings('core/eventinvalidation', array('summariesstore'));
308         $this->assertTrue($config->set_mode_mappings(array(
309             cache_store::MODE_APPLICATION => array('summariesstore'),
310             cache_store::MODE_SESSION => array('default_session'),
311             cache_store::MODE_REQUEST => array('default_request'),
312         )));
314         $storesummaries = cache_administration_helper::get_store_summaries();
315         $this->assertInternalType('array', $storesummaries);
316         $this->assertArrayHasKey('summariesstore', $storesummaries);
317         $summary = $storesummaries['summariesstore'];
318         // Check the keys
319         $this->assertArrayHasKey('name', $summary);
320         $this->assertArrayHasKey('plugin', $summary);
321         $this->assertArrayHasKey('default', $summary);
322         $this->assertArrayHasKey('isready', $summary);
323         $this->assertArrayHasKey('requirementsmet', $summary);
324         $this->assertArrayHasKey('mappings', $summary);
325         $this->assertArrayHasKey('modes', $summary);
326         $this->assertArrayHasKey('supports', $summary);
327         // Check the important/known values
328         $this->assertEquals('summariesstore', $summary['name']);
329         $this->assertEquals('file', $summary['plugin']);
330         $this->assertEquals(0, $summary['default']);
331         $this->assertEquals(1, $summary['isready']);
332         $this->assertEquals(1, $summary['requirementsmet']);
333         $this->assertEquals(1, $summary['mappings']);
335         $definitionsummaries = cache_administration_helper::get_definition_summaries();
336         $this->assertInternalType('array', $definitionsummaries);
337         $this->assertArrayHasKey('core/eventinvalidation', $definitionsummaries);
338         $summary = $definitionsummaries['core/eventinvalidation'];
339         // Check the keys
340         $this->assertArrayHasKey('id', $summary);
341         $this->assertArrayHasKey('name', $summary);
342         $this->assertArrayHasKey('mode', $summary);
343         $this->assertArrayHasKey('component', $summary);
344         $this->assertArrayHasKey('area', $summary);
345         $this->assertArrayHasKey('mappings', $summary);
346         // Check the important/known values
347         $this->assertEquals('core/eventinvalidation', $summary['id']);
348         $this->assertInstanceOf('lang_string', $summary['name']);
349         $this->assertEquals(cache_store::MODE_APPLICATION, $summary['mode']);
350         $this->assertEquals('core', $summary['component']);
351         $this->assertEquals('eventinvalidation', $summary['area']);
352         $this->assertInternalType('array', $summary['mappings']);
353         $this->assertContains('summariesstore', $summary['mappings']);
355         $pluginsummaries = cache_administration_helper::get_plugin_summaries();
356         $this->assertInternalType('array', $pluginsummaries);
357         $this->assertArrayHasKey('file', $pluginsummaries);
358         $summary = $pluginsummaries['file'];
359         // Check the keys
360         $this->assertArrayHasKey('name', $summary);
361         $this->assertArrayHasKey('requirementsmet', $summary);
362         $this->assertArrayHasKey('instances', $summary);
363         $this->assertArrayHasKey('modes', $summary);
364         $this->assertArrayHasKey('supports', $summary);
365         $this->assertArrayHasKey('canaddinstance', $summary);
367         $locksummaries = cache_administration_helper::get_lock_summaries();
368         $this->assertInternalType('array', $locksummaries);
369         $this->assertTrue(count($locksummaries) > 0);
371         $mappings = cache_administration_helper::get_default_mode_stores();
372         $this->assertInternalType('array', $mappings);
373         $this->assertCount(3, $mappings);
374         $this->assertArrayHasKey(cache_store::MODE_APPLICATION, $mappings);
375         $this->assertInternalType('array', $mappings[cache_store::MODE_APPLICATION]);
376         $this->assertContains('summariesstore', $mappings[cache_store::MODE_APPLICATION]);
378         $potentials = cache_administration_helper::get_definition_store_options('core', 'eventinvalidation');
379         $this->assertInternalType('array', $potentials); // Currently used, suitable, default
380         $this->assertCount(3, $potentials);
381         $this->assertArrayHasKey('summariesstore', $potentials[0]);
382         $this->assertArrayHasKey('summariesstore', $potentials[1]);
383         $this->assertArrayHasKey('default_application', $potentials[1]);
384     }
386     /**
387      * Test instantiating an add store form.
388      */
389     public function test_get_add_store_form() {
390         $form = cache_administration_helper::get_add_store_form('file');
391         $this->assertInstanceOf('moodleform', $form);
393         try {
394             $form = cache_administration_helper::get_add_store_form('somethingstupid');
395             $this->fail('You should not be able to create an add form for a store plugin that does not exist.');
396         } catch (moodle_exception $e) {
397             $this->assertInstanceOf('coding_exception', $e, 'Needs to be: ' .get_class($e)." ::: ".$e->getMessage());
398         }
399     }
401     /**
402      * Test instantiating a form to edit a store instance.
403      */
404     public function test_get_edit_store_form() {
405         $config = cache_config_writer::instance();
406         $this->assertTrue($config->add_plugin_instance('summariesstore', 'file'));
408         $form = cache_administration_helper::get_edit_store_form('file', 'summariesstore');
409         $this->assertInstanceOf('moodleform', $form);
411         try {
412             $form = cache_administration_helper::get_edit_store_form('somethingstupid', 'moron');
413             $this->fail('You should not be able to create an edit form for a store plugin that does not exist.');
414         } catch (moodle_exception $e) {
415             $this->assertInstanceOf('coding_exception', $e);
416         }
418         try {
419             $form = cache_administration_helper::get_edit_store_form('file', 'blisters');
420             $this->fail('You should not be able to create an edit form for a store plugin that does not exist.');
421         } catch (moodle_exception $e) {
422             $this->assertInstanceOf('coding_exception', $e);
423         }
424     }