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   * Cache store test fixtures.
  19   *
  20   * @package    core
  21   * @category   cache
  22   * @copyright  2013 Sam Hemelryk
  23   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  24   */
  25  
  26  defined('MOODLE_INTERNAL') || die();
  27  
  28  /**
  29   * An abstract class to make writing unit tests for cache stores very easy.
  30   *
  31   * @package    core
  32   * @category   cache
  33   * @copyright  2013 Sam Hemelryk
  34   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  35   */
  36  abstract class cachestore_tests extends advanced_testcase {
  37  
  38      /**
  39       * Returns the class name for the store.
  40       *
  41       * @return string
  42       */
  43      abstract protected function get_class_name();
  44  
  45      /**
  46       * Sets up the fixture, for example, open a network connection.
  47       * This method is called before a test is executed.
  48       */
  49      public function setUp() {
  50          $class = $this->get_class_name();
  51          if (!class_exists($class) || !$class::are_requirements_met()) {
  52              $this->markTestSkipped('Could not test '.$class.'. Requirements are not met.');
  53          }
  54          parent::setUp();
  55      }
  56      /**
  57       * Run the unit tests for the store.
  58       */
  59      public function test_test_instance() {
  60          $class = $this->get_class_name();
  61  
  62          $modes = $class::get_supported_modes();
  63          if ($modes & cache_store::MODE_APPLICATION) {
  64              $definition = cache_definition::load_adhoc(cache_store::MODE_APPLICATION, $class, 'phpunit_test');
  65              $instance = new $class($class.'_test', $class::unit_test_configuration());
  66  
  67              if (!$instance->is_ready()) {
  68                  $this->markTestSkipped('Could not test '.$class.'. No test instance configured for application caches.');
  69              } else {
  70                  $instance->initialise($definition);
  71                  $this->run_tests($instance);
  72              }
  73          }
  74          if ($modes & cache_store::MODE_SESSION) {
  75              $definition = cache_definition::load_adhoc(cache_store::MODE_SESSION, $class, 'phpunit_test');
  76              $instance = new $class($class.'_test', $class::unit_test_configuration());
  77  
  78              if (!$instance->is_ready()) {
  79                  $this->markTestSkipped('Could not test '.$class.'. No test instance configured for session caches.');
  80              } else {
  81                  $instance->initialise($definition);
  82                  $this->run_tests($instance);
  83              }
  84          }
  85          if ($modes & cache_store::MODE_REQUEST) {
  86              $definition = cache_definition::load_adhoc(cache_store::MODE_REQUEST, $class, 'phpunit_test');
  87              $instance = new $class($class.'_test', $class::unit_test_configuration());
  88  
  89              if (!$instance->is_ready()) {
  90                  $this->markTestSkipped('Could not test '.$class.'. No test instance configured for request caches.');
  91              } else {
  92                  $instance->initialise($definition);
  93                  $this->run_tests($instance);
  94              }
  95          }
  96      }
  97  
  98      /**
  99       * Test the store for basic functionality.
 100       */
 101      public function run_tests(cache_store $instance) {
 102          $object = new stdClass;
 103          $object->data = 1;
 104  
 105          // Test set with a string.
 106          $this->assertTrue($instance->set('test1', 'test1'));
 107          $this->assertTrue($instance->set('test2', 'test2'));
 108          $this->assertTrue($instance->set('test3', '3'));
 109          $this->assertTrue($instance->set('other3', '3'));
 110  
 111          // Test get with a string.
 112          $this->assertSame('test1', $instance->get('test1'));
 113          $this->assertSame('test2', $instance->get('test2'));
 114          $this->assertSame('3', $instance->get('test3'));
 115  
 116          // Test find and find with prefix if this class implements the searchable interface.
 117          if ($instance->is_searchable()) {
 118              // Extra settings here ignore the return order of the array.
 119              $this->assertEquals(['test3', 'test1', 'test2', 'other3'], $instance->find_all(), '', 0, 1, true);
 120  
 121              // Extra settings here ignore the return order of the array.
 122              $this->assertEquals(['test2', 'test1', 'test3'], $instance->find_by_prefix('test'), '', 0, 1, true);
 123              $this->assertEquals(['test2'], $instance->find_by_prefix('test2'));
 124              $this->assertEquals(['other3'], $instance->find_by_prefix('other'));
 125              $this->assertEquals([], $instance->find_by_prefix('nothere'));
 126          }
 127  
 128          // Test set with an int.
 129          $this->assertTrue($instance->set('test1', 1));
 130          $this->assertTrue($instance->set('test2', 2));
 131  
 132          // Test get with an int.
 133          $this->assertSame(1, $instance->get('test1'));
 134          $this->assertInternalType('int', $instance->get('test1'));
 135          $this->assertSame(2, $instance->get('test2'));
 136          $this->assertInternalType('int', $instance->get('test2'));
 137  
 138          // Test set with a bool.
 139          $this->assertTrue($instance->set('test1', true));
 140  
 141          // Test get with an bool.
 142          $this->assertSame(true, $instance->get('test1'));
 143          $this->assertInternalType('boolean', $instance->get('test1'));
 144  
 145          // Test with an object.
 146          $this->assertTrue($instance->set('obj', $object));
 147          if ($instance::get_supported_features() & cache_store::DEREFERENCES_OBJECTS) {
 148              $this->assertNotSame($object, $instance->get('obj'), 'Objects must be dereferenced when returned.');
 149          }
 150          $this->assertEquals($object, $instance->get('obj'));
 151  
 152          // Test delete.
 153          $this->assertTrue($instance->delete('test1'));
 154          $this->assertTrue($instance->delete('test3'));
 155          $this->assertFalse($instance->delete('test3'));
 156          $this->assertFalse($instance->get('test1'));
 157          $this->assertSame(2, $instance->get('test2'));
 158          $this->assertTrue($instance->set('test1', 'test1'));
 159  
 160          // Test purge.
 161          $this->assertTrue($instance->purge());
 162          $this->assertFalse($instance->get('test1'));
 163          $this->assertFalse($instance->get('test2'));
 164  
 165          // Test set_many.
 166          $outcome = $instance->set_many(array(
 167              array('key' => 'many1', 'value' => 'many1'),
 168              array('key' => 'many2', 'value' => 'many2'),
 169              array('key' => 'many3', 'value' => 'many3'),
 170              array('key' => 'many4', 'value' => 'many4'),
 171              array('key' => 'many5', 'value' => 'many5')
 172          ));
 173          $this->assertSame(5, $outcome);
 174          $this->assertSame('many1', $instance->get('many1'));
 175          $this->assertSame('many5', $instance->get('many5'));
 176          $this->assertFalse($instance->get('many6'));
 177  
 178          // Test get_many.
 179          $result = $instance->get_many(array('many1', 'many3', 'many5', 'many6'));
 180          $this->assertInternalType('array', $result);
 181          $this->assertCount(4, $result);
 182          $this->assertSame(array(
 183              'many1' => 'many1',
 184              'many3' => 'many3',
 185              'many5' => 'many5',
 186              'many6' => false,
 187          ), $result);
 188  
 189          // Test delete_many.
 190          $this->assertSame(3, $instance->delete_many(array('many2', 'many3', 'many4')));
 191          $this->assertSame(2, $instance->delete_many(array('many1', 'many5', 'many6')));
 192      }
 193  }