Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 3.9.x will end* 10 May 2021 (12 months).
  • Bug fixes for security issues in 3.9.x will end* 8 May 2023 (36 months).
  • PHP version: minimum PHP 7.2.0 Note: minimum PHP version has increased since Moodle 3.8. PHP 7.3.x and 7.4.x are supported too.

Differences Between: [Versions 39 and 310] [Versions 39 and 311] [Versions 39 and 400] [Versions 39 and 401] [Versions 39 and 402] [Versions 39 and 403]

   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
  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  
  29  defined('MOODLE_INTERNAL') || die();
  30  
  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');
  35  
  36  /**
  37   * PHPunit tests for the cache API
  38   *
  39   * @copyright  2012 Sam Hemelryk
  40   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  41   */
  42  class core_cache_testcase 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_testing::create_default_configuration();
  51      }
  52  
  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  
  61      /**
  62       * Returns the expected application cache store.
  63       * @return string
  64       */
  65      protected function get_expected_application_cache_store() {
  66          global $CFG;
  67          $expected = 'cachestore_file';
  68  
  69          // Verify if we are using any of the available ways to use a different application store within tests.
  70          if (defined('TEST_CACHE_USING_APPLICATION_STORE') && preg_match('#[a-zA-Z][a-zA-Z0-9_]*#', TEST_CACHE_USING_APPLICATION_STORE)) {
  71              // 1st way. Using some of the testing servers.
  72              $expected = 'cachestore_'.(string)TEST_CACHE_USING_APPLICATION_STORE;
  73  
  74          } else if (defined('TEST_CACHE_USING_ALT_CACHE_CONFIG_PATH') && TEST_CACHE_USING_ALT_CACHE_CONFIG_PATH && !empty($CFG->altcacheconfigpath)) {
  75              // 2nd way. Using an alternative configuration.
  76              $defaultstores = cache_helper::get_stores_suitable_for_mode_default();
  77              $instance = cache_config::instance();
  78              // Iterate over defined mode mappings until we get an application one not being the default.
  79              foreach ($instance->get_mode_mappings() as $mapping) {
  80                  // If the store is not for application mode, ignore.
  81                  if ($mapping['mode'] !== cache_store::MODE_APPLICATION) {
  82                      continue;
  83                  }
  84                  // If the store matches some default mapping store name, ignore.
  85                  if (array_key_exists($mapping['store'], $defaultstores) && !empty($defaultstores[$mapping['store']]['default'])) {
  86                      continue;
  87                  }
  88                  // Arrived here, have found an application mode store not being the default mapped one (file),
  89                  // that's the one we are using in the configuration for sure.
  90                  $expected = 'cachestore_'.$mapping['store'];
  91              }
  92          }
  93  
  94          return $expected;
  95      }
  96  
  97      /**
  98       * Tests cache configuration
  99       */
 100      public function test_cache_config() {
 101          global $CFG;
 102  
 103          if (defined('TEST_CACHE_USING_ALT_CACHE_CONFIG_PATH') && TEST_CACHE_USING_ALT_CACHE_CONFIG_PATH &&
 104              !empty($CFG->altcacheconfigpath)) {
 105              // We need to skip this test - it checks the default config structure, but very likely we arn't using the
 106              // default config structure here so theres no point in running the test.
 107              $this->markTestSkipped('Skipped testing default cache config structure as alt cache path is being used.');
 108          }
 109  
 110          if (defined('TEST_CACHE_USING_APPLICATION_STORE')) {
 111              // We need to skip this test - it checks the default config structure, but very likely we arn't using the
 112              // default config structure here because we are testing against an alternative application store.
 113              $this->markTestSkipped('Skipped testing default cache config structure as alt application store is being used.');
 114          }
 115  
 116          $instance = cache_config::instance();
 117          $this->assertInstanceOf('cache_config_testing', $instance);
 118  
 119          $this->assertTrue(cache_config_testing::config_file_exists());
 120  
 121          $stores = $instance->get_all_stores();
 122          $this->assertCount(3, $stores);
 123          foreach ($stores as $name => $store) {
 124              // Check its an array.
 125              $this->assertInternalType('array', $store);
 126              // Check the name is the key.
 127              $this->assertEquals($name, $store['name']);
 128              // Check that it has been declared default.
 129              $this->assertTrue($store['default']);
 130              // Required attributes = name + plugin + configuration + modes + features.
 131              $this->assertArrayHasKey('name', $store);
 132              $this->assertArrayHasKey('plugin', $store);
 133              $this->assertArrayHasKey('configuration', $store);
 134              $this->assertArrayHasKey('modes', $store);
 135              $this->assertArrayHasKey('features', $store);
 136          }
 137  
 138          $modemappings = $instance->get_mode_mappings();
 139          $this->assertCount(3, $modemappings);
 140          $modes = array(
 141              cache_store::MODE_APPLICATION => false,
 142              cache_store::MODE_SESSION => false,
 143              cache_store::MODE_REQUEST => false,
 144          );
 145          foreach ($modemappings as $mapping) {
 146              // We expect 3 properties.
 147              $this->assertCount(3, $mapping);
 148              // Required attributes = mode + store.
 149              $this->assertArrayHasKey('mode', $mapping);
 150              $this->assertArrayHasKey('store', $mapping);
 151              // Record the mode.
 152              $modes[$mapping['mode']] = true;
 153          }
 154  
 155          // Must have the default 3 modes and no more.
 156          $this->assertCount(3, $mapping);
 157          foreach ($modes as $mode) {
 158              $this->assertTrue($mode);
 159          }
 160  
 161          $definitions = $instance->get_definitions();
 162          // The event invalidation definition is required for the cache API and must be there.
 163          $this->assertArrayHasKey('core/eventinvalidation', $definitions);
 164  
 165          $definitionmappings = $instance->get_definition_mappings();
 166          foreach ($definitionmappings as $mapping) {
 167              // Required attributes = definition + store.
 168              $this->assertArrayHasKey('definition', $mapping);
 169              $this->assertArrayHasKey('store', $mapping);
 170          }
 171      }
 172  
 173      /**
 174       * Tests for cache keys that would break on windows.
 175       */
 176      public function test_windows_nasty_keys() {
 177          $instance = cache_config_testing::instance();
 178          $instance->phpunit_add_definition('phpunit/windowskeytest', array(
 179              'mode' => cache_store::MODE_APPLICATION,
 180              'component' => 'phpunit',
 181              'area' => 'windowskeytest',
 182              'simplekeys' => true,
 183              'simpledata' => true
 184          ));
 185          $cache = cache::make('phpunit', 'windowskeytest');
 186          $this->assertTrue($cache->set('contest', 'test data 1'));
 187          $this->assertEquals('test data 1', $cache->get('contest'));
 188      }
 189  
 190      /**
 191       * Tests set_identifiers fails post cache creation.
 192       *
 193       * set_identifiers cannot be called after initial cache instantiation, as you need to create a difference cache.
 194       */
 195      public function test_set_identifiers() {
 196          $instance = cache_config_testing::instance();
 197          $instance->phpunit_add_definition('phpunit/identifier', array(
 198              'mode' => cache_store::MODE_APPLICATION,
 199              'component' => 'phpunit',
 200              'area' => 'identifier',
 201              'simplekeys' => true,
 202              'simpledata' => true,
 203              'staticacceleration' => true
 204          ));
 205          $cache = cache::make('phpunit', 'identifier', array('area'));
 206          $this->assertTrue($cache->set('contest', 'test data 1'));
 207          $this->assertEquals('test data 1', $cache->get('contest'));
 208  
 209          $this->expectException('coding_exception');
 210          $cache->set_identifiers(array());
 211      }
 212  
 213      /**
 214       * Tests the default application cache
 215       */
 216      public function test_default_application_cache() {
 217          $cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'phpunit', 'applicationtest');
 218          $this->assertInstanceOf('cache_application', $cache);
 219          $this->run_on_cache($cache);
 220  
 221          $instance = cache_config_testing::instance(true);
 222          $instance->phpunit_add_definition('phpunit/test_default_application_cache', array(
 223              'mode' => cache_store::MODE_APPLICATION,
 224              'component' => 'phpunit',
 225              'area' => 'test_default_application_cache',
 226              'staticacceleration' => true,
 227              'staticaccelerationsize' => 1
 228          ));
 229          $cache = cache::make('phpunit', 'test_default_application_cache');
 230          $this->assertInstanceOf('cache_application', $cache);
 231          $this->run_on_cache($cache);
 232      }
 233  
 234      /**
 235       * Tests the default session cache
 236       */
 237      public function test_default_session_cache() {
 238          $cache = cache::make_from_params(cache_store::MODE_SESSION, 'phpunit', 'applicationtest');
 239          $this->assertInstanceOf('cache_session', $cache);
 240          $this->run_on_cache($cache);
 241      }
 242  
 243      /**
 244       * Tests the default request cache
 245       */
 246      public function test_default_request_cache() {
 247          $cache = cache::make_from_params(cache_store::MODE_REQUEST, 'phpunit', 'applicationtest');
 248          $this->assertInstanceOf('cache_request', $cache);
 249          $this->run_on_cache($cache);
 250      }
 251  
 252      /**
 253       * Tests using a cache system when there are no stores available (who knows what the admin did to achieve this).
 254       */
 255      public function test_on_cache_without_store() {
 256          $instance = cache_config_testing::instance(true);
 257          $instance->phpunit_add_definition('phpunit/nostoretest1', array(
 258              'mode' => cache_store::MODE_APPLICATION,
 259              'component' => 'phpunit',
 260              'area' => 'nostoretest1',
 261          ));
 262          $instance->phpunit_add_definition('phpunit/nostoretest2', array(
 263              'mode' => cache_store::MODE_APPLICATION,
 264              'component' => 'phpunit',
 265              'area' => 'nostoretest2',
 266              'staticacceleration' => true
 267          ));
 268          $instance->phpunit_remove_stores();
 269  
 270          $cache = cache::make('phpunit', 'nostoretest1');
 271          $this->run_on_cache($cache);
 272  
 273          $cache = cache::make('phpunit', 'nostoretest2');
 274          $this->run_on_cache($cache);
 275      }
 276  
 277      /**
 278       * Runs a standard series of access and use tests on a cache instance.
 279       *
 280       * This function is great because we can use it to ensure all of the loaders perform exactly the same way.
 281       *
 282       * @param cache_loader $cache
 283       */
 284      protected function run_on_cache(cache_loader $cache) {
 285          $key = 'contestkey';
 286          $datascalars = array('test data', null);
 287          $dataarray = array('contest' => 'data', 'part' => 'two');
 288          $dataobject = (object)$dataarray;
 289  
 290          foreach ($datascalars as $datascalar) {
 291              $this->assertTrue($cache->purge());
 292  
 293              // Check all read methods.
 294              $this->assertFalse($cache->get($key));
 295              $this->assertFalse($cache->has($key));
 296              $result = $cache->get_many(array($key));
 297              $this->assertCount(1, $result);
 298              $this->assertFalse(reset($result));
 299              $this->assertFalse($cache->has_any(array($key)));
 300              $this->assertFalse($cache->has_all(array($key)));
 301  
 302              // Set the data.
 303              $this->assertTrue($cache->set($key, $datascalar));
 304              // Setting it more than once should be permitted.
 305              $this->assertTrue($cache->set($key, $datascalar));
 306  
 307              // Recheck the read methods.
 308              $this->assertEquals($datascalar, $cache->get($key));
 309              $this->assertTrue($cache->has($key));
 310              $result = $cache->get_many(array($key));
 311              $this->assertCount(1, $result);
 312              $this->assertEquals($datascalar, reset($result));
 313              $this->assertTrue($cache->has_any(array($key)));
 314              $this->assertTrue($cache->has_all(array($key)));
 315  
 316              // Delete it.
 317              $this->assertTrue($cache->delete($key));
 318  
 319              // Check its gone.
 320              $this->assertFalse($cache->get($key));
 321              $this->assertFalse($cache->has($key));
 322          }
 323  
 324          // Test arrays.
 325          $this->assertTrue($cache->set($key, $dataarray));
 326          $this->assertEquals($dataarray, $cache->get($key));
 327  
 328          // Test objects.
 329          $this->assertTrue($cache->set($key, $dataobject));
 330          $this->assertEquals($dataobject, $cache->get($key));
 331  
 332          $starttime = microtime(true);
 333          $specobject = new cache_phpunit_dummy_object('red', 'blue', $starttime);
 334          $this->assertTrue($cache->set($key, $specobject));
 335          $result = $cache->get($key);
 336          $this->assertInstanceOf('cache_phpunit_dummy_object', $result);
 337          $this->assertEquals('red_ptc_wfc', $result->property1);
 338          $this->assertEquals('blue_ptc_wfc', $result->property2);
 339          $this->assertGreaterThan($starttime, $result->propertytime);
 340  
 341          // Test array of objects.
 342          $specobject = new cache_phpunit_dummy_object('red', 'blue', $starttime);
 343          $data = new cacheable_object_array(array(
 344              clone($specobject),
 345              clone($specobject),
 346              clone($specobject))
 347          );
 348          $this->assertTrue($cache->set($key, $data));
 349          $result = $cache->get($key);
 350          $this->assertInstanceOf('cacheable_object_array', $result);
 351          $this->assertCount(3, $data);
 352          foreach ($result as $item) {
 353              $this->assertInstanceOf('cache_phpunit_dummy_object', $item);
 354              $this->assertEquals('red_ptc_wfc', $item->property1);
 355              $this->assertEquals('blue_ptc_wfc', $item->property2);
 356              // Ensure that wake from cache is called in all cases.
 357              $this->assertGreaterThan($starttime, $item->propertytime);
 358          }
 359  
 360          // Test set many.
 361          $cache->set_many(array('key1' => 'data1', 'key2' => 'data2', 'key3' => null));
 362          $this->assertEquals('data1', $cache->get('key1'));
 363          $this->assertEquals('data2', $cache->get('key2'));
 364          $this->assertEquals(null, $cache->get('key3'));
 365          $this->assertTrue($cache->delete('key1'));
 366          $this->assertTrue($cache->delete('key2'));
 367          $this->assertTrue($cache->delete('key3'));
 368  
 369          $cache->set_many(array(
 370              'key1' => array(1, 2, 3),
 371              'key2' => array(3, 2, 1),
 372          ));
 373          $this->assertInternalType('array', $cache->get('key1'));
 374          $this->assertInternalType('array', $cache->get('key2'));
 375          $this->assertCount(3, $cache->get('key1'));
 376          $this->assertCount(3, $cache->get('key2'));
 377          $this->assertInternalType('array', $cache->get_many(array('key1', 'key2')));
 378          $this->assertCount(2, $cache->get_many(array('key1', 'key2')));
 379          $this->assertEquals(2, $cache->delete_many(array('key1', 'key2')));
 380  
 381          // Test delete many.
 382          $this->assertTrue($cache->set('key1', 'data1'));
 383          $this->assertTrue($cache->set('key2', 'data2'));
 384          $this->assertTrue($cache->set('key3', null));
 385  
 386          $this->assertEquals('data1', $cache->get('key1'));
 387          $this->assertEquals('data2', $cache->get('key2'));
 388          $this->assertEquals(null, $cache->get('key3'));
 389  
 390          $this->assertEquals(3, $cache->delete_many(array('key1', 'key2', 'key3')));
 391  
 392          $this->assertFalse($cache->get('key1'));
 393          $this->assertFalse($cache->get('key2'));
 394          $this->assertFalse($cache->get('key3'));
 395  
 396          // Quick reference test.
 397          $obj = new stdClass;
 398          $obj->key = 'value';
 399          $ref =& $obj;
 400          $this->assertTrue($cache->set('obj', $obj));
 401  
 402          $obj->key = 'eulav';
 403          $var = $cache->get('obj');
 404          $this->assertInstanceOf('stdClass', $var);
 405          $this->assertEquals('value', $var->key);
 406  
 407          $ref->key = 'eulav';
 408          $var = $cache->get('obj');
 409          $this->assertInstanceOf('stdClass', $var);
 410          $this->assertEquals('value', $var->key);
 411  
 412          $this->assertTrue($cache->delete('obj'));
 413  
 414          // Deep reference test.
 415          $obj1 = new stdClass;
 416          $obj1->key = 'value';
 417          $obj2 = new stdClass;
 418          $obj2->key = 'test';
 419          $obj3 = new stdClass;
 420          $obj3->key = 'pork';
 421          $obj1->subobj =& $obj2;
 422          $obj2->subobj =& $obj3;
 423          $this->assertTrue($cache->set('obj', $obj1));
 424  
 425          $obj1->key = 'eulav';
 426          $obj2->key = 'tset';
 427          $obj3->key = 'krop';
 428          $var = $cache->get('obj');
 429          $this->assertInstanceOf('stdClass', $var);
 430          $this->assertEquals('value', $var->key);
 431          $this->assertInstanceOf('stdClass', $var->subobj);
 432          $this->assertEquals('test', $var->subobj->key);
 433          $this->assertInstanceOf('stdClass', $var->subobj->subobj);
 434          $this->assertEquals('pork', $var->subobj->subobj->key);
 435          $this->assertTrue($cache->delete('obj'));
 436  
 437          // Death reference test... basically we don't want this to die.
 438          $obj = new stdClass;
 439          $obj->key = 'value';
 440          $obj->self =& $obj;
 441          $this->assertTrue($cache->set('obj', $obj));
 442          $var = $cache->get('obj');
 443          $this->assertInstanceOf('stdClass', $var);
 444          $this->assertEquals('value', $var->key);
 445  
 446          // Reference test after retrieve.
 447          $obj = new stdClass;
 448          $obj->key = 'value';
 449          $this->assertTrue($cache->set('obj', $obj));
 450  
 451          $var1 = $cache->get('obj');
 452          $this->assertInstanceOf('stdClass', $var1);
 453          $this->assertEquals('value', $var1->key);
 454          $var1->key = 'eulav';
 455          $this->assertEquals('eulav', $var1->key);
 456  
 457          $var2 = $cache->get('obj');
 458          $this->assertInstanceOf('stdClass', $var2);
 459          $this->assertEquals('value', $var2->key);
 460  
 461          $this->assertTrue($cache->delete('obj'));
 462  
 463          // Death reference test on get_many... basically we don't want this to die.
 464          $obj = new stdClass;
 465          $obj->key = 'value';
 466          $obj->self =& $obj;
 467          $this->assertEquals(1, $cache->set_many(array('obj' => $obj)));
 468          $var = $cache->get_many(array('obj'));
 469          $this->assertInstanceOf('stdClass', $var['obj']);
 470          $this->assertEquals('value', $var['obj']->key);
 471  
 472          // Reference test after retrieve.
 473          $obj = new stdClass;
 474          $obj->key = 'value';
 475          $this->assertEquals(1, $cache->set_many(array('obj' => $obj)));
 476  
 477          $var1 = $cache->get_many(array('obj'));
 478          $this->assertInstanceOf('stdClass', $var1['obj']);
 479          $this->assertEquals('value', $var1['obj']->key);
 480          $var1['obj']->key = 'eulav';
 481          $this->assertEquals('eulav', $var1['obj']->key);
 482  
 483          $var2 = $cache->get_many(array('obj'));
 484          $this->assertInstanceOf('stdClass', $var2['obj']);
 485          $this->assertEquals('value', $var2['obj']->key);
 486  
 487          $this->assertTrue($cache->delete('obj'));
 488  
 489          // Test strictness exceptions.
 490          try {
 491              $cache->get('exception', MUST_EXIST);
 492              $this->fail('Exception expected from cache::get using MUST_EXIST');
 493          } catch (Exception $e) {
 494              $this->assertTrue(true);
 495          }
 496          try {
 497              $cache->get_many(array('exception1', 'exception2'), MUST_EXIST);
 498              $this->fail('Exception expected from cache::get_many using MUST_EXIST');
 499          } catch (Exception $e) {
 500              $this->assertTrue(true);
 501          }
 502          $cache->set('test', 'test');
 503          try {
 504              $cache->get_many(array('test', 'exception'), MUST_EXIST);
 505              $this->fail('Exception expected from cache::get_many using MUST_EXIST');
 506          } catch (Exception $e) {
 507              $this->assertTrue(true);
 508          }
 509      }
 510  
 511      /**
 512       * Tests a definition using a data loader
 513       */
 514      public function test_definition_data_loader() {
 515          $instance = cache_config_testing::instance(true);
 516          $instance->phpunit_add_definition('phpunit/datasourcetest', array(
 517              'mode' => cache_store::MODE_APPLICATION,
 518              'component' => 'phpunit',
 519              'area' => 'datasourcetest',
 520              'datasource' => 'cache_phpunit_dummy_datasource',
 521              'datasourcefile' => 'cache/tests/fixtures/lib.php'
 522          ));
 523  
 524          $cache = cache::make('phpunit', 'datasourcetest');
 525          $this->assertInstanceOf('cache_application', $cache);
 526  
 527          // Purge it to be sure.
 528          $this->assertTrue($cache->purge());
 529          // It won't be there yet.
 530          $this->assertFalse($cache->has('Test'));
 531          // It should load it ;).
 532          $this->assertTrue($cache->has('Test', true));
 533  
 534          // Purge it to be sure.
 535          $this->assertTrue($cache->purge());
 536          $this->assertEquals('Test has no value really.', $cache->get('Test'));
 537  
 538          // Test multiple values.
 539          $this->assertTrue($cache->purge());
 540          $this->assertTrue($cache->set('b', 'B'));
 541          $result = $cache->get_many(array('a', 'b', 'c'));
 542          $this->assertInternalType('array', $result);
 543          $this->assertCount(3, $result);
 544          $this->assertArrayHasKey('a', $result);
 545          $this->assertArrayHasKey('b', $result);
 546          $this->assertArrayHasKey('c', $result);
 547          $this->assertEquals('a has no value really.', $result['a']);
 548          $this->assertEquals('B', $result['b']);
 549          $this->assertEquals('c has no value really.', $result['c']);
 550      }
 551  
 552      /**
 553       * Tests a definition using an overridden loader
 554       */
 555      public function test_definition_overridden_loader() {
 556          $instance = cache_config_testing::instance(true);
 557          $instance->phpunit_add_definition('phpunit/overridetest', array(
 558              'mode' => cache_store::MODE_APPLICATION,
 559              'component' => 'phpunit',
 560              'area' => 'overridetest',
 561              'overrideclass' => 'cache_phpunit_dummy_overrideclass',
 562              'overrideclassfile' => 'cache/tests/fixtures/lib.php'
 563          ));
 564          $cache = cache::make('phpunit', 'overridetest');
 565          $this->assertInstanceOf('cache_phpunit_dummy_overrideclass', $cache);
 566          $this->assertInstanceOf('cache_application', $cache);
 567          // Purge it to be sure.
 568          $this->assertTrue($cache->purge());
 569          // It won't be there yet.
 570          $this->assertFalse($cache->has('Test'));
 571          // Add it.
 572          $this->assertTrue($cache->set('Test', 'Test has no value really.'));
 573          // Check its there.
 574          $this->assertEquals('Test has no value really.', $cache->get('Test'));
 575      }
 576  
 577      /**
 578       * Test the mappingsonly setting.
 579       */
 580      public function test_definition_mappings_only() {
 581          /** @var cache_config_testing $instance */
 582          $instance = cache_config_testing::instance(true);
 583          $instance->phpunit_add_definition('phpunit/mappingsonly', array(
 584              'mode' => cache_store::MODE_APPLICATION,
 585              'component' => 'phpunit',
 586              'area' => 'mappingsonly',
 587              'mappingsonly' => true
 588          ), false);
 589          $instance->phpunit_add_definition('phpunit/nonmappingsonly', array(
 590              'mode' => cache_store::MODE_APPLICATION,
 591              'component' => 'phpunit',
 592              'area' => 'nonmappingsonly',
 593              'mappingsonly' => false
 594          ), false);
 595  
 596          $cacheonly = cache::make('phpunit', 'mappingsonly');
 597          $this->assertInstanceOf('cache_application', $cacheonly);
 598          $this->assertEquals('cachestore_dummy', $cacheonly->phpunit_get_store_class());
 599  
 600          $expected = $this->get_expected_application_cache_store();
 601          $cachenon = cache::make('phpunit', 'nonmappingsonly');
 602          $this->assertInstanceOf('cache_application', $cachenon);
 603          $this->assertEquals($expected, $cachenon->phpunit_get_store_class());
 604      }
 605  
 606      /**
 607       * Test a very basic definition.
 608       */
 609      public function test_definition() {
 610          $instance = cache_config_testing::instance();
 611          $instance->phpunit_add_definition('phpunit/test', array(
 612              'mode' => cache_store::MODE_APPLICATION,
 613              'component' => 'phpunit',
 614              'area' => 'test',
 615          ));
 616          $cache = cache::make('phpunit', 'test');
 617  
 618          $this->assertTrue($cache->set('testkey1', 'test data 1'));
 619          $this->assertEquals('test data 1', $cache->get('testkey1'));
 620          $this->assertTrue($cache->set('testkey2', 'test data 2'));
 621          $this->assertEquals('test data 2', $cache->get('testkey2'));
 622      }
 623  
 624      /**
 625       * Test a definition using the simple keys.
 626       */
 627      public function test_definition_simplekeys() {
 628          $instance = cache_config_testing::instance();
 629          $instance->phpunit_add_definition('phpunit/simplekeytest', array(
 630              'mode' => cache_store::MODE_APPLICATION,
 631              'component' => 'phpunit',
 632              'area' => 'simplekeytest',
 633              'simplekeys' => true
 634          ));
 635          $cache = cache::make('phpunit', 'simplekeytest');
 636  
 637          $this->assertTrue($cache->set('testkey1', 'test data 1'));
 638          $this->assertEquals('test data 1', $cache->get('testkey1'));
 639          $this->assertTrue($cache->set('testkey2', 'test data 2'));
 640          $this->assertEquals('test data 2', $cache->get('testkey2'));
 641  
 642          $cache->purge();
 643  
 644          $this->assertTrue($cache->set('1', 'test data 1'));
 645          $this->assertEquals('test data 1', $cache->get('1'));
 646          $this->assertTrue($cache->set('2', 'test data 2'));
 647          $this->assertEquals('test data 2', $cache->get('2'));
 648      }
 649  
 650      /**
 651       * Test a negative TTL on an application cache.
 652       */
 653      public function test_application_ttl_negative() {
 654          $instance = cache_config_testing::instance(true);
 655          $instance->phpunit_add_definition('phpunit/ttltest', array(
 656              'mode' => cache_store::MODE_APPLICATION,
 657              'component' => 'phpunit',
 658              'area' => 'ttltest',
 659              'ttl' => -86400 // Set to a day in the past to be extra sure.
 660          ));
 661          $cache = cache::make('phpunit', 'ttltest');
 662          $this->assertInstanceOf('cache_application', $cache);
 663  
 664          // Purge it to be sure.
 665          $this->assertTrue($cache->purge());
 666          // It won't be there yet.
 667          $this->assertFalse($cache->has('Test'));
 668          // Set it now.
 669          $this->assertTrue($cache->set('Test', 'Test'));
 670          // Check its not there.
 671          $this->assertFalse($cache->has('Test'));
 672          // Double check by trying to get it.
 673          $this->assertFalse($cache->get('Test'));
 674  
 675          // Test with multiple keys.
 676          $this->assertEquals(3, $cache->set_many(array('a' => 'A', 'b' => 'B', 'c' => 'C')));
 677          $result = $cache->get_many(array('a', 'b', 'c'));
 678          $this->assertInternalType('array', $result);
 679          $this->assertCount(3, $result);
 680          $this->assertArrayHasKey('a', $result);
 681          $this->assertArrayHasKey('b', $result);
 682          $this->assertArrayHasKey('c', $result);
 683          $this->assertFalse($result['a']);
 684          $this->assertFalse($result['b']);
 685          $this->assertFalse($result['c']);
 686  
 687          // Test with multiple keys including missing ones.
 688          $result = $cache->get_many(array('a', 'c', 'e'));
 689          $this->assertInternalType('array', $result);
 690          $this->assertCount(3, $result);
 691          $this->assertArrayHasKey('a', $result);
 692          $this->assertArrayHasKey('c', $result);
 693          $this->assertArrayHasKey('e', $result);
 694          $this->assertFalse($result['a']);
 695          $this->assertFalse($result['c']);
 696          $this->assertFalse($result['e']);
 697      }
 698  
 699      /**
 700       * Test a positive TTL on an application cache.
 701       */
 702      public function test_application_ttl_positive() {
 703          $instance = cache_config_testing::instance(true);
 704          $instance->phpunit_add_definition('phpunit/ttltest', array(
 705              'mode' => cache_store::MODE_APPLICATION,
 706              'component' => 'phpunit',
 707              'area' => 'ttltest',
 708              'ttl' => 86400 // Set to a day in the future to be extra sure.
 709          ));
 710          $cache = cache::make('phpunit', 'ttltest');
 711          $this->assertInstanceOf('cache_application', $cache);
 712  
 713          // Purge it to be sure.
 714          $this->assertTrue($cache->purge());
 715          // It won't be there yet.
 716          $this->assertFalse($cache->has('Test'));
 717          // Set it now.
 718          $this->assertTrue($cache->set('Test', 'Test'));
 719          // Check its there.
 720          $this->assertTrue($cache->has('Test'));
 721          // Double check by trying to get it.
 722          $this->assertEquals('Test', $cache->get('Test'));
 723  
 724          // Test with multiple keys.
 725          $this->assertEquals(3, $cache->set_many(array('a' => 'A', 'b' => 'B', 'c' => 'C')));
 726          $result = $cache->get_many(array('a', 'b', 'c'));
 727          $this->assertInternalType('array', $result);
 728          $this->assertCount(3, $result);
 729          $this->assertArrayHasKey('a', $result);
 730          $this->assertArrayHasKey('b', $result);
 731          $this->assertArrayHasKey('c', $result);
 732          $this->assertEquals('A', $result['a']);
 733          $this->assertEquals('B', $result['b']);
 734          $this->assertEquals('C', $result['c']);
 735  
 736          // Test with multiple keys including missing ones.
 737          $result = $cache->get_many(array('a', 'c', 'e'));
 738          $this->assertInternalType('array', $result);
 739          $this->assertCount(3, $result);
 740          $this->assertArrayHasKey('a', $result);
 741          $this->assertArrayHasKey('c', $result);
 742          $this->assertArrayHasKey('e', $result);
 743          $this->assertEquals('A', $result['a']);
 744          $this->assertEquals('C', $result['c']);
 745          $this->assertEquals(false, $result['e']);
 746      }
 747  
 748      /**
 749       * Test a negative TTL on an session cache.
 750       */
 751      public function test_session_ttl_positive() {
 752          $instance = cache_config_testing::instance(true);
 753          $instance->phpunit_add_definition('phpunit/ttltest', array(
 754              'mode' => cache_store::MODE_SESSION,
 755              'component' => 'phpunit',
 756              'area' => 'ttltest',
 757              'ttl' => 86400 // Set to a day in the future to be extra sure.
 758          ));
 759          $cache = cache::make('phpunit', 'ttltest');
 760          $this->assertInstanceOf('cache_session', $cache);
 761  
 762          // Purge it to be sure.
 763          $this->assertTrue($cache->purge());
 764          // It won't be there yet.
 765          $this->assertFalse($cache->has('Test'));
 766          // Set it now.
 767          $this->assertTrue($cache->set('Test', 'Test'));
 768          // Check its there.
 769          $this->assertTrue($cache->has('Test'));
 770          // Double check by trying to get it.
 771          $this->assertEquals('Test', $cache->get('Test'));
 772  
 773          // Test with multiple keys.
 774          $this->assertEquals(3, $cache->set_many(array('a' => 'A', 'b' => 'B', 'c' => 'C')));
 775          $result = $cache->get_many(array('a', 'b', 'c'));
 776          $this->assertInternalType('array', $result);
 777          $this->assertCount(3, $result);
 778          $this->assertArrayHasKey('a', $result);
 779          $this->assertArrayHasKey('b', $result);
 780          $this->assertArrayHasKey('c', $result);
 781          $this->assertEquals('A', $result['a']);
 782          $this->assertEquals('B', $result['b']);
 783          $this->assertEquals('C', $result['c']);
 784  
 785          // Test with multiple keys including missing ones.
 786          $result = $cache->get_many(array('a', 'c', 'e'));
 787          $this->assertInternalType('array', $result);
 788          $this->assertCount(3, $result);
 789          $this->assertArrayHasKey('a', $result);
 790          $this->assertArrayHasKey('c', $result);
 791          $this->assertArrayHasKey('e', $result);
 792          $this->assertEquals('A', $result['a']);
 793          $this->assertEquals('C', $result['c']);
 794          $this->assertEquals(false, $result['e']);
 795      }
 796  
 797      /**
 798       * Tests manual locking operations on an application cache
 799       */
 800      public function test_application_manual_locking() {
 801          $instance = cache_config_testing::instance();
 802          $instance->phpunit_add_definition('phpunit/lockingtest', array(
 803              'mode' => cache_store::MODE_APPLICATION,
 804              'component' => 'phpunit',
 805              'area' => 'lockingtest'
 806          ));
 807          $cache1 = cache::make('phpunit', 'lockingtest');
 808          $cache2 = clone($cache1);
 809  
 810          $this->assertTrue($cache1->set('testkey', 'test data'));
 811          $this->assertTrue($cache2->set('testkey', 'test data'));
 812  
 813          $this->assertTrue($cache1->acquire_lock('testkey'));
 814          $this->assertFalse($cache2->acquire_lock('testkey'));
 815  
 816          $this->assertTrue($cache1->check_lock_state('testkey'));
 817          $this->assertFalse($cache2->check_lock_state('testkey'));
 818  
 819          $this->assertTrue($cache1->release_lock('testkey'));
 820          $this->assertFalse($cache2->release_lock('testkey'));
 821  
 822          $this->assertTrue($cache1->set('testkey', 'test data'));
 823          $this->assertTrue($cache2->set('testkey', 'test data'));
 824      }
 825  
 826      /**
 827       * Tests application cache event invalidation
 828       */
 829      public function test_application_event_invalidation() {
 830          $instance = cache_config_testing::instance();
 831          $instance->phpunit_add_definition('phpunit/eventinvalidationtest', array(
 832              'mode' => cache_store::MODE_APPLICATION,
 833              'component' => 'phpunit',
 834              'area' => 'eventinvalidationtest',
 835              'invalidationevents' => array(
 836                  'crazyevent'
 837              )
 838          ));
 839          $cache = cache::make('phpunit', 'eventinvalidationtest');
 840  
 841          $this->assertTrue($cache->set('testkey1', 'test data 1'));
 842          $this->assertEquals('test data 1', $cache->get('testkey1'));
 843          $this->assertTrue($cache->set('testkey2', 'test data 2'));
 844          $this->assertEquals('test data 2', $cache->get('testkey2'));
 845  
 846          // Test invalidating a single entry.
 847          cache_helper::invalidate_by_event('crazyevent', array('testkey1'));
 848  
 849          $this->assertFalse($cache->get('testkey1'));
 850          $this->assertEquals('test data 2', $cache->get('testkey2'));
 851  
 852          $this->assertTrue($cache->set('testkey1', 'test data 1'));
 853  
 854          // Test invalidating both entries.
 855          cache_helper::invalidate_by_event('crazyevent', array('testkey1', 'testkey2'));
 856  
 857          $this->assertFalse($cache->get('testkey1'));
 858          $this->assertFalse($cache->get('testkey2'));
 859      }
 860  
 861      /**
 862       * Tests session cache event invalidation
 863       */
 864      public function test_session_event_invalidation() {
 865          $instance = cache_config_testing::instance();
 866          $instance->phpunit_add_definition('phpunit/test_session_event_invalidation', array(
 867              'mode' => cache_store::MODE_SESSION,
 868              'component' => 'phpunit',
 869              'area' => 'test_session_event_invalidation',
 870              'invalidationevents' => array(
 871                  'crazyevent'
 872              )
 873          ));
 874          $cache = cache::make('phpunit', 'test_session_event_invalidation');
 875          $this->assertInstanceOf('cache_session', $cache);
 876  
 877          $this->assertTrue($cache->set('testkey1', 'test data 1'));
 878          $this->assertEquals('test data 1', $cache->get('testkey1'));
 879          $this->assertTrue($cache->set('testkey2', 'test data 2'));
 880          $this->assertEquals('test data 2', $cache->get('testkey2'));
 881  
 882          // Test invalidating a single entry.
 883          cache_helper::invalidate_by_event('crazyevent', array('testkey1'));
 884  
 885          $this->assertFalse($cache->get('testkey1'));
 886          $this->assertEquals('test data 2', $cache->get('testkey2'));
 887  
 888          $this->assertTrue($cache->set('testkey1', 'test data 1'));
 889  
 890          // Test invalidating both entries.
 891          cache_helper::invalidate_by_event('crazyevent', array('testkey1', 'testkey2'));
 892  
 893          $this->assertFalse($cache->get('testkey1'));
 894          $this->assertFalse($cache->get('testkey2'));
 895      }
 896  
 897      /**
 898       * Tests application cache definition invalidation
 899       */
 900      public function test_application_definition_invalidation() {
 901          $instance = cache_config_testing::instance();
 902          $instance->phpunit_add_definition('phpunit/definitioninvalidation', array(
 903              'mode' => cache_store::MODE_APPLICATION,
 904              'component' => 'phpunit',
 905              'area' => 'definitioninvalidation'
 906          ));
 907          $cache = cache::make('phpunit', 'definitioninvalidation');
 908          $this->assertTrue($cache->set('testkey1', 'test data 1'));
 909          $this->assertEquals('test data 1', $cache->get('testkey1'));
 910          $this->assertTrue($cache->set('testkey2', 'test data 2'));
 911          $this->assertEquals('test data 2', $cache->get('testkey2'));
 912  
 913          cache_helper::invalidate_by_definition('phpunit', 'definitioninvalidation', array(), 'testkey1');
 914  
 915          $this->assertFalse($cache->get('testkey1'));
 916          $this->assertEquals('test data 2', $cache->get('testkey2'));
 917  
 918          $this->assertTrue($cache->set('testkey1', 'test data 1'));
 919  
 920          cache_helper::invalidate_by_definition('phpunit', 'definitioninvalidation', array(), array('testkey1'));
 921  
 922          $this->assertFalse($cache->get('testkey1'));
 923          $this->assertEquals('test data 2', $cache->get('testkey2'));
 924  
 925          $this->assertTrue($cache->set('testkey1', 'test data 1'));
 926  
 927          cache_helper::invalidate_by_definition('phpunit', 'definitioninvalidation', array(), array('testkey1', 'testkey2'));
 928  
 929          $this->assertFalse($cache->get('testkey1'));
 930          $this->assertFalse($cache->get('testkey2'));
 931      }
 932  
 933      /**
 934       * Tests session cache definition invalidation
 935       */
 936      public function test_session_definition_invalidation() {
 937          $instance = cache_config_testing::instance();
 938          $instance->phpunit_add_definition('phpunit/test_session_definition_invalidation', array(
 939              'mode' => cache_store::MODE_SESSION,
 940              'component' => 'phpunit',
 941              'area' => 'test_session_definition_invalidation'
 942          ));
 943          $cache = cache::make('phpunit', 'test_session_definition_invalidation');
 944          $this->assertInstanceOf('cache_session', $cache);
 945          $this->assertTrue($cache->set('testkey1', 'test data 1'));
 946          $this->assertEquals('test data 1', $cache->get('testkey1'));
 947          $this->assertTrue($cache->set('testkey2', 'test data 2'));
 948          $this->assertEquals('test data 2', $cache->get('testkey2'));
 949  
 950          cache_helper::invalidate_by_definition('phpunit', 'test_session_definition_invalidation', array(), 'testkey1');
 951  
 952          $this->assertFalse($cache->get('testkey1'));
 953          $this->assertEquals('test data 2', $cache->get('testkey2'));
 954  
 955          $this->assertTrue($cache->set('testkey1', 'test data 1'));
 956  
 957          cache_helper::invalidate_by_definition('phpunit', 'test_session_definition_invalidation', array(),
 958                  array('testkey1'));
 959  
 960          $this->assertFalse($cache->get('testkey1'));
 961          $this->assertEquals('test data 2', $cache->get('testkey2'));
 962  
 963          $this->assertTrue($cache->set('testkey1', 'test data 1'));
 964  
 965          cache_helper::invalidate_by_definition('phpunit', 'test_session_definition_invalidation', array(),
 966                  array('testkey1', 'testkey2'));
 967  
 968          $this->assertFalse($cache->get('testkey1'));
 969          $this->assertFalse($cache->get('testkey2'));
 970      }
 971  
 972      /**
 973       * Tests application cache event invalidation over a distributed setup.
 974       */
 975      public function test_distributed_application_event_invalidation() {
 976          global $CFG;
 977          // This is going to be an intense wee test.
 978          // We need to add data the to cache, invalidate it by event, manually force it back without MUC knowing to simulate a
 979          // disconnected/distributed setup (think load balanced server using local cache), instantiate the cache again and finally
 980          // check that it is not picked up.
 981          $instance = cache_config_testing::instance();
 982          $instance->phpunit_add_definition('phpunit/eventinvalidationtest', array(
 983              'mode' => cache_store::MODE_APPLICATION,
 984              'component' => 'phpunit',
 985              'area' => 'eventinvalidationtest',
 986              'simplekeys' => true,
 987              'simpledata' => true,
 988              'invalidationevents' => array(
 989                  'crazyevent'
 990              )
 991          ));
 992          $cache = cache::make('phpunit', 'eventinvalidationtest');
 993          $this->assertTrue($cache->set('testkey1', 'test data 1'));
 994          $this->assertEquals('test data 1', $cache->get('testkey1'));
 995  
 996          cache_helper::invalidate_by_event('crazyevent', array('testkey1'));
 997  
 998          $this->assertFalse($cache->get('testkey1'));
 999  
1000          // OK data added, data invalidated, and invalidation time has been set.
1001          // Now we need to manually add back the data and adjust the invalidation time.
1002          $hash = md5(cache_store::MODE_APPLICATION.'/phpunit/eventinvalidationtest/'.$CFG->wwwroot.'phpunit');
1003          $timefile = $CFG->dataroot."/cache/cachestore_file/default_application/phpunit_eventinvalidationtest/las-cache/lastinvalidation-$hash.cache";
1004          // Make sure the file is correct.
1005          $this->assertTrue(file_exists($timefile));
1006          $timecont = serialize(cache::now(true) - 60); // Back 60sec in the past to force it to re-invalidate.
1007          make_writable_directory(dirname($timefile));
1008          file_put_contents($timefile, $timecont);
1009          $this->assertTrue(file_exists($timefile));
1010  
1011          $datafile = $CFG->dataroot."/cache/cachestore_file/default_application/phpunit_eventinvalidationtest/tes-cache/testkey1-$hash.cache";
1012          $datacont = serialize("test data 1");
1013          make_writable_directory(dirname($datafile));
1014          file_put_contents($datafile, $datacont);
1015          $this->assertTrue(file_exists($datafile));
1016  
1017          // Test 1: Rebuild without the event and test its there.
1018          cache_factory::reset();
1019          $instance = cache_config_testing::instance();
1020          $instance->phpunit_add_definition('phpunit/eventinvalidationtest', array(
1021              'mode' => cache_store::MODE_APPLICATION,
1022              'component' => 'phpunit',
1023              'area' => 'eventinvalidationtest',
1024              'simplekeys' => true,
1025              'simpledata' => true,
1026          ));
1027          $cache = cache::make('phpunit', 'eventinvalidationtest');
1028          $this->assertEquals('test data 1', $cache->get('testkey1'));
1029  
1030          // Test 2: Rebuild and test the invalidation of the event via the invalidation cache.
1031          cache_factory::reset();
1032  
1033          $instance = cache_config_testing::instance();
1034          $instance->phpunit_add_definition('phpunit/eventinvalidationtest', array(
1035              'mode' => cache_store::MODE_APPLICATION,
1036              'component' => 'phpunit',
1037              'area' => 'eventinvalidationtest',
1038              'simplekeys' => true,
1039              'simpledata' => true,
1040              'invalidationevents' => array(
1041                  'crazyevent'
1042              )
1043          ));
1044  
1045          $cache = cache::make('phpunit', 'eventinvalidationtest');
1046          $this->assertFalse($cache->get('testkey1'));
1047  
1048          // Test 3: Verify that an existing lastinvalidation cache file is updated when needed.
1049  
1050          // Make a new cache class.  This should should invalidate testkey2.
1051          $cache = cache::make('phpunit', 'eventinvalidationtest');
1052  
1053          // Invalidation token should have been reset.
1054          $this->assertEquals(cache::get_purge_token(), $cache->get('lastinvalidation'));
1055  
1056          // Set testkey2 data.
1057          $cache->set('testkey2', 'test data 2');
1058  
1059          // Backdate the event invalidation time by 30 seconds.
1060          $invalidationcache = cache::make('core', 'eventinvalidation');
1061          $invalidationcache->set('crazyevent', array('testkey2' => cache::now() - 30));
1062  
1063          // Lastinvalidation should already be cache::now().
1064          $this->assertEquals(cache::get_purge_token(), $cache->get('lastinvalidation'));
1065  
1066          // Set it to 15 seconds ago so that we know if it changes.
1067          $pasttime = cache::now(true) - 15;
1068          $cache->set('lastinvalidation', $pasttime);
1069  
1070          // Make a new cache class.  This should not invalidate anything.
1071          cache_factory::instance()->reset_cache_instances();
1072          $cache = cache::make('phpunit', 'eventinvalidationtest');
1073  
1074          // Lastinvalidation shouldn't change since it was already newer than invalidation event.
1075          $this->assertEquals($pasttime, $cache->get('lastinvalidation'));
1076  
1077          // Now set the event invalidation to newer than the lastinvalidation time.
1078          $invalidationcache->set('crazyevent', array('testkey2' => cache::now() - 5));
1079          // Make a new cache class.  This should should invalidate testkey2.
1080          cache_factory::instance()->reset_cache_instances();
1081          $cache = cache::make('phpunit', 'eventinvalidationtest');
1082          // Lastinvalidation timestamp should have updated to cache::now().
1083          $this->assertEquals(cache::get_purge_token(), $cache->get('lastinvalidation'));
1084  
1085          // Now simulate a purge_by_event 5 seconds ago.
1086          $invalidationcache = cache::make('core', 'eventinvalidation');
1087          $invalidationcache->set('crazyevent', array('purged' => cache::now(true) - 5));
1088          // Set our lastinvalidation timestamp to 15 seconds ago.
1089          $cache->set('lastinvalidation', cache::now(true) - 15);
1090          // Make a new cache class.  This should invalidate the cache.
1091          cache_factory::instance()->reset_cache_instances();
1092          $cache = cache::make('phpunit', 'eventinvalidationtest');
1093          // Lastinvalidation timestamp should have updated to cache::now().
1094          $this->assertEquals(cache::get_purge_token(), $cache->get('lastinvalidation'));
1095  
1096      }
1097  
1098      /**
1099       * Tests application cache event purge
1100       */
1101      public function test_application_event_purge() {
1102          $instance = cache_config_testing::instance();
1103          $instance->phpunit_add_definition('phpunit/eventpurgetest', array(
1104              'mode' => cache_store::MODE_APPLICATION,
1105              'component' => 'phpunit',
1106              'area' => 'eventpurgetest',
1107              'invalidationevents' => array(
1108                  'crazyevent'
1109              )
1110          ));
1111          $instance->phpunit_add_definition('phpunit/eventpurgetestaccelerated', array(
1112              'mode' => cache_store::MODE_APPLICATION,
1113              'component' => 'phpunit',
1114              'area' => 'eventpurgetestaccelerated',
1115              'staticacceleration' => true,
1116              'invalidationevents' => array(
1117                  'crazyevent'
1118              )
1119          ));
1120          $cache = cache::make('phpunit', 'eventpurgetest');
1121  
1122          $this->assertTrue($cache->set('testkey1', 'test data 1'));
1123          $this->assertEquals('test data 1', $cache->get('testkey1'));
1124          $this->assertTrue($cache->set('testkey2', 'test data 2'));
1125          $this->assertEquals('test data 2', $cache->get('testkey2'));
1126  
1127          // Purge the event.
1128          cache_helper::purge_by_event('crazyevent');
1129  
1130          // Check things have been removed.
1131          $this->assertFalse($cache->get('testkey1'));
1132          $this->assertFalse($cache->get('testkey2'));
1133  
1134          // Now test the static acceleration array.
1135          $cache = cache::make('phpunit', 'eventpurgetestaccelerated');
1136          $this->assertTrue($cache->set('testkey1', 'test data 1'));
1137          $this->assertEquals('test data 1', $cache->get('testkey1'));
1138          $this->assertTrue($cache->set('testkey2', 'test data 2'));
1139          $this->assertEquals('test data 2', $cache->get('testkey2'));
1140  
1141          // Purge the event.
1142          cache_helper::purge_by_event('crazyevent');
1143  
1144          // Check things have been removed.
1145          $this->assertFalse($cache->get('testkey1'));
1146          $this->assertFalse($cache->get('testkey2'));
1147      }
1148  
1149      /**
1150       * Tests session cache event purge
1151       */
1152      public function test_session_event_purge() {
1153          $instance = cache_config_testing::instance();
1154          $instance->phpunit_add_definition('phpunit/eventpurgetest', array(
1155              'mode' => cache_store::MODE_SESSION,
1156              'component' => 'phpunit',
1157              'area' => 'eventpurgetest',
1158              'invalidationevents' => array(
1159                  'crazyevent'
1160              )
1161          ));
1162          $instance->phpunit_add_definition('phpunit/eventpurgetestaccelerated', array(
1163              'mode' => cache_store::MODE_SESSION,
1164              'component' => 'phpunit',
1165              'area' => 'eventpurgetestaccelerated',
1166              'staticacceleration' => true,
1167              'invalidationevents' => array(
1168                  'crazyevent'
1169              )
1170          ));
1171          $cache = cache::make('phpunit', 'eventpurgetest');
1172  
1173          $this->assertTrue($cache->set('testkey1', 'test data 1'));
1174          $this->assertEquals('test data 1', $cache->get('testkey1'));
1175          $this->assertTrue($cache->set('testkey2', 'test data 2'));
1176          $this->assertEquals('test data 2', $cache->get('testkey2'));
1177  
1178          // Purge the event.
1179          cache_helper::purge_by_event('crazyevent');
1180  
1181          // Check things have been removed.
1182          $this->assertFalse($cache->get('testkey1'));
1183          $this->assertFalse($cache->get('testkey2'));
1184  
1185          // Now test the static acceleration array.
1186          $cache = cache::make('phpunit', 'eventpurgetestaccelerated');
1187          $this->assertTrue($cache->set('testkey1', 'test data 1'));
1188          $this->assertEquals('test data 1', $cache->get('testkey1'));
1189          $this->assertTrue($cache->set('testkey2', 'test data 2'));
1190          $this->assertEquals('test data 2', $cache->get('testkey2'));
1191  
1192          // Purge the event.
1193          cache_helper::purge_by_event('crazyevent');
1194  
1195          // Check things have been removed.
1196          $this->assertFalse($cache->get('testkey1'));
1197          $this->assertFalse($cache->get('testkey2'));
1198      }
1199  
1200      /**
1201       * Tests application cache definition purge
1202       */
1203      public function test_application_definition_purge() {
1204          $instance = cache_config_testing::instance();
1205          $instance->phpunit_add_definition('phpunit/definitionpurgetest', array(
1206              'mode' => cache_store::MODE_APPLICATION,
1207              'component' => 'phpunit',
1208              'area' => 'definitionpurgetest',
1209              'invalidationevents' => array(
1210                  'crazyevent'
1211              )
1212          ));
1213          $cache = cache::make('phpunit', 'definitionpurgetest');
1214  
1215          $this->assertTrue($cache->set('testkey1', 'test data 1'));
1216          $this->assertEquals('test data 1', $cache->get('testkey1'));
1217          $this->assertTrue($cache->set('testkey2', 'test data 2'));
1218          $this->assertEquals('test data 2', $cache->get('testkey2'));
1219  
1220          // Purge the event.
1221          cache_helper::purge_by_definition('phpunit', 'definitionpurgetest');
1222  
1223          // Check things have been removed.
1224          $this->assertFalse($cache->get('testkey1'));
1225          $this->assertFalse($cache->get('testkey2'));
1226      }
1227  
1228      /**
1229       * Test the use of an alt path.
1230       * If we can generate a config instance we are done :)
1231       */
1232      public function test_alt_cache_path() {
1233          global $CFG;
1234          if ((defined('TEST_CACHE_USING_ALT_CACHE_CONFIG_PATH') && TEST_CACHE_USING_ALT_CACHE_CONFIG_PATH) || !empty($CFG->altcacheconfigpath)) {
1235              $this->markTestSkipped('Skipped testing alt cache path as it is already being used.');
1236          }
1237          $this->resetAfterTest();
1238          $CFG->altcacheconfigpath = $CFG->dataroot.'/cache/altcacheconfigpath';
1239          $instance = cache_config_testing::instance();
1240          $this->assertInstanceOf('cache_config', $instance);
1241      }
1242  
1243      /**
1244       * Test disabling the cache stores.
1245       */
1246      public function test_disable_stores() {
1247          $instance = cache_config_testing::instance();
1248          $instance->phpunit_add_definition('phpunit/disabletest1', array(
1249              'mode' => cache_store::MODE_APPLICATION,
1250              'component' => 'phpunit',
1251              'area' => 'disabletest1'
1252          ));
1253          $instance->phpunit_add_definition('phpunit/disabletest2', array(
1254              'mode' => cache_store::MODE_SESSION,
1255              'component' => 'phpunit',
1256              'area' => 'disabletest2'
1257          ));
1258          $instance->phpunit_add_definition('phpunit/disabletest3', array(
1259              'mode' => cache_store::MODE_REQUEST,
1260              'component' => 'phpunit',
1261              'area' => 'disabletest3'
1262          ));
1263  
1264          $caches = array(
1265              'disabletest1' => cache::make('phpunit', 'disabletest1'),
1266              'disabletest2' => cache::make('phpunit', 'disabletest2'),
1267              'disabletest3' => cache::make('phpunit', 'disabletest3')
1268          );
1269  
1270          $this->assertInstanceOf('cache_phpunit_application', $caches['disabletest1']);
1271          $this->assertInstanceOf('cache_phpunit_session', $caches['disabletest2']);
1272          $this->assertInstanceOf('cache_phpunit_request', $caches['disabletest3']);
1273  
1274          $this->assertEquals('cachestore_file', $caches['disabletest1']->phpunit_get_store_class());
1275          $this->assertEquals('cachestore_session', $caches['disabletest2']->phpunit_get_store_class());
1276          $this->assertEquals('cachestore_static', $caches['disabletest3']->phpunit_get_store_class());
1277  
1278          foreach ($caches as $cache) {
1279              $this->assertFalse($cache->get('test'));
1280              $this->assertTrue($cache->set('test', 'test'));
1281              $this->assertEquals('test', $cache->get('test'));
1282          }
1283  
1284          cache_factory::disable_stores();
1285  
1286          $caches = array(
1287              'disabletest1' => cache::make('phpunit', 'disabletest1'),
1288              'disabletest2' => cache::make('phpunit', 'disabletest2'),
1289              'disabletest3' => cache::make('phpunit', 'disabletest3')
1290          );
1291  
1292          $this->assertInstanceOf('cache_phpunit_application', $caches['disabletest1']);
1293          $this->assertInstanceOf('cache_phpunit_session', $caches['disabletest2']);
1294          $this->assertInstanceOf('cache_phpunit_request', $caches['disabletest3']);
1295  
1296          $this->assertEquals('cachestore_dummy', $caches['disabletest1']->phpunit_get_store_class());
1297          $this->assertEquals('cachestore_dummy', $caches['disabletest2']->phpunit_get_store_class());
1298          $this->assertEquals('cachestore_dummy', $caches['disabletest3']->phpunit_get_store_class());
1299  
1300          foreach ($caches as $cache) {
1301              $this->assertFalse($cache->get('test'));
1302              $this->assertTrue($cache->set('test', 'test'));
1303              $this->assertEquals('test', $cache->get('test'));
1304          }
1305      }
1306  
1307      /**
1308       * Test disabling the cache.
1309       */
1310      public function test_disable() {
1311          global $CFG;
1312  
1313          if ((defined('TEST_CACHE_USING_ALT_CACHE_CONFIG_PATH') && TEST_CACHE_USING_ALT_CACHE_CONFIG_PATH) || !empty($CFG->altcacheconfigpath)) {
1314              // We can't run this test as it requires us to delete the cache configuration script which we just
1315              // cant do with a custom path in play.
1316              $this->markTestSkipped('Skipped testing cache disable functionality as alt cache path is being used.');
1317          }
1318  
1319          $configfile = $CFG->dataroot.'/muc/config.php';
1320  
1321          // The config file will not exist yet as we've not done anything with the cache.
1322          // reset_all_data removes the file and without a call to create a configuration it doesn't exist
1323          // as yet.
1324          $this->assertFileNotExists($configfile);
1325  
1326          // Disable the cache
1327          cache_phpunit_factory::phpunit_disable();
1328  
1329          // Check we get the expected disabled factory.
1330          $factory = cache_factory::instance();
1331          $this->assertInstanceOf('cache_factory_disabled', $factory);
1332  
1333          // Check we get the expected disabled config.
1334          $config = $factory->create_config_instance();
1335          $this->assertInstanceOf('cache_config_disabled', $config);
1336  
1337          // Check we get the expected disabled caches.
1338          $cache = cache::make('core', 'string');
1339          $this->assertInstanceOf('cache_disabled', $cache);
1340  
1341          // Test an application cache.
1342          $cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'phpunit', 'disable');
1343          $this->assertInstanceOf('cache_disabled', $cache);
1344  
1345          $this->assertFalse($cache->get('test'));
1346          $this->assertFalse($cache->set('test', 'test'));
1347          $this->assertFalse($cache->delete('test'));
1348          $this->assertTrue($cache->purge());
1349  
1350          // Test a session cache.
1351          $cache = cache::make_from_params(cache_store::MODE_SESSION, 'phpunit', 'disable');
1352          $this->assertInstanceOf('cache_disabled', $cache);
1353  
1354          $this->assertFalse($cache->get('test'));
1355          $this->assertFalse($cache->set('test', 'test'));
1356          $this->assertFalse($cache->delete('test'));
1357          $this->assertTrue($cache->purge());
1358  
1359          // Finally test a request cache.
1360          $cache = cache::make_from_params(cache_store::MODE_REQUEST, 'phpunit', 'disable');
1361          $this->assertInstanceOf('cache_disabled', $cache);
1362  
1363          $this->assertFalse($cache->get('test'));
1364          $this->assertFalse($cache->set('test', 'test'));
1365          $this->assertFalse($cache->delete('test'));
1366          $this->assertTrue($cache->purge());
1367  
1368          cache_factory::reset();
1369  
1370          $factory = cache_factory::instance(true);
1371          $config = $factory->create_config_instance();
1372          $this->assertEquals('cache_config_testing', get_class($config));
1373      }
1374  
1375      /**
1376       * Test that multiple application loaders work ok.
1377       */
1378      public function test_multiple_application_loaders() {
1379          $instance = cache_config_testing::instance(true);
1380          $instance->phpunit_add_file_store('phpunittest1');
1381          $instance->phpunit_add_file_store('phpunittest2');
1382          $instance->phpunit_add_definition('phpunit/multi_loader', array(
1383              'mode' => cache_store::MODE_APPLICATION,
1384              'component' => 'phpunit',
1385              'area' => 'multi_loader'
1386          ));
1387          $instance->phpunit_add_definition_mapping('phpunit/multi_loader', 'phpunittest1', 3);
1388          $instance->phpunit_add_definition_mapping('phpunit/multi_loader', 'phpunittest2', 2);
1389  
1390          $cache = cache::make('phpunit', 'multi_loader');
1391          $this->assertInstanceOf('cache_application', $cache);
1392          $this->assertFalse($cache->get('test'));
1393          $this->assertTrue($cache->set('test', 'test'));
1394          $this->assertEquals('test', $cache->get('test'));
1395          $this->assertTrue($cache->delete('test'));
1396          $this->assertFalse($cache->get('test'));
1397          $this->assertTrue($cache->set('test', 'test'));
1398          $this->assertTrue($cache->purge());
1399          $this->assertFalse($cache->get('test'));
1400  
1401          // Test the many commands.
1402          $this->assertEquals(3, $cache->set_many(array('a' => 'A', 'b' => 'B', 'c' => 'C')));
1403          $result = $cache->get_many(array('a', 'b', 'c'));
1404          $this->assertInternalType('array', $result);
1405          $this->assertCount(3, $result);
1406          $this->assertArrayHasKey('a', $result);
1407          $this->assertArrayHasKey('b', $result);
1408          $this->assertArrayHasKey('c', $result);
1409          $this->assertEquals('A', $result['a']);
1410          $this->assertEquals('B', $result['b']);
1411          $this->assertEquals('C', $result['c']);
1412          $this->assertEquals($result, $cache->get_many(array('a', 'b', 'c')));
1413          $this->assertEquals(2, $cache->delete_many(array('a', 'c')));
1414          $result = $cache->get_many(array('a', 'b', 'c'));
1415          $this->assertInternalType('array', $result);
1416          $this->assertCount(3, $result);
1417          $this->assertArrayHasKey('a', $result);
1418          $this->assertArrayHasKey('b', $result);
1419          $this->assertArrayHasKey('c', $result);
1420          $this->assertFalse($result['a']);
1421          $this->assertEquals('B', $result['b']);
1422          $this->assertFalse($result['c']);
1423  
1424          // Test non-recursive deletes.
1425          $this->assertTrue($cache->set('test', 'test'));
1426          $this->assertSame('test', $cache->get('test'));
1427          $this->assertTrue($cache->delete('test', false));
1428          // We should still have it on a deeper loader.
1429          $this->assertSame('test', $cache->get('test'));
1430          // Test non-recusive with many functions.
1431          $this->assertSame(3, $cache->set_many(array(
1432              'one' => 'one',
1433              'two' => 'two',
1434              'three' => 'three'
1435          )));
1436          $this->assertSame('one', $cache->get('one'));
1437          $this->assertSame(array('two' => 'two', 'three' => 'three'), $cache->get_many(array('two', 'three')));
1438          $this->assertSame(3, $cache->delete_many(array('one', 'two', 'three'), false));
1439          $this->assertSame('one', $cache->get('one'));
1440          $this->assertSame(array('two' => 'two', 'three' => 'three'), $cache->get_many(array('two', 'three')));
1441      }
1442  
1443      /**
1444       * Test that multiple application loaders work ok.
1445       */
1446      public function test_multiple_session_loaders() {
1447          /* @var cache_config_testing $instance */
1448          $instance = cache_config_testing::instance(true);
1449          $instance->phpunit_add_session_store('phpunittest1');
1450          $instance->phpunit_add_session_store('phpunittest2');
1451          $instance->phpunit_add_definition('phpunit/multi_loader', array(
1452              'mode' => cache_store::MODE_SESSION,
1453              'component' => 'phpunit',
1454              'area' => 'multi_loader'
1455          ));
1456          $instance->phpunit_add_definition_mapping('phpunit/multi_loader', 'phpunittest1', 3);
1457          $instance->phpunit_add_definition_mapping('phpunit/multi_loader', 'phpunittest2', 2);
1458  
1459          $cache = cache::make('phpunit', 'multi_loader');
1460          $this->assertInstanceOf('cache_session', $cache);
1461          $this->assertFalse($cache->get('test'));
1462          $this->assertTrue($cache->set('test', 'test'));
1463          $this->assertEquals('test', $cache->get('test'));
1464          $this->assertTrue($cache->delete('test'));
1465          $this->assertFalse($cache->get('test'));
1466          $this->assertTrue($cache->set('test', 'test'));
1467          $this->assertTrue($cache->purge());
1468          $this->assertFalse($cache->get('test'));
1469  
1470          // Test the many commands.
1471          $this->assertEquals(3, $cache->set_many(array('a' => 'A', 'b' => 'B', 'c' => 'C')));
1472          $result = $cache->get_many(array('a', 'b', 'c'));
1473          $this->assertInternalType('array', $result);
1474          $this->assertCount(3, $result);
1475          $this->assertArrayHasKey('a', $result);
1476          $this->assertArrayHasKey('b', $result);
1477          $this->assertArrayHasKey('c', $result);
1478          $this->assertEquals('A', $result['a']);
1479          $this->assertEquals('B', $result['b']);
1480          $this->assertEquals('C', $result['c']);
1481          $this->assertEquals($result, $cache->get_many(array('a', 'b', 'c')));
1482          $this->assertEquals(2, $cache->delete_many(array('a', 'c')));
1483          $result = $cache->get_many(array('a', 'b', 'c'));
1484          $this->assertInternalType('array', $result);
1485          $this->assertCount(3, $result);
1486          $this->assertArrayHasKey('a', $result);
1487          $this->assertArrayHasKey('b', $result);
1488          $this->assertArrayHasKey('c', $result);
1489          $this->assertFalse($result['a']);
1490          $this->assertEquals('B', $result['b']);
1491          $this->assertFalse($result['c']);
1492  
1493          // Test non-recursive deletes.
1494          $this->assertTrue($cache->set('test', 'test'));
1495          $this->assertSame('test', $cache->get('test'));
1496          $this->assertTrue($cache->delete('test', false));
1497          // We should still have it on a deeper loader.
1498          $this->assertSame('test', $cache->get('test'));
1499          // Test non-recusive with many functions.
1500          $this->assertSame(3, $cache->set_many(array(
1501              'one' => 'one',
1502              'two' => 'two',
1503              'three' => 'three'
1504          )));
1505          $this->assertSame('one', $cache->get('one'));
1506          $this->assertSame(array('two' => 'two', 'three' => 'three'), $cache->get_many(array('two', 'three')));
1507          $this->assertSame(3, $cache->delete_many(array('one', 'two', 'three'), false));
1508          $this->assertSame('one', $cache->get('one'));
1509          $this->assertSame(array('two' => 'two', 'three' => 'three'), $cache->get_many(array('two', 'three')));
1510      }
1511  
1512      /**
1513       * Test switching users with session caches.
1514       */
1515      public function test_session_cache_switch_user() {
1516          $this->resetAfterTest(true);
1517          $cache = cache::make_from_params(cache_store::MODE_SESSION, 'phpunit', 'sessioncache');
1518          $user1 = $this->getDataGenerator()->create_user();
1519          $user2 = $this->getDataGenerator()->create_user();
1520  
1521          // Log in as the first user.
1522          $this->setUser($user1);
1523          $sesskey1 = sesskey();
1524  
1525          // Set a basic value in the cache.
1526          $cache->set('var', 1);
1527          $this->assertTrue($cache->has('var'));
1528          $this->assertEquals(1, $cache->get('var'));
1529  
1530          // Change to the second user.
1531          $this->setUser($user2);
1532          $sesskey2 = sesskey();
1533  
1534          // Make sure the cache doesn't give us the data for the last user.
1535          $this->assertNotEquals($sesskey1, $sesskey2);
1536          $this->assertFalse($cache->has('var'));
1537          $this->assertEquals(false, $cache->get('var'));
1538      }
1539  
1540      /**
1541       * Test switching users with session caches.
1542       */
1543      public function test_session_cache_switch_user_application_mapping() {
1544          $this->resetAfterTest(true);
1545          $instance = cache_config_testing::instance(true);
1546          $instance->phpunit_add_file_store('testfilestore');
1547          $instance->phpunit_add_definition('phpunit/testappsession', array(
1548              'mode' => cache_store::MODE_SESSION,
1549              'component' => 'phpunit',
1550              'area' => 'testappsession'
1551          ));
1552          $instance->phpunit_add_definition_mapping('phpunit/testappsession', 'testfilestore', 3);
1553          $cache = cache::make('phpunit', 'testappsession');
1554          $user1 = $this->getDataGenerator()->create_user();
1555          $user2 = $this->getDataGenerator()->create_user();
1556  
1557          // Log in as the first user.
1558          $this->setUser($user1);
1559          $sesskey1 = sesskey();
1560  
1561          // Set a basic value in the cache.
1562          $cache->set('var', 1);
1563          $this->assertTrue($cache->has('var'));
1564          $this->assertEquals(1, $cache->get('var'));
1565  
1566          // Change to the second user.
1567          $this->setUser($user2);
1568          $sesskey2 = sesskey();
1569  
1570          // Make sure the cache doesn't give us the data for the last user.
1571          $this->assertNotEquals($sesskey1, $sesskey2);
1572          $this->assertFalse($cache->has('var'));
1573          $this->assertEquals(false, $cache->get('var'));
1574      }
1575  
1576      /**
1577       * Test two session caches being used at once to confirm collisions don't occur.
1578       */
1579      public function test_dual_session_caches() {
1580          $instance = cache_config_testing::instance(true);
1581          $instance->phpunit_add_definition('phpunit/testsess1', array(
1582              'mode' => cache_store::MODE_SESSION,
1583              'component' => 'phpunit',
1584              'area' => 'testsess1'
1585          ));
1586          $instance->phpunit_add_definition('phpunit/testsess2', array(
1587              'mode' => cache_store::MODE_SESSION,
1588              'component' => 'phpunit',
1589              'area' => 'testsess2'
1590          ));
1591          $cache1 = cache::make('phpunit', 'testsess1');
1592          $cache2 = cache::make('phpunit', 'testsess2');
1593  
1594          $this->assertFalse($cache1->has('test'));
1595          $this->assertFalse($cache2->has('test'));
1596  
1597          $this->assertTrue($cache1->set('test', '1'));
1598  
1599          $this->assertTrue($cache1->has('test'));
1600          $this->assertFalse($cache2->has('test'));
1601  
1602          $this->assertTrue($cache2->set('test', '2'));
1603  
1604          $this->assertEquals(1, $cache1->get('test'));
1605          $this->assertEquals(2, $cache2->get('test'));
1606  
1607          $this->assertTrue($cache1->delete('test'));
1608      }
1609  
1610      /**
1611       * Test multiple session caches when switching user.
1612       */
1613      public function test_session_cache_switch_user_multiple() {
1614          $this->resetAfterTest(true);
1615          $cache1 = cache::make_from_params(cache_store::MODE_SESSION, 'phpunit', 'sessioncache1');
1616          $cache2 = cache::make_from_params(cache_store::MODE_SESSION, 'phpunit', 'sessioncache2');
1617          $user1 = $this->getDataGenerator()->create_user();
1618          $user2 = $this->getDataGenerator()->create_user();
1619  
1620          // Log in as the first user.
1621          $this->setUser($user1);
1622          $sesskey1 = sesskey();
1623  
1624          // Set a basic value in the caches.
1625          $cache1->set('var', 1);
1626          $cache2->set('var', 2);
1627          $this->assertEquals(1, $cache1->get('var'));
1628          $this->assertEquals(2, $cache2->get('var'));
1629  
1630          // Change to the second user.
1631          $this->setUser($user2);
1632          $sesskey2 = sesskey();
1633  
1634          // Make sure the cache doesn't give us the data for the last user.
1635          // Also make sure that switching the user has lead to both caches being purged.
1636          $this->assertNotEquals($sesskey1, $sesskey2);
1637          $this->assertEquals(false, $cache1->get('var'));
1638          $this->assertEquals(false, $cache2->get('var'));
1639      }
1640  
1641      /**
1642       * Test application locking.
1643       */
1644      public function test_application_locking() {
1645          $instance = cache_config_testing::instance(true);
1646          $instance->phpunit_add_definition('phpunit/test_application_locking', array(
1647              'mode' => cache_store::MODE_APPLICATION,
1648              'component' => 'phpunit',
1649              'area' => 'test_application_locking',
1650              'staticacceleration' => true,
1651              'staticaccelerationsize' => 1,
1652              'requirelockingread' => true,
1653              'requirelockingwrite' => true
1654          ));
1655          $cache = cache::make('phpunit', 'test_application_locking');
1656          $this->assertInstanceOf('cache_application', $cache);
1657  
1658          $this->assertTrue($cache->set('a', 'A'));
1659          $this->assertTrue($cache->set('b', 'B'));
1660          $this->assertTrue($cache->set('c', 'C'));
1661          $this->assertEquals('A', $cache->get('a'));
1662          $this->assertEquals(array('b' => 'B', 'c' => 'C'), $cache->get_many(array('b', 'c')));
1663          $this->assertTrue($cache->delete('a'));
1664          $this->assertFalse($cache->has('a'));
1665      }
1666  
1667      /**
1668       * Test the static cache_helper method purge_stores_used_by_definition.
1669       */
1670      public function test_purge_stores_used_by_definition() {
1671          $instance = cache_config_testing::instance(true);
1672          $instance->phpunit_add_definition('phpunit/test_purge_stores_used_by_definition', array(
1673              'mode' => cache_store::MODE_APPLICATION,
1674              'component' => 'phpunit',
1675              'area' => 'test_purge_stores_used_by_definition'
1676          ));
1677          $cache = cache::make('phpunit', 'test_purge_stores_used_by_definition');
1678          $this->assertInstanceOf('cache_application', $cache);
1679          $this->assertTrue($cache->set('test', 'test'));
1680          unset($cache);
1681  
1682          cache_helper::purge_stores_used_by_definition('phpunit', 'test_purge_stores_used_by_definition');
1683  
1684          $cache = cache::make('phpunit', 'test_purge_stores_used_by_definition');
1685          $this->assertInstanceOf('cache_application', $cache);
1686          $this->assertFalse($cache->get('test'));
1687      }
1688  
1689      /**
1690       * Test purge routines.
1691       */
1692      public function test_purge_routines() {
1693          $instance = cache_config_testing::instance(true);
1694          $instance->phpunit_add_definition('phpunit/purge1', array(
1695              'mode' => cache_store::MODE_APPLICATION,
1696              'component' => 'phpunit',
1697              'area' => 'purge1'
1698          ));
1699          $instance->phpunit_add_definition('phpunit/purge2', array(
1700              'mode' => cache_store::MODE_APPLICATION,
1701              'component' => 'phpunit',
1702              'area' => 'purge2',
1703              'requireidentifiers' => array(
1704                  'id'
1705              )
1706          ));
1707  
1708          $factory = cache_factory::instance();
1709          $definition = $factory->create_definition('phpunit', 'purge1');
1710          $this->assertFalse($definition->has_required_identifiers());
1711          $cache = $factory->create_cache($definition);
1712          $this->assertInstanceOf('cache_application', $cache);
1713          $this->assertTrue($cache->set('test', 'test'));
1714          $this->assertTrue($cache->has('test'));
1715          cache_helper::purge_by_definition('phpunit', 'purge1');
1716          $this->assertFalse($cache->has('test'));
1717  
1718          $factory = cache_factory::instance();
1719          $definition = $factory->create_definition('phpunit', 'purge2');
1720          $this->assertTrue($definition->has_required_identifiers());
1721          $cache = $factory->create_cache($definition);
1722          $this->assertInstanceOf('cache_application', $cache);
1723          $this->assertTrue($cache->set('test', 'test'));
1724          $this->assertTrue($cache->has('test'));
1725          cache_helper::purge_stores_used_by_definition('phpunit', 'purge2');
1726          $this->assertFalse($cache->has('test'));
1727  
1728          try {
1729              cache_helper::purge_by_definition('phpunit', 'purge2');
1730              $this->fail('Should not be able to purge a definition required identifiers without providing them.');
1731          } catch (coding_exception $ex) {
1732              $this->assertContains('Identifier required for cache has not been provided', $ex->getMessage());
1733          }
1734      }
1735  
1736      /**
1737       * Tests that ad-hoc caches are correctly purged with a purge_all call.
1738       */
1739      public function test_purge_all_with_adhoc_caches() {
1740          $cache = \cache::make_from_params(\cache_store::MODE_REQUEST, 'core_cache', 'test');
1741          $cache->set('test', 123);
1742          cache_helper::purge_all();
1743          $this->assertFalse($cache->get('test'));
1744      }
1745  
1746      /**
1747       * Test that the default stores all support searching.
1748       */
1749      public function test_defaults_support_searching() {
1750          $instance = cache_config_testing::instance(true);
1751          $instance->phpunit_add_definition('phpunit/search1', array(
1752              'mode' => cache_store::MODE_APPLICATION,
1753              'component' => 'phpunit',
1754              'area' => 'search1',
1755              'requiresearchable' => true
1756          ));
1757          $instance->phpunit_add_definition('phpunit/search2', array(
1758              'mode' => cache_store::MODE_SESSION,
1759              'component' => 'phpunit',
1760              'area' => 'search2',
1761              'requiresearchable' => true
1762          ));
1763          $instance->phpunit_add_definition('phpunit/search3', array(
1764              'mode' => cache_store::MODE_REQUEST,
1765              'component' => 'phpunit',
1766              'area' => 'search3',
1767              'requiresearchable' => true
1768          ));
1769          $factory = cache_factory::instance();
1770  
1771          // Test application cache is searchable.
1772          $definition = $factory->create_definition('phpunit', 'search1');
1773          $this->assertInstanceOf('cache_definition', $definition);
1774          $this->assertEquals(cache_store::IS_SEARCHABLE, $definition->get_requirements_bin() & cache_store::IS_SEARCHABLE);
1775          $cache = $factory->create_cache($definition);
1776          $this->assertInstanceOf('cache_application', $cache);
1777          $this->assertArrayHasKey('cache_is_searchable', $cache->phpunit_get_store_implements());
1778  
1779          // Test session cache is searchable.
1780          $definition = $factory->create_definition('phpunit', 'search2');
1781          $this->assertInstanceOf('cache_definition', $definition);
1782          $this->assertEquals(cache_store::IS_SEARCHABLE, $definition->get_requirements_bin() & cache_store::IS_SEARCHABLE);
1783          $cache = $factory->create_cache($definition);
1784          $this->assertInstanceOf('cache_session', $cache);
1785          $this->assertArrayHasKey('cache_is_searchable', $cache->phpunit_get_store_implements());
1786  
1787          // Test request cache is searchable.
1788          $definition = $factory->create_definition('phpunit', 'search3');
1789          $this->assertInstanceOf('cache_definition', $definition);
1790          $this->assertEquals(cache_store::IS_SEARCHABLE, $definition->get_requirements_bin() & cache_store::IS_SEARCHABLE);
1791          $cache = $factory->create_cache($definition);
1792          $this->assertInstanceOf('cache_request', $cache);
1793          $this->assertArrayHasKey('cache_is_searchable', $cache->phpunit_get_store_implements());
1794      }
1795  
1796      /**
1797       * Test static acceleration
1798       *
1799       * Note: All the assertGreaterThanOrEqual() in this test should be assertGreaterThan() be because of some microtime()
1800       * resolution problems under some OSs / PHP versions, we are accepting equal as valid outcome. For more info see MDL-57147.
1801       */
1802      public function test_static_acceleration() {
1803          $instance = cache_config_testing::instance();
1804          $instance->phpunit_add_definition('phpunit/accelerated', array(
1805              'mode' => cache_store::MODE_APPLICATION,
1806              'component' => 'phpunit',
1807              'area' => 'accelerated',
1808              'staticacceleration' => true,
1809              'staticaccelerationsize' => 3,
1810          ));
1811          $instance->phpunit_add_definition('phpunit/accelerated2', array(
1812              'mode' => cache_store::MODE_APPLICATION,
1813              'component' => 'phpunit',
1814              'area' => 'accelerated2',
1815              'staticacceleration' => true,
1816              'staticaccelerationsize' => 3,
1817          ));
1818          $instance->phpunit_add_definition('phpunit/accelerated3', array(
1819              'mode' => cache_store::MODE_APPLICATION,
1820              'component' => 'phpunit',
1821              'area' => 'accelerated3',
1822              'staticacceleration' => true,
1823              'staticaccelerationsize' => 3,
1824          ));
1825          $instance->phpunit_add_definition('phpunit/accelerated4', array(
1826              'mode' => cache_store::MODE_APPLICATION,
1827              'component' => 'phpunit',
1828              'area' => 'accelerated4',
1829              'staticacceleration' => true,
1830              'staticaccelerationsize' => 4,
1831          ));
1832          $instance->phpunit_add_definition('phpunit/simpledataarea1', array(
1833              'mode' => cache_store::MODE_APPLICATION,
1834              'component' => 'phpunit',
1835              'area' => 'simpledataarea1',
1836              'staticacceleration' => true,
1837              'simpledata' => false
1838          ));
1839          $instance->phpunit_add_definition('phpunit/simpledataarea2', array(
1840              'mode' => cache_store::MODE_APPLICATION,
1841              'component' => 'phpunit',
1842              'area' => 'simpledataarea2',
1843              'staticacceleration' => true,
1844              'simpledata' => true
1845          ));
1846  
1847          $cache = cache::make('phpunit', 'accelerated');
1848          $this->assertInstanceOf('cache_phpunit_application', $cache);
1849  
1850          // Set and get three elements.
1851          $this->assertTrue($cache->set('a', 'A'));
1852          $this->assertTrue($cache->set('b', 'B'));
1853          $this->assertTrue($cache->set('c', 'C'));
1854          $this->assertEquals('A', $cache->get('a'));
1855          $this->assertEquals(array('b' => 'B', 'c' => 'C'), $cache->get_many(array('b', 'c')));
1856  
1857          // Make sure all items are in static acceleration array.
1858          $this->assertEquals('A', $cache->phpunit_static_acceleration_get('a'));
1859          $this->assertEquals('B', $cache->phpunit_static_acceleration_get('b'));
1860          $this->assertEquals('C', $cache->phpunit_static_acceleration_get('c'));
1861  
1862          // Add new value and make sure it is in cache and it is in array.
1863          $this->assertTrue($cache->set('d', 'D'));
1864          $this->assertEquals('D', $cache->phpunit_static_acceleration_get('d'));
1865          $this->assertEquals('D', $cache->get('d'));
1866  
1867          // Now the least recent accessed item (a) is no longer in acceleration array.
1868          $this->assertFalse($cache->phpunit_static_acceleration_get('a'));
1869          $this->assertEquals('B', $cache->phpunit_static_acceleration_get('b'));
1870          $this->assertEquals('C', $cache->phpunit_static_acceleration_get('c'));
1871  
1872          // Adding and deleting element.
1873          $this->assertTrue($cache->set('a', 'A'));
1874          $this->assertTrue($cache->delete('a'));
1875          $this->assertFalse($cache->phpunit_static_acceleration_get('a'));
1876          $this->assertFalse($cache->has('a'));
1877  
1878          // Make sure "purge" deletes from the array as well.
1879          $cache->purge();
1880          $this->assertFalse($cache->phpunit_static_acceleration_get('a'));
1881          $this->assertFalse($cache->phpunit_static_acceleration_get('b'));
1882          $this->assertFalse($cache->phpunit_static_acceleration_get('c'));
1883          $this->assertFalse($cache->phpunit_static_acceleration_get('d'));
1884          $this->assertFalse($cache->phpunit_static_acceleration_get('e'));
1885  
1886          // Check that the array holds the last accessed items by get/set.
1887          $this->assertTrue($cache->set('a', 'A'));
1888          $this->assertTrue($cache->set('b', 'B'));
1889          $this->assertTrue($cache->set('c', 'C'));
1890          $this->assertTrue($cache->set('d', 'D'));
1891          $this->assertTrue($cache->set('e', 'E'));
1892          $this->assertFalse($cache->phpunit_static_acceleration_get('a'));
1893          $this->assertFalse($cache->phpunit_static_acceleration_get('b'));
1894          $this->assertEquals('C', $cache->phpunit_static_acceleration_get('c'));
1895          $this->assertEquals('D', $cache->phpunit_static_acceleration_get('d'));
1896          $this->assertEquals('E', $cache->phpunit_static_acceleration_get('e'));
1897  
1898          // Store a cacheable_object, get many times and ensure each time wake_for_cache is used.
1899          // Both get and get_many are tested.  Two cache entries are used to ensure the times aren't
1900          // confused with multiple calls to get()/get_many().
1901          $startmicrotime = microtime(true);
1902          $cacheableobject = new cache_phpunit_dummy_object(1, 1, $startmicrotime);
1903          $cacheableobject2 = new cache_phpunit_dummy_object(2, 2, $startmicrotime);
1904          $this->assertTrue($cache->set('a', $cacheableobject));
1905          $this->assertTrue($cache->set('b', $cacheableobject2));
1906          $staticaccelerationreturntime = $cache->phpunit_static_acceleration_get('a')->propertytime;
1907          $staticaccelerationreturntimeb = $cache->phpunit_static_acceleration_get('b')->propertytime;
1908          $this->assertGreaterThanOrEqual($startmicrotime, $staticaccelerationreturntime, 'Restore time of static must be newer.');
1909  
1910          // Reset the static cache without resetting backing store.
1911          $cache->phpunit_static_acceleration_purge();
1912  
1913          // Get the value from the backend store, populating the static cache.
1914          $cachevalue = $cache->get('a');
1915          $this->assertInstanceOf('cache_phpunit_dummy_object', $cachevalue);
1916          $this->assertGreaterThanOrEqual($staticaccelerationreturntime, $cachevalue->propertytime);
1917          $backingstorereturntime = $cachevalue->propertytime;
1918  
1919          $results = $cache->get_many(array('b'));
1920          $this->assertInstanceOf('cache_phpunit_dummy_object', $results['b']);
1921          $this->assertGreaterThanOrEqual($staticaccelerationreturntimeb, $results['b']->propertytime);
1922          $backingstorereturntimeb = $results['b']->propertytime;
1923  
1924          // Obtain the value again and confirm that static cache is using wake_from_cache.
1925          // Upon failure, the times are not adjusted as wake_from_cache is skipped as the
1926          // value is stored serialized in the static acceleration cache.
1927          $cachevalue = $cache->phpunit_static_acceleration_get('a');
1928          $this->assertInstanceOf('cache_phpunit_dummy_object', $cachevalue);
1929          $this->assertGreaterThanOrEqual($backingstorereturntime, $cachevalue->propertytime);
1930  
1931          $results = $cache->get_many(array('b'));
1932          $this->assertInstanceOf('cache_phpunit_dummy_object', $results['b']);
1933          $this->assertGreaterThanOrEqual($backingstorereturntimeb, $results['b']->propertytime);
1934  
1935          /** @var cache_phpunit_application $cache */
1936          $cache = cache::make('phpunit', 'accelerated2');
1937          $this->assertInstanceOf('cache_phpunit_application', $cache);
1938  
1939          // Check that the array holds the last accessed items by get/set.
1940          $this->assertTrue($cache->set('a', 'A'));
1941          $this->assertTrue($cache->set('b', 'B'));
1942          $this->assertTrue($cache->set('c', 'C'));
1943          $this->assertTrue($cache->set('d', 'D'));
1944          $this->assertTrue($cache->set('e', 'E'));
1945          // Current keys in the array: c, d, e.
1946          $this->assertEquals('C', $cache->phpunit_static_acceleration_get('c'));
1947          $this->assertEquals('D', $cache->phpunit_static_acceleration_get('d'));
1948          $this->assertEquals('E', $cache->phpunit_static_acceleration_get('e'));
1949          $this->assertFalse($cache->phpunit_static_acceleration_get('a'));
1950          $this->assertFalse($cache->phpunit_static_acceleration_get('b'));
1951  
1952          $this->assertEquals('A', $cache->get('a'));
1953          // Current keys in the array: d, e, a.
1954          $this->assertEquals('D', $cache->phpunit_static_acceleration_get('d'));
1955          $this->assertEquals('E', $cache->phpunit_static_acceleration_get('e'));
1956          $this->assertEquals('A', $cache->phpunit_static_acceleration_get('a'));
1957          $this->assertFalse($cache->phpunit_static_acceleration_get('b'));
1958          $this->assertFalse($cache->phpunit_static_acceleration_get('c'));
1959  
1960          // Current keys in the array: d, e, a.
1961          $this->assertEquals(array('c' => 'C'), $cache->get_many(array('c')));
1962          // Current keys in the array: e, a, c.
1963          $this->assertEquals('E', $cache->phpunit_static_acceleration_get('e'));
1964          $this->assertEquals('A', $cache->phpunit_static_acceleration_get('a'));
1965          $this->assertEquals('C', $cache->phpunit_static_acceleration_get('c'));
1966          $this->assertFalse($cache->phpunit_static_acceleration_get('b'));
1967          $this->assertFalse($cache->phpunit_static_acceleration_get('d'));
1968  
1969  
1970          $cache = cache::make('phpunit', 'accelerated3');
1971          $this->assertInstanceOf('cache_phpunit_application', $cache);
1972  
1973          // Check that the array holds the last accessed items by get/set.
1974          $this->assertTrue($cache->set('a', 'A'));
1975          $this->assertTrue($cache->set('b', 'B'));
1976          $this->assertTrue($cache->set('c', 'C'));
1977          $this->assertTrue($cache->set('d', 'D'));
1978          $this->assertTrue($cache->set('e', 'E'));
1979          $this->assertFalse($cache->phpunit_static_acceleration_get('a'));
1980          $this->assertFalse($cache->phpunit_static_acceleration_get('b'));
1981          $this->assertEquals('C', $cache->phpunit_static_acceleration_get('c'));
1982          $this->assertEquals('D', $cache->phpunit_static_acceleration_get('d'));
1983          $this->assertEquals('E', $cache->phpunit_static_acceleration_get('e'));
1984  
1985          $this->assertTrue($cache->set('b', 'B2'));
1986          $this->assertFalse($cache->phpunit_static_acceleration_get('a'));
1987          $this->assertEquals('B2', $cache->phpunit_static_acceleration_get('b'));
1988          $this->assertFalse($cache->phpunit_static_acceleration_get('c'));
1989          $this->assertEquals('D', $cache->phpunit_static_acceleration_get('d'));
1990          $this->assertEquals('E', $cache->phpunit_static_acceleration_get('e'));
1991  
1992          $this->assertEquals(2, $cache->set_many(array('b' => 'B3', 'c' => 'C3')));
1993          $this->assertFalse($cache->phpunit_static_acceleration_get('a'));
1994          $this->assertEquals('B3', $cache->phpunit_static_acceleration_get('b'));
1995          $this->assertEquals('C3', $cache->phpunit_static_acceleration_get('c'));
1996          $this->assertFalse($cache->phpunit_static_acceleration_get('d'));
1997          $this->assertEquals('E', $cache->phpunit_static_acceleration_get('e'));
1998  
1999          $cache = cache::make('phpunit', 'accelerated4');
2000          $this->assertInstanceOf('cache_phpunit_application', $cache);
2001          $this->assertTrue($cache->set('a', 'A'));
2002          $this->assertTrue($cache->set('a', 'A'));
2003          $this->assertTrue($cache->set('a', 'A'));
2004          $this->assertTrue($cache->set('a', 'A'));
2005          $this->assertTrue($cache->set('a', 'A'));
2006          $this->assertTrue($cache->set('a', 'A'));
2007          $this->assertTrue($cache->set('a', 'A'));
2008          $this->assertEquals('A', $cache->phpunit_static_acceleration_get('a'));
2009          $this->assertEquals('A', $cache->get('a'));
2010  
2011          // Setting simpledata to false objects are cloned when retrieving data.
2012          $cache = cache::make('phpunit', 'simpledataarea1');
2013          $notreallysimple = new stdClass();
2014          $notreallysimple->name = 'a';
2015          $cache->set('a', $notreallysimple);
2016          $returnedinstance1 = $cache->get('a');
2017          $returnedinstance2 = $cache->get('a');
2018          $returnedinstance1->name = 'b';
2019          $this->assertEquals('a', $returnedinstance2->name);
2020  
2021          // Setting simpledata to true we assume that data does not contain references.
2022          $cache = cache::make('phpunit', 'simpledataarea2');
2023          $notreallysimple = new stdClass();
2024          $notreallysimple->name = 'a';
2025          $cache->set('a', $notreallysimple);
2026          $returnedinstance1 = $cache->get('a');
2027          $returnedinstance2 = $cache->get('a');
2028          $returnedinstance1->name = 'b';
2029          $this->assertEquals('b', $returnedinstance2->name);
2030      }
2031  
2032      public function test_identifiers_have_separate_caches() {
2033          $cachepg = cache::make('core', 'databasemeta', array('dbfamily' => 'pgsql'));
2034          $cachepg->set(1, 'here');
2035          $cachemy = cache::make('core', 'databasemeta', array('dbfamily' => 'mysql'));
2036          $cachemy->set(2, 'there');
2037          $this->assertEquals('here', $cachepg->get(1));
2038          $this->assertEquals('there', $cachemy->get(2));
2039          $this->assertFalse($cachemy->get(1));
2040      }
2041  
2042      public function test_performance_debug() {
2043          global $CFG;
2044          $this->resetAfterTest(true);
2045          $CFG->perfdebug = 15;
2046  
2047          $instance = cache_config_testing::instance();
2048          $applicationid = 'phpunit/applicationperf';
2049          $instance->phpunit_add_definition($applicationid, array(
2050              'mode' => cache_store::MODE_APPLICATION,
2051              'component' => 'phpunit',
2052              'area' => 'applicationperf'
2053          ));
2054          $sessionid = 'phpunit/sessionperf';
2055          $instance->phpunit_add_definition($sessionid, array(
2056              'mode' => cache_store::MODE_SESSION,
2057              'component' => 'phpunit',
2058              'area' => 'sessionperf'
2059          ));
2060          $requestid = 'phpunit/requestperf';
2061          $instance->phpunit_add_definition($requestid, array(
2062              'mode' => cache_store::MODE_REQUEST,
2063              'component' => 'phpunit',
2064              'area' => 'requestperf'
2065          ));
2066  
2067          $application = cache::make('phpunit', 'applicationperf');
2068          $session = cache::make('phpunit', 'sessionperf');
2069          $request = cache::make('phpunit', 'requestperf');
2070  
2071          // Check that no stats are recorded for these definitions yet.
2072          $stats = cache_helper::get_stats();
2073          $this->assertArrayNotHasKey($applicationid, $stats);
2074          $this->assertArrayHasKey($sessionid, $stats);       // Session cache sets a key on construct.
2075          $this->assertArrayNotHasKey($requestid, $stats);
2076  
2077          // Check that stores register misses.
2078          $this->assertFalse($application->get('missMe'));
2079          $this->assertFalse($application->get('missMe'));
2080          $this->assertFalse($session->get('missMe'));
2081          $this->assertFalse($session->get('missMe'));
2082          $this->assertFalse($session->get('missMe'));
2083          $this->assertFalse($request->get('missMe'));
2084          $this->assertFalse($request->get('missMe'));
2085          $this->assertFalse($request->get('missMe'));
2086          $this->assertFalse($request->get('missMe'));
2087  
2088          $endstats = cache_helper::get_stats();
2089          $this->assertEquals(2, $endstats[$applicationid]['stores']['default_application']['misses']);
2090          $this->assertEquals(0, $endstats[$applicationid]['stores']['default_application']['hits']);
2091          $this->assertEquals(0, $endstats[$applicationid]['stores']['default_application']['sets']);
2092          $this->assertEquals(3, $endstats[$sessionid]['stores']['default_session']['misses']);
2093          $this->assertEquals(0, $endstats[$sessionid]['stores']['default_session']['hits']);
2094          $this->assertEquals(1, $endstats[$sessionid]['stores']['default_session']['sets']);
2095          $this->assertEquals(4, $endstats[$requestid]['stores']['default_request']['misses']);
2096          $this->assertEquals(0, $endstats[$requestid]['stores']['default_request']['hits']);
2097          $this->assertEquals(0, $endstats[$requestid]['stores']['default_request']['sets']);
2098  
2099          $startstats = cache_helper::get_stats();
2100  
2101          // Check that stores register sets.
2102          $this->assertTrue($application->set('setMe1', 1));
2103          $this->assertTrue($application->set('setMe2', 2));
2104          $this->assertTrue($session->set('setMe1', 1));
2105          $this->assertTrue($session->set('setMe2', 2));
2106          $this->assertTrue($session->set('setMe3', 3));
2107          $this->assertTrue($request->set('setMe1', 1));
2108          $this->assertTrue($request->set('setMe2', 2));
2109          $this->assertTrue($request->set('setMe3', 3));
2110          $this->assertTrue($request->set('setMe4', 4));
2111  
2112          $endstats = cache_helper::get_stats();
2113          $this->assertEquals(0, $endstats[$applicationid]['stores']['default_application']['misses'] -
2114                               $startstats[$applicationid]['stores']['default_application']['misses']);
2115          $this->assertEquals(0, $endstats[$applicationid]['stores']['default_application']['hits'] -
2116                               $startstats[$applicationid]['stores']['default_application']['hits']);
2117          $this->assertEquals(2, $endstats[$applicationid]['stores']['default_application']['sets'] -
2118                               $startstats[$applicationid]['stores']['default_application']['sets']);
2119          $this->assertEquals(0, $endstats[$sessionid]['stores']['default_session']['misses'] -
2120                               $startstats[$sessionid]['stores']['default_session']['misses']);
2121          $this->assertEquals(0, $endstats[$sessionid]['stores']['default_session']['hits'] -
2122                               $startstats[$sessionid]['stores']['default_session']['hits']);
2123          $this->assertEquals(3, $endstats[$sessionid]['stores']['default_session']['sets'] -
2124                               $startstats[$sessionid]['stores']['default_session']['sets']);
2125          $this->assertEquals(0, $endstats[$requestid]['stores']['default_request']['misses'] -
2126                               $startstats[$requestid]['stores']['default_request']['misses']);
2127          $this->assertEquals(0, $endstats[$requestid]['stores']['default_request']['hits'] -
2128                               $startstats[$requestid]['stores']['default_request']['hits']);
2129          $this->assertEquals(4, $endstats[$requestid]['stores']['default_request']['sets'] -
2130                               $startstats[$requestid]['stores']['default_request']['sets']);
2131  
2132          $startstats = cache_helper::get_stats();
2133  
2134          // Check that stores register hits.
2135          $this->assertEquals($application->get('setMe1'), 1);
2136          $this->assertEquals($application->get('setMe2'), 2);
2137          $this->assertEquals($session->get('setMe1'), 1);
2138          $this->assertEquals($session->get('setMe2'), 2);
2139          $this->assertEquals($session->get('setMe3'), 3);
2140          $this->assertEquals($request->get('setMe1'), 1);
2141          $this->assertEquals($request->get('setMe2'), 2);
2142          $this->assertEquals($request->get('setMe3'), 3);
2143          $this->assertEquals($request->get('setMe4'), 4);
2144  
2145          $endstats = cache_helper::get_stats();
2146          $this->assertEquals(0, $endstats[$applicationid]['stores']['default_application']['misses'] -
2147                               $startstats[$applicationid]['stores']['default_application']['misses']);
2148          $this->assertEquals(2, $endstats[$applicationid]['stores']['default_application']['hits'] -
2149                               $startstats[$applicationid]['stores']['default_application']['hits']);
2150          $this->assertEquals(0, $endstats[$applicationid]['stores']['default_application']['sets'] -
2151                               $startstats[$applicationid]['stores']['default_application']['sets']);
2152          $this->assertEquals(0, $endstats[$sessionid]['stores']['default_session']['misses'] -
2153                               $startstats[$sessionid]['stores']['default_session']['misses']);
2154          $this->assertEquals(3, $endstats[$sessionid]['stores']['default_session']['hits'] -
2155                               $startstats[$sessionid]['stores']['default_session']['hits']);
2156          $this->assertEquals(0, $endstats[$sessionid]['stores']['default_session']['sets'] -
2157                               $startstats[$sessionid]['stores']['default_session']['sets']);
2158          $this->assertEquals(0, $endstats[$requestid]['stores']['default_request']['misses'] -
2159                               $startstats[$requestid]['stores']['default_request']['misses']);
2160          $this->assertEquals(4, $endstats[$requestid]['stores']['default_request']['hits'] -
2161                               $startstats[$requestid]['stores']['default_request']['hits']);
2162          $this->assertEquals(0, $endstats[$requestid]['stores']['default_request']['sets'] -
2163                               $startstats[$requestid]['stores']['default_request']['sets']);
2164  
2165          $startstats = cache_helper::get_stats();
2166  
2167          // Check that stores register through get_many.
2168          $application->get_many(array('setMe1', 'setMe2'));
2169          $session->get_many(array('setMe1', 'setMe2', 'setMe3'));
2170          $request->get_many(array('setMe1', 'setMe2', 'setMe3', 'setMe4'));
2171  
2172          $endstats = cache_helper::get_stats();
2173          $this->assertEquals(0, $endstats[$applicationid]['stores']['default_application']['misses'] -
2174                               $startstats[$applicationid]['stores']['default_application']['misses']);
2175          $this->assertEquals(2, $endstats[$applicationid]['stores']['default_application']['hits'] -
2176                               $startstats[$applicationid]['stores']['default_application']['hits']);
2177          $this->assertEquals(0, $endstats[$applicationid]['stores']['default_application']['sets'] -
2178                               $startstats[$applicationid]['stores']['default_application']['sets']);
2179          $this->assertEquals(0, $endstats[$sessionid]['stores']['default_session']['misses'] -
2180                               $startstats[$sessionid]['stores']['default_session']['misses']);
2181          $this->assertEquals(3, $endstats[$sessionid]['stores']['default_session']['hits'] -
2182                               $startstats[$sessionid]['stores']['default_session']['hits']);
2183          $this->assertEquals(0, $endstats[$sessionid]['stores']['default_session']['sets'] -
2184                               $startstats[$sessionid]['stores']['default_session']['sets']);
2185          $this->assertEquals(0, $endstats[$requestid]['stores']['default_request']['misses'] -
2186                               $startstats[$requestid]['stores']['default_request']['misses']);
2187          $this->assertEquals(4, $endstats[$requestid]['stores']['default_request']['hits'] -
2188                               $startstats[$requestid]['stores']['default_request']['hits']);
2189          $this->assertEquals(0, $endstats[$requestid]['stores']['default_request']['sets'] -
2190                               $startstats[$requestid]['stores']['default_request']['sets']);
2191  
2192          $startstats = cache_helper::get_stats();
2193  
2194          // Check that stores register through set_many.
2195          $this->assertEquals(2, $application->set_many(['setMe1' => 1, 'setMe2' => 2]));
2196          $this->assertEquals(3, $session->set_many(['setMe1' => 1, 'setMe2' => 2, 'setMe3' => 3]));
2197          $this->assertEquals(4, $request->set_many(['setMe1' => 1, 'setMe2' => 2, 'setMe3' => 3, 'setMe4' => 4]));
2198  
2199          $endstats = cache_helper::get_stats();
2200  
2201          $this->assertEquals(0, $endstats[$applicationid]['stores']['default_application']['misses'] -
2202              $startstats[$applicationid]['stores']['default_application']['misses']);
2203          $this->assertEquals(0, $endstats[$applicationid]['stores']['default_application']['hits'] -
2204              $startstats[$applicationid]['stores']['default_application']['hits']);
2205          $this->assertEquals(2, $endstats[$applicationid]['stores']['default_application']['sets'] -
2206              $startstats[$applicationid]['stores']['default_application']['sets']);
2207          $this->assertEquals(0, $endstats[$sessionid]['stores']['default_session']['misses'] -
2208              $startstats[$sessionid]['stores']['default_session']['misses']);
2209          $this->assertEquals(0, $endstats[$sessionid]['stores']['default_session']['hits'] -
2210              $startstats[$sessionid]['stores']['default_session']['hits']);
2211          $this->assertEquals(3, $endstats[$sessionid]['stores']['default_session']['sets'] -
2212              $startstats[$sessionid]['stores']['default_session']['sets']);
2213          $this->assertEquals(0, $endstats[$requestid]['stores']['default_request']['misses'] -
2214              $startstats[$requestid]['stores']['default_request']['misses']);
2215          $this->assertEquals(0, $endstats[$requestid]['stores']['default_request']['hits'] -
2216              $startstats[$requestid]['stores']['default_request']['hits']);
2217          $this->assertEquals(4, $endstats[$requestid]['stores']['default_request']['sets'] -
2218              $startstats[$requestid]['stores']['default_request']['sets']);
2219      }
2220  
2221      public function test_static_cache() {
2222          global $CFG;
2223          $this->resetAfterTest(true);
2224          $CFG->perfdebug = 15;
2225  
2226          // Create cache store with static acceleration.
2227          $instance = cache_config_testing::instance();
2228          $applicationid = 'phpunit/applicationperf';
2229          $instance->phpunit_add_definition($applicationid, array(
2230              'mode' => cache_store::MODE_APPLICATION,
2231              'component' => 'phpunit',
2232              'area' => 'applicationperf',
2233              'simplekeys' => true,
2234              'staticacceleration' => true,
2235              'staticaccelerationsize' => 3
2236          ));
2237  
2238          $application = cache::make('phpunit', 'applicationperf');
2239  
2240          // Check that stores register sets.
2241          $this->assertTrue($application->set('setMe1', 1));
2242          $this->assertTrue($application->set('setMe2', 0));
2243          $this->assertTrue($application->set('setMe3', array()));
2244          $this->assertTrue($application->get('setMe1') !== false);
2245          $this->assertTrue($application->get('setMe2') !== false);
2246          $this->assertTrue($application->get('setMe3') !== false);
2247  
2248          // Check that the static acceleration worked, even on empty arrays and the number 0.
2249          $endstats = cache_helper::get_stats();
2250          $this->assertEquals(0, $endstats[$applicationid]['stores']['** static accel. **']['misses']);
2251          $this->assertEquals(3, $endstats[$applicationid]['stores']['** static accel. **']['hits']);
2252      }
2253  
2254      public function test_performance_debug_off() {
2255          global $CFG;
2256          $this->resetAfterTest(true);
2257          $CFG->perfdebug = 7;
2258  
2259          $instance = cache_config_testing::instance();
2260          $applicationid = 'phpunit/applicationperfoff';
2261          $instance->phpunit_add_definition($applicationid, array(
2262              'mode' => cache_store::MODE_APPLICATION,
2263              'component' => 'phpunit',
2264              'area' => 'applicationperfoff'
2265          ));
2266          $sessionid = 'phpunit/sessionperfoff';
2267          $instance->phpunit_add_definition($sessionid, array(
2268              'mode' => cache_store::MODE_SESSION,
2269              'component' => 'phpunit',
2270              'area' => 'sessionperfoff'
2271          ));
2272          $requestid = 'phpunit/requestperfoff';
2273          $instance->phpunit_add_definition($requestid, array(
2274              'mode' => cache_store::MODE_REQUEST,
2275              'component' => 'phpunit',
2276              'area' => 'requestperfoff'
2277          ));
2278  
2279          $application = cache::make('phpunit', 'applicationperfoff');
2280          $session = cache::make('phpunit', 'sessionperfoff');
2281          $request = cache::make('phpunit', 'requestperfoff');
2282  
2283          // Check that no stats are recorded for these definitions yet.
2284          $stats = cache_helper::get_stats();
2285          $this->assertArrayNotHasKey($applicationid, $stats);
2286          $this->assertArrayNotHasKey($sessionid, $stats);
2287          $this->assertArrayNotHasKey($requestid, $stats);
2288  
2289          // Trigger cache misses, cache sets and cache hits.
2290          $this->assertFalse($application->get('missMe'));
2291          $this->assertTrue($application->set('setMe', 1));
2292          $this->assertEquals(1, $application->get('setMe'));
2293          $this->assertFalse($session->get('missMe'));
2294          $this->assertTrue($session->set('setMe', 3));
2295          $this->assertEquals(3, $session->get('setMe'));
2296          $this->assertFalse($request->get('missMe'));
2297          $this->assertTrue($request->set('setMe', 4));
2298          $this->assertEquals(4, $request->get('setMe'));
2299  
2300          // Check that no stats are being recorded for these definitions.
2301          $endstats = cache_helper::get_stats();
2302          $this->assertArrayNotHasKey($applicationid, $endstats);
2303          $this->assertArrayNotHasKey($sessionid, $endstats);
2304          $this->assertArrayNotHasKey($requestid, $endstats);
2305      }
2306  
2307      /**
2308       * Tests session cache event purge and subsequent visit in the same request.
2309       *
2310       * This test simulates a cache being created, a value being set, then the value being purged.
2311       * A subsequent use of the same cache is started in the same request which fills the cache.
2312       * A new request is started a short time later.
2313       * The cache should be filled.
2314       */
2315      public function test_session_event_purge_same_second() {
2316          $instance = cache_config_testing::instance();
2317          $instance->phpunit_add_definition('phpunit/eventpurgetest', array(
2318              'mode' => cache_store::MODE_SESSION,
2319              'component' => 'phpunit',
2320              'area' => 'eventpurgetest',
2321              'invalidationevents' => array(
2322                  'crazyevent',
2323              )
2324          ));
2325  
2326          // Create the cache, set a value, and immediately purge it by event.
2327          $cache = cache::make('phpunit', 'eventpurgetest');
2328          $cache->set('testkey1', 'test data 1');
2329          $this->assertEquals('test data 1', $cache->get('testkey1'));
2330          cache_helper::purge_by_event('crazyevent');
2331          $this->assertFalse($cache->get('testkey1'));
2332  
2333          // Set up the cache again in the same request and add a new value back in.
2334          $factory = \cache_factory::instance();
2335          $factory->reset_cache_instances();
2336          $cache = cache::make('phpunit', 'eventpurgetest');
2337          $cache->set('testkey1', 'test data 2');
2338          $this->assertEquals('test data 2', $cache->get('testkey1'));
2339  
2340          // Trick the cache into thinking that this is a new request.
2341          cache_phpunit_cache::simulate_new_request();
2342          $factory = \cache_factory::instance();
2343          $factory->reset_cache_instances();
2344  
2345          // Set up the cache again.
2346          // This is a subsequent request at a new time, so we instead the invalidation time will be checked.
2347          // The invalidation time should match the last purged time and the cache will not be re-purged.
2348          $cache = cache::make('phpunit', 'eventpurgetest');
2349          $this->assertEquals('test data 2', $cache->get('testkey1'));
2350      }
2351  
2352      /**
2353       * Test that values set in different sessions are stored with different key prefixes.
2354       */
2355      public function test_session_distinct_storage_key() {
2356          $this->resetAfterTest();
2357  
2358          // Prepare a dummy session cache configuration.
2359          $config = cache_config_testing::instance();
2360          $config->phpunit_add_definition('phpunit/test_session_distinct_storage_key', array(
2361              'mode' => cache_store::MODE_SESSION,
2362              'component' => 'phpunit',
2363              'area' => 'test_session_distinct_storage_key'
2364          ));
2365  
2366          // First anonymous user's session cache.
2367          cache_phpunit_session::phpunit_mockup_session_id('foo');
2368          $this->setUser(0);
2369          $cache1 = cache::make('phpunit', 'test_session_distinct_storage_key');
2370  
2371          // Reset cache instances to emulate a new request.
2372          cache_factory::instance()->reset_cache_instances();
2373  
2374          // Another anonymous user's session cache.
2375          cache_phpunit_session::phpunit_mockup_session_id('bar');
2376          $this->setUser(0);
2377          $cache2 = cache::make('phpunit', 'test_session_distinct_storage_key');
2378  
2379          cache_factory::instance()->reset_cache_instances();
2380  
2381          // Guest user's session cache.
2382          cache_phpunit_session::phpunit_mockup_session_id('baz');
2383          $this->setGuestUser();
2384          $cache3 = cache::make('phpunit', 'test_session_distinct_storage_key');
2385  
2386          cache_factory::instance()->reset_cache_instances();
2387  
2388          // Same guest user's session cache but in another browser window.
2389          cache_phpunit_session::phpunit_mockup_session_id('baz');
2390          $this->setGuestUser();
2391          $cache4 = cache::make('phpunit', 'test_session_distinct_storage_key');
2392  
2393          // Assert that different PHP session implies different key prefix for storing values.
2394          $this->assertNotEquals($cache1->phpunit_get_key_prefix(), $cache2->phpunit_get_key_prefix());
2395  
2396          // Assert that same PHP session implies same key prefix for storing values.
2397          $this->assertEquals($cache3->phpunit_get_key_prefix(), $cache4->phpunit_get_key_prefix());
2398      }
2399  }