MDL-36466 cache: implemented functionality to disable the bulk of the cache API
[moodle.git] / cache / tests / locallib_test.php
CommitLineData
42f2c59e
SH
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/**
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 */
28
29defined('MOODLE_INTERNAL') || die();
30
31// Include the necessary evils.
32global $CFG;
33require_once($CFG->dirroot.'/cache/locallib.php');
34require_once($CFG->dirroot.'/cache/tests/fixtures/lib.php');
35
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 */
42class cache_config_writer_phpunit_tests extends advanced_testcase {
43
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 }
52
3680c61a
SH
53 /**
54 * Final task is to reset the cache system
55 */
56 public static function tearDownAfterClass() {
57 parent::tearDownAfterClass();
58 cache_factory::reset();
59 }
60
42f2c59e
SH
61 /**
62 * Test getting an instance. Pretty basic.
63 */
64 public function test_instance() {
65 $config = cache_config_writer::instance();
66 $this->assertInstanceOf('cache_config_writer', $config);
67 }
68
69 /**
70 * Test the default configuration.
71 */
72 public function test_default_configuration() {
73 $config = cache_config_writer::instance();
74
75 // First check stores.
76 $stores = $config->get_all_stores();
77 $hasapplication = false;
78 $hassession = false;
79 $hasrequest = false;
80 foreach ($stores as $store) {
81 // Check the required keys.
82 $this->assertArrayHasKey('name', $store);
83 $this->assertArrayHasKey('plugin', $store);
84 $this->assertArrayHasKey('modes', $store);
85 $this->assertArrayHasKey('default', $store);
86 // Check the mode, we need at least one default store of each mode.
87 if (!empty($store['default'])) {
88 if ($store['modes'] & cache_store::MODE_APPLICATION) {
89 $hasapplication = true;
90 }
91 if ($store['modes'] & cache_store::MODE_SESSION) {
92 $hassession = true;
93 }
94 if ($store['modes'] & cache_store::MODE_REQUEST) {
95 $hasrequest = true;
96 }
97 }
98 }
99 $this->assertTrue($hasapplication, 'There is no default application cache store.');
100 $this->assertTrue($hassession, 'There is no default session cache store.');
101 $this->assertTrue($hasrequest, 'There is no default request cache store.');
102
103 // Next check the definitions.
104 $definitions = $config->get_definitions();
105 $eventinvalidation = false;
106 foreach ($definitions as $definition) {
107 // Check the required keys.
108 $this->assertArrayHasKey('mode', $definition);
109 $this->assertArrayHasKey('component', $definition);
110 $this->assertArrayHasKey('area', $definition);
111 if ($definition['component'] === 'core' && $definition['area'] === 'eventinvalidation') {
112 $eventinvalidation = true;
113 }
114 }
115 $this->assertTrue($eventinvalidation, 'Missing the event invalidation definition.');
116
117 // Next mode mappings
118 $mappings = $config->get_mode_mappings();
119 $hasapplication = false;
120 $hassession = false;
121 $hasrequest = false;
122 foreach ($mappings as $mode) {
123 // Check the required keys.
124 $this->assertArrayHasKey('mode', $mode);
125 $this->assertArrayHasKey('store', $mode);
126
127 if ($mode['mode'] === cache_store::MODE_APPLICATION) {
128 $hasapplication = true;
129 }
130 if ($mode['mode'] === cache_store::MODE_SESSION) {
131 $hassession = true;
132 }
133 if ($mode['mode'] === cache_store::MODE_REQUEST) {
134 $hasrequest = true;
135 }
136 }
137 $this->assertTrue($hasapplication, 'There is no mapping for the application mode.');
138 $this->assertTrue($hassession, 'There is no mapping for the session mode.');
139 $this->assertTrue($hasrequest, 'There is no mapping for the request mode.');
140
141 // Finally check config locks
142 $locks = $config->get_locks();
143 foreach ($locks as $lock) {
144 $this->assertArrayHasKey('name', $lock);
145 $this->assertArrayHasKey('type', $lock);
146 $this->assertArrayHasKey('default', $lock);
147 }
148 // There has to be at least the default lock.
149 $this->assertTrue(count($locks) > 0);
150 }
151
152 /**
153 * Test updating the definitions.
154 */
155 public function test_update_definitions() {
156 $config = cache_config_writer::instance();
157 $earlydefinitions = $config->get_definitions();
158 unset($config);
159 cache_factory::reset();
160 cache_config_writer::update_definitions();
161
162 $config = cache_config_writer::instance();
163 $latedefinitions = $config->get_definitions();
164
165 $this->assertSame($latedefinitions, $earlydefinitions);
166 }
167
168 /**
169 * Test adding/editing/deleting store instances.
170 */
171 public function test_add_edit_delete_plugin_instance() {
172 $config = cache_config_writer::instance();
173 $this->assertArrayNotHasKey('addplugintest', $config->get_all_stores());
174 $this->assertArrayNotHasKey('addplugintestwlock', $config->get_all_stores());
175 // Add a default file instance.
26ce56fd 176 $config->add_store_instance('addplugintest', 'file');
42f2c59e
SH
177
178 cache_factory::reset();
179 $config = cache_config_writer::instance();
180 $this->assertArrayHasKey('addplugintest', $config->get_all_stores());
181
182 // Add a store with a lock described.
26ce56fd 183 $config->add_store_instance('addplugintestwlock', 'file', array('lock' => 'default_file_lock'));
42f2c59e
SH
184 $this->assertArrayHasKey('addplugintestwlock', $config->get_all_stores());
185
26ce56fd 186 $config->delete_store_instance('addplugintest');
42f2c59e
SH
187 $this->assertArrayNotHasKey('addplugintest', $config->get_all_stores());
188 $this->assertArrayHasKey('addplugintestwlock', $config->get_all_stores());
189
26ce56fd 190 $config->delete_store_instance('addplugintestwlock');
42f2c59e
SH
191 $this->assertArrayNotHasKey('addplugintest', $config->get_all_stores());
192 $this->assertArrayNotHasKey('addplugintestwlock', $config->get_all_stores());
193
194 // Add a default file instance.
26ce56fd 195 $config->add_store_instance('storeconfigtest', 'file', array('test' => 'a', 'one' => 'two'));
42f2c59e
SH
196 $stores = $config->get_all_stores();
197 $this->assertArrayHasKey('storeconfigtest', $stores);
198 $this->assertArrayHasKey('configuration', $stores['storeconfigtest']);
199 $this->assertArrayHasKey('test', $stores['storeconfigtest']['configuration']);
200 $this->assertArrayHasKey('one', $stores['storeconfigtest']['configuration']);
201 $this->assertEquals('a', $stores['storeconfigtest']['configuration']['test']);
202 $this->assertEquals('two', $stores['storeconfigtest']['configuration']['one']);
203
26ce56fd 204 $config->edit_store_instance('storeconfigtest', 'file', array('test' => 'b', 'one' => 'three'));
42f2c59e
SH
205 $stores = $config->get_all_stores();
206 $this->assertArrayHasKey('storeconfigtest', $stores);
207 $this->assertArrayHasKey('configuration', $stores['storeconfigtest']);
208 $this->assertArrayHasKey('test', $stores['storeconfigtest']['configuration']);
209 $this->assertArrayHasKey('one', $stores['storeconfigtest']['configuration']);
210 $this->assertEquals('b', $stores['storeconfigtest']['configuration']['test']);
211 $this->assertEquals('three', $stores['storeconfigtest']['configuration']['one']);
212
26ce56fd 213 $config->delete_store_instance('storeconfigtest');
42f2c59e
SH
214
215 try {
26ce56fd 216 $config->delete_store_instance('default_application');
42f2c59e
SH
217 $this->fail('Default store deleted. This should not be possible!');
218 } catch (Exception $e) {
219 $this->assertInstanceOf('cache_exception', $e);
220 }
221
222 try {
26ce56fd 223 $config->delete_store_instance('some_crazy_store');
42f2c59e
SH
224 $this->fail('You should not be able to delete a store that does not exist.');
225 } catch (Exception $e) {
226 $this->assertInstanceOf('cache_exception', $e);
227 }
228
229 try {
230 // Try with a plugin that does not exist.
26ce56fd 231 $config->add_store_instance('storeconfigtest', 'shallowfail', array('test' => 'a', 'one' => 'two'));
42f2c59e
SH
232 $this->fail('You should not be able to add an instance of a store that does not exist.');
233 } catch (Exception $e) {
234 $this->assertInstanceOf('cache_exception', $e);
235 }
236 }
237
238 /**
239 * Test setting some mode mappings.
240 */
241 public function test_set_mode_mappings() {
242 $config = cache_config_writer::instance();
26ce56fd 243 $this->assertTrue($config->add_store_instance('setmodetest', 'file'));
42f2c59e
SH
244 $this->assertTrue($config->set_mode_mappings(array(
245 cache_store::MODE_APPLICATION => array('setmodetest', 'default_application'),
246 cache_store::MODE_SESSION => array('default_session'),
247 cache_store::MODE_REQUEST => array('default_request'),
248 )));
249 $mappings = $config->get_mode_mappings();
250 $setmodetestfound = false;
251 foreach ($mappings as $mapping) {
252 if ($mapping['store'] == 'setmodetest' && $mapping['mode'] == cache_store::MODE_APPLICATION) {
253 $setmodetestfound = true;
254 }
255 }
256 $this->assertTrue($setmodetestfound, 'Set mapping did not work as expected.');
257 }
258
259 /**
260 * Test setting some definition mappings.
261 */
262 public function test_set_definition_mappings() {
263 $config = cache_config_phpunittest::instance(true);
264 $config->phpunit_add_definition('phpunit/testdefinition', array(
265 'mode' => cache_store::MODE_APPLICATION,
266 'component' => 'phpunit',
267 'area' => 'testdefinition'
268 ));
269
270 $config = cache_config_writer::instance();
26ce56fd 271 $this->assertTrue($config->add_store_instance('setdefinitiontest', 'file'));
42f2c59e
SH
272 $this->assertInternalType('array', $config->get_definition_by_id('phpunit/testdefinition'));
273 $config->set_definition_mappings('phpunit/testdefinition', array('setdefinitiontest', 'default_application'));
274
275 try {
276 $config->set_definition_mappings('phpunit/testdefinition', array('something that does not exist'));
277 $this->fail('You should not be able to set a mapping for a store that does not exist.');
278 } catch (Exception $e) {
279 $this->assertInstanceOf('coding_exception', $e);
280 }
281
282 try {
283 $config->set_definition_mappings('something/crazy', array('setdefinitiontest'));
284 $this->fail('You should not be able to set a mapping for a definition that does not exist.');
285 } catch (Exception $e) {
286 $this->assertInstanceOf('coding_exception', $e);
287 }
288 }
289}
290
291/**
292 * PHPunit tests for the cache API and in particular the cache_administration_helper
293 *
294 * @copyright 2012 Sam Hemelryk
295 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
296 */
297class cache_administration_helper_phpunit_tests extends advanced_testcase {
298
299 /**
300 * Set things back to the default before each test.
301 */
302 public function setUp() {
303 parent::setUp();
304 cache_factory::reset();
305 cache_config_phpunittest::create_default_configuration();
306 }
307
3680c61a
SH
308 /**
309 * Final task is to reset the cache system
310 */
311 public static function tearDownAfterClass() {
312 parent::tearDownAfterClass();
313 cache_factory::reset();
314 }
315
42f2c59e
SH
316 /**
317 * Test the numerous summaries the helper can produce.
318 */
319 public function test_get_summaries() {
320 // First the preparation.
321 $config = cache_config_writer::instance();
26ce56fd 322 $this->assertTrue($config->add_store_instance('summariesstore', 'file'));
42f2c59e
SH
323 $config->set_definition_mappings('core/eventinvalidation', array('summariesstore'));
324 $this->assertTrue($config->set_mode_mappings(array(
325 cache_store::MODE_APPLICATION => array('summariesstore'),
326 cache_store::MODE_SESSION => array('default_session'),
327 cache_store::MODE_REQUEST => array('default_request'),
328 )));
329
26ce56fd 330 $storesummaries = cache_administration_helper::get_store_instance_summaries();
42f2c59e
SH
331 $this->assertInternalType('array', $storesummaries);
332 $this->assertArrayHasKey('summariesstore', $storesummaries);
333 $summary = $storesummaries['summariesstore'];
334 // Check the keys
335 $this->assertArrayHasKey('name', $summary);
336 $this->assertArrayHasKey('plugin', $summary);
337 $this->assertArrayHasKey('default', $summary);
338 $this->assertArrayHasKey('isready', $summary);
339 $this->assertArrayHasKey('requirementsmet', $summary);
340 $this->assertArrayHasKey('mappings', $summary);
341 $this->assertArrayHasKey('modes', $summary);
342 $this->assertArrayHasKey('supports', $summary);
343 // Check the important/known values
344 $this->assertEquals('summariesstore', $summary['name']);
345 $this->assertEquals('file', $summary['plugin']);
346 $this->assertEquals(0, $summary['default']);
347 $this->assertEquals(1, $summary['isready']);
348 $this->assertEquals(1, $summary['requirementsmet']);
349 $this->assertEquals(1, $summary['mappings']);
350
351 $definitionsummaries = cache_administration_helper::get_definition_summaries();
352 $this->assertInternalType('array', $definitionsummaries);
353 $this->assertArrayHasKey('core/eventinvalidation', $definitionsummaries);
354 $summary = $definitionsummaries['core/eventinvalidation'];
355 // Check the keys
356 $this->assertArrayHasKey('id', $summary);
357 $this->assertArrayHasKey('name', $summary);
358 $this->assertArrayHasKey('mode', $summary);
359 $this->assertArrayHasKey('component', $summary);
360 $this->assertArrayHasKey('area', $summary);
361 $this->assertArrayHasKey('mappings', $summary);
362 // Check the important/known values
363 $this->assertEquals('core/eventinvalidation', $summary['id']);
364 $this->assertInstanceOf('lang_string', $summary['name']);
365 $this->assertEquals(cache_store::MODE_APPLICATION, $summary['mode']);
366 $this->assertEquals('core', $summary['component']);
367 $this->assertEquals('eventinvalidation', $summary['area']);
368 $this->assertInternalType('array', $summary['mappings']);
369 $this->assertContains('summariesstore', $summary['mappings']);
370
26ce56fd 371 $pluginsummaries = cache_administration_helper::get_store_plugin_summaries();
42f2c59e
SH
372 $this->assertInternalType('array', $pluginsummaries);
373 $this->assertArrayHasKey('file', $pluginsummaries);
374 $summary = $pluginsummaries['file'];
375 // Check the keys
376 $this->assertArrayHasKey('name', $summary);
377 $this->assertArrayHasKey('requirementsmet', $summary);
378 $this->assertArrayHasKey('instances', $summary);
379 $this->assertArrayHasKey('modes', $summary);
380 $this->assertArrayHasKey('supports', $summary);
381 $this->assertArrayHasKey('canaddinstance', $summary);
382
383 $locksummaries = cache_administration_helper::get_lock_summaries();
384 $this->assertInternalType('array', $locksummaries);
385 $this->assertTrue(count($locksummaries) > 0);
386
387 $mappings = cache_administration_helper::get_default_mode_stores();
388 $this->assertInternalType('array', $mappings);
389 $this->assertCount(3, $mappings);
390 $this->assertArrayHasKey(cache_store::MODE_APPLICATION, $mappings);
391 $this->assertInternalType('array', $mappings[cache_store::MODE_APPLICATION]);
392 $this->assertContains('summariesstore', $mappings[cache_store::MODE_APPLICATION]);
393
394 $potentials = cache_administration_helper::get_definition_store_options('core', 'eventinvalidation');
395 $this->assertInternalType('array', $potentials); // Currently used, suitable, default
396 $this->assertCount(3, $potentials);
397 $this->assertArrayHasKey('summariesstore', $potentials[0]);
398 $this->assertArrayHasKey('summariesstore', $potentials[1]);
399 $this->assertArrayHasKey('default_application', $potentials[1]);
400 }
401
402 /**
403 * Test instantiating an add store form.
404 */
405 public function test_get_add_store_form() {
406 $form = cache_administration_helper::get_add_store_form('file');
407 $this->assertInstanceOf('moodleform', $form);
408
409 try {
410 $form = cache_administration_helper::get_add_store_form('somethingstupid');
411 $this->fail('You should not be able to create an add form for a store plugin that does not exist.');
412 } catch (moodle_exception $e) {
413 $this->assertInstanceOf('coding_exception', $e, 'Needs to be: ' .get_class($e)." ::: ".$e->getMessage());
414 }
415 }
416
417 /**
418 * Test instantiating a form to edit a store instance.
419 */
420 public function test_get_edit_store_form() {
421 $config = cache_config_writer::instance();
26ce56fd 422 $this->assertTrue($config->add_store_instance('summariesstore', 'file'));
42f2c59e
SH
423
424 $form = cache_administration_helper::get_edit_store_form('file', 'summariesstore');
425 $this->assertInstanceOf('moodleform', $form);
426
427 try {
428 $form = cache_administration_helper::get_edit_store_form('somethingstupid', 'moron');
429 $this->fail('You should not be able to create an edit form for a store plugin that does not exist.');
430 } catch (moodle_exception $e) {
431 $this->assertInstanceOf('coding_exception', $e);
432 }
433
434 try {
435 $form = cache_administration_helper::get_edit_store_form('file', 'blisters');
436 $this->fail('You should not be able to create an edit form for a store plugin that does not exist.');
437 } catch (moodle_exception $e) {
438 $this->assertInstanceOf('coding_exception', $e);
439 }
440 }
5dd68a75
SH
441
442 /**
443 * Test the hash_key functionality.
444 */
445 public function test_hash_key() {
446 global $CFG;
447
448 $currentdebugging = $CFG->debug;
449
450 $CFG->debug = E_ALL;
451
452 // First with simplekeys
453 $instance = cache_config_phpunittest::instance(true);
454 $instance->phpunit_add_definition('phpunit/hashtest', array(
455 'mode' => cache_store::MODE_APPLICATION,
456 'component' => 'phpunit',
457 'area' => 'hashtest',
458 'simplekeys' => true
459 ));
460 $factory = cache_factory::instance();
461 $definition = $factory->create_definition('phpunit', 'hashtest');
462
463 $result = cache_helper::hash_key('test', $definition);
464 $this->assertEquals('test-'.$definition->generate_single_key_prefix(), $result);
465
466 try {
467 cache_helper::hash_key('test/test', $definition);
468 $this->fail('Invalid key was allowed, you should see this.');
469 } catch (coding_exception $e) {
470 $this->assertEquals('test/test', $e->debuginfo);
471 }
472
473 // Second without simple keys
474 $instance->phpunit_add_definition('phpunit/hashtest2', array(
475 'mode' => cache_store::MODE_APPLICATION,
476 'component' => 'phpunit',
477 'area' => 'hashtest2',
478 'simplekeys' => false
479 ));
480 $definition = $factory->create_definition('phpunit', 'hashtest2');
481
482 $result = cache_helper::hash_key('test', $definition);
483 $this->assertEquals(sha1($definition->generate_single_key_prefix().'-test'), $result);
484
485 $result = cache_helper::hash_key('test/test', $definition);
486 $this->assertEquals(sha1($definition->generate_single_key_prefix().'-test/test'), $result);
487
488 $CFG->debug = $currentdebugging;
489 }
490}