[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/cache/stores/memcached/tests/ -> memcached_test.php (source)

   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   * Memcached unit tests.
  19   *
  20   * If you wish to use these unit tests all you need to do is add the following definition to
  21   * your config.php file.
  22   *
  23   * define('TEST_CACHESTORE_MEMCACHED_TESTSERVERS', '127.0.0.1:11211');
  24   *
  25   * @package    cachestore_memcached
  26   * @copyright  2013 Sam Hemelryk
  27   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  28   */
  29  
  30  defined('MOODLE_INTERNAL') || die();
  31  
  32  // Include the necessary evils.
  33  global $CFG;
  34  require_once($CFG->dirroot.'/cache/tests/fixtures/stores.php');
  35  require_once($CFG->dirroot.'/cache/stores/memcached/lib.php');
  36  
  37  /**
  38   * Memcached unit test class.
  39   *
  40   * @package    cachestore_memcached
  41   * @copyright  2013 Sam Hemelryk
  42   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  43   */
  44  class cachestore_memcached_test extends cachestore_tests {
  45      /**
  46       * Returns the memcached class name
  47       * @return string
  48       */
  49      protected function get_class_name() {
  50          return 'cachestore_memcached';
  51      }
  52  
  53      /**
  54       * Tests the valid keys to ensure they work.
  55       */
  56      public function test_valid_keys() {
  57          if (!cachestore_memcached::are_requirements_met() || !defined('TEST_CACHESTORE_MEMCACHED_TESTSERVERS')) {
  58              $this->markTestSkipped('Could not test cachestore_memcached. Requirements are not met.');
  59          }
  60  
  61          $this->resetAfterTest(true);
  62  
  63          $definition = cache_definition::load_adhoc(cache_store::MODE_APPLICATION, 'cachestore_memcached', 'phpunit_test');
  64          $instance = cachestore_memcached::initialise_unit_test_instance($definition);
  65  
  66          if (!$instance) { // Something prevented memcached store to be inited (extension, TEST_CACHESTORE_MEMCACHED_TESTSERVERS...).
  67              $this->markTestSkipped();
  68          }
  69  
  70          $keys = array(
  71              // Alphanumeric.
  72              'abc', 'ABC', '123', 'aB1', '1aB',
  73              // Hyphens.
  74              'a-1', '1-a', '-a1', 'a1-',
  75              // Underscores.
  76              'a_1', '1_a', '_a1', 'a1_'
  77          );
  78  
  79          // Set some keys.
  80          foreach ($keys as $key) {
  81              $this->assertTrue($instance->set($key, $key), "Failed to set key `$key`");
  82          }
  83  
  84          // Get some keys.
  85          foreach ($keys as $key) {
  86              $this->assertEquals($key, $instance->get($key), "Failed to get key `$key`");
  87          }
  88  
  89          // Try get many.
  90          $values = $instance->get_many($keys);
  91          foreach ($values as $key => $value) {
  92              $this->assertEquals($key, $value);
  93          }
  94  
  95          // Reset a key.
  96          $this->assertTrue($instance->set($keys[0], 'New'), "Failed to reset key `$key`");
  97          $this->assertEquals('New', $instance->get($keys[0]), "Failed to get reset key `$key`");
  98  
  99          // Delete and check that we can't retrieve.
 100          foreach ($keys as $key) {
 101              $this->assertTrue($instance->delete($key), "Failed to delete key `$key`");
 102              $this->assertFalse($instance->get($key), "Retrieved deleted key `$key`");
 103          }
 104  
 105          // Try set many, and check that count is correct.
 106          $many = array();
 107          foreach ($keys as $key) {
 108              $many[] = array('key' => $key, 'value' => $key);
 109          }
 110          $returncount = $instance->set_many($many);
 111          $this->assertEquals(count($many), $returncount, 'Set many count didn\'t match');
 112  
 113          // Check keys retrieved with get_many.
 114          $values = $instance->get_many($keys);
 115          foreach ($keys as $key) {
 116              $this->assertTrue(isset($values[$key]), "Failed to get_many key `$key`");
 117              $this->assertEquals($key, $values[$key], "Failed to match get_many key `$key`");
 118          }
 119  
 120          // Delete many, make sure count matches.
 121          $returncount = $instance->delete_many($keys);
 122          $this->assertEquals(count($many), $returncount, 'Delete many count didn\'t match');
 123  
 124          // Check that each key was deleted.
 125          foreach ($keys as $key) {
 126              $this->assertFalse($instance->get($key), "Retrieved many deleted key `$key`");
 127          }
 128  
 129          // Set the keys again.
 130          $returncount = $instance->set_many($many);
 131          $this->assertEquals(count($many), $returncount, 'Set many count didn\'t match');
 132  
 133          // Purge.
 134          $this->assertTrue($instance->purge(), 'Failure to purge');
 135  
 136          // Delete and check that we can't retrieve.
 137          foreach ($keys as $key) {
 138              $this->assertFalse($instance->get($key), "Retrieved purged key `$key`");
 139          }
 140      }
 141  
 142      /**
 143       * Tests the clustering feature.
 144       */
 145      public function test_clustered() {
 146          if (!cachestore_memcached::are_requirements_met() || !defined('TEST_CACHESTORE_MEMCACHED_TESTSERVERS')) {
 147              $this->markTestSkipped('Could not test cachestore_memcached. Requirements are not met.');
 148          }
 149  
 150          $this->resetAfterTest(true);
 151  
 152          $testservers = explode("\n", trim(TEST_CACHESTORE_MEMCACHED_TESTSERVERS));
 153  
 154          if (count($testservers) < 2) {
 155              $this->markTestSkipped('Could not test clustered memcached, there are not enough test servers defined.');
 156          }
 157  
 158          // Use the first server as our primary.
 159          // We need to set a prefix for all, otherwise it uses the name, which will not match between connections.
 160          set_config('testprefix', 'pre', 'cachestore_memcached');
 161          // We need to set a name, otherwise we get a reused connection.
 162          set_config('testname', 'cluster', 'cachestore_memcached');
 163          set_config('testservers', $testservers[0], 'cachestore_memcached');
 164          set_config('testsetservers', TEST_CACHESTORE_MEMCACHED_TESTSERVERS, 'cachestore_memcached');
 165          set_config('testclustered', true, 'cachestore_memcached');
 166  
 167          // First and instance that we can use to test the second server.
 168          $definition = cache_definition::load_adhoc(cache_store::MODE_APPLICATION, 'cachestore_memcached', 'phpunit_test');
 169          $instance = cachestore_memcached::initialise_test_instance($definition);
 170  
 171          if (!$instance) {
 172              $this->markTestSkipped();
 173          }
 174  
 175          // Now we are going to setup a connection to each independent server.
 176          set_config('testclustered', false, 'cachestore_memcached');
 177          set_config('testsetservers', '', 'cachestore_memcached');
 178          $checkinstances = array();
 179          foreach ($testservers as $testserver) {
 180              // We need to set a name, otherwise we get a reused connection.
 181              set_config('testname', $testserver, 'cachestore_memcached');
 182              set_config('testservers', $testserver, 'cachestore_memcached');
 183              $checkinstance = cachestore_memcached::initialise_test_instance($definition);
 184              if (!$checkinstance) {
 185                  $this->markTestSkipped();
 186              }
 187              $checkinstances[] = $checkinstance;
 188          }
 189  
 190          $keys = array(
 191              // Alphanumeric.
 192              'abc', 'ABC', '123', 'aB1', '1aB',
 193              // Hyphens.
 194              'a-1', '1-a', '-a1', 'a1-',
 195              // Underscores.
 196              'a_1', '1_a', '_a1', 'a1_'
 197          );
 198  
 199          // Set each key.
 200          foreach ($keys as $key) {
 201              $this->assertTrue($instance->set($key, $key), "Failed to set key `$key`");
 202          }
 203  
 204          // Check each key.
 205          foreach ($keys as $key) {
 206              $this->assertEquals($key, $instance->get($key), "Failed to get key `$key`");
 207              foreach ($checkinstances as $id => $checkinstance) {
 208                  $this->assertEquals($key, $checkinstance->get($key), "Failed to get key `$key` from server $id");
 209              }
 210          }
 211  
 212          // Reset a key.
 213          $this->assertTrue($instance->set($keys[0], 'New'), "Failed to reset key `$key`");
 214          $this->assertEquals('New', $instance->get($keys[0]), "Failed to get reset key `$key`");
 215          foreach ($checkinstances as $id => $checkinstance) {
 216              $this->assertEquals('New', $checkinstance->get($keys[0]), "Failed to get reset key `$key` from server $id");
 217          }
 218  
 219          // Delete and check that we can't retrieve.
 220          foreach ($keys as $key) {
 221              $this->assertTrue($instance->delete($key), "Failed to delete key `$key`");
 222              $this->assertFalse($instance->get($key), "Retrieved deleted key `$key`");
 223              foreach ($checkinstances as $id => $checkinstance) {
 224                  $this->assertFalse($checkinstance->get($key), "Retrieved deleted key `$key` from server $id");
 225              }
 226          }
 227  
 228          // Try set many, and check that count is correct.
 229          $many = array();
 230          foreach ($keys as $key) {
 231              $many[] = array('key' => $key, 'value' => $key);
 232          }
 233          $returncount = $instance->set_many($many);
 234          $this->assertEquals(count($many), $returncount, 'Set many count didn\'t match');
 235  
 236          // Check keys retrieved with get_many.
 237          $values = $instance->get_many($keys);
 238          foreach ($keys as $key) {
 239              $this->assertTrue(isset($values[$key]), "Failed to get_many key `$key`");
 240              $this->assertEquals($key, $values[$key], "Failed to match get_many key `$key`");
 241          }
 242          foreach ($checkinstances as $id => $checkinstance) {
 243              $values = $checkinstance->get_many($keys);
 244              foreach ($keys as $key) {
 245                  $this->assertTrue(isset($values[$key]), "Failed to get_many key `$key` from server $id");
 246                  $this->assertEquals($key, $values[$key], "Failed to get_many key `$key` from server $id");
 247              }
 248          }
 249  
 250          // Delete many, make sure count matches.
 251          $returncount = $instance->delete_many($keys);
 252          $this->assertEquals(count($many), $returncount, 'Delete many count didn\'t match');
 253  
 254          // Check that each key was deleted.
 255          foreach ($keys as $key) {
 256              $this->assertFalse($instance->get($key), "Retrieved many deleted key `$key`");
 257              foreach ($checkinstances as $id => $checkinstance) {
 258                  $this->assertFalse($checkinstance->get($key), "Retrieved many deleted key `$key` from server $id");
 259              }
 260          }
 261  
 262          // Set the keys again.
 263          $returncount = $instance->set_many($many);
 264          $this->assertEquals(count($many), $returncount, 'Set many count didn\'t match');
 265  
 266          // Purge.
 267          $this->assertTrue($instance->purge(), 'Failure to purge');
 268  
 269          // Delete and check that we can't retrieve.
 270          foreach ($keys as $key) {
 271              $this->assertFalse($instance->get($key), "Retrieved purged key `$key`");
 272              foreach ($checkinstances as $id => $checkinstance) {
 273                  $this->assertFalse($checkinstance->get($key), "Retrieved purged key `$key` from server 2");
 274              }
 275          }
 276      }
 277  
 278      /**
 279       * Tests that memcached cache store doesn't just flush everything and instead deletes only what belongs to it
 280       * when it is marked as a shared cache.
 281       */
 282      public function test_multi_use_compatibility() {
 283          if (!cachestore_memcached::are_requirements_met() || !defined('TEST_CACHESTORE_MEMCACHED_TESTSERVERS')) {
 284              $this->markTestSkipped('Could not test cachestore_memcached. Requirements are not met.');
 285          }
 286  
 287          $definition = cache_definition::load_adhoc(cache_store::MODE_APPLICATION, 'cachestore_memcached', 'phpunit_test');
 288          $cachestore = $this->create_test_cache_with_config($definition, array('isshared' => true));
 289          $connection = new Memcached(crc32(__METHOD__));
 290          $connection->addServers($this->get_servers(TEST_CACHESTORE_MEMCACHED_TESTSERVERS));
 291          $connection->setOptions(array(
 292              Memcached::OPT_COMPRESSION => true,
 293              Memcached::OPT_SERIALIZER => Memcached::SERIALIZER_PHP,
 294              Memcached::OPT_PREFIX_KEY => 'phpunit_',
 295              Memcached::OPT_BUFFER_WRITES => false
 296          ));
 297  
 298          // We must flush first to make sure nothing is there.
 299          $connection->flush();
 300  
 301          // Test the cachestore.
 302          $this->assertFalse($cachestore->get('test'));
 303          $this->assertTrue($cachestore->set('test', 'cachestore'));
 304          $this->assertSame('cachestore', $cachestore->get('test'));
 305  
 306          // Test the connection.
 307          $this->assertFalse($connection->get('test'));
 308          $this->assertEquals(Memcached::RES_NOTFOUND, $connection->getResultCode());
 309          $this->assertTrue($connection->set('test', 'connection'));
 310          $this->assertSame('connection', $connection->get('test'));
 311  
 312          // Test both again and make sure the values are correct.
 313          $this->assertSame('cachestore', $cachestore->get('test'));
 314          $this->assertSame('connection', $connection->get('test'));
 315  
 316          // Purge the cachestore and check the connection was not purged.
 317          $this->assertTrue($cachestore->purge());
 318          $this->assertFalse($cachestore->get('test'));
 319          $this->assertSame('connection', $connection->get('test'));
 320      }
 321  
 322      /**
 323       * Tests that memcached cache store flushes entire cache when it is using a dedicated cache.
 324       */
 325      public function test_dedicated_cache() {
 326          if (!cachestore_memcached::are_requirements_met() || !defined('TEST_CACHESTORE_MEMCACHED_TESTSERVERS')) {
 327              $this->markTestSkipped('Could not test cachestore_memcached. Requirements are not met.');
 328          }
 329  
 330          $definition = cache_definition::load_adhoc(cache_store::MODE_APPLICATION, 'cachestore_memcached', 'phpunit_test');
 331          $cachestore = $this->create_test_cache_with_config($definition, array('isshared' => false));
 332          $connection = new Memcached(crc32(__METHOD__));
 333          $connection->addServers($this->get_servers(TEST_CACHESTORE_MEMCACHED_TESTSERVERS));
 334          $connection->setOptions(array(
 335              Memcached::OPT_COMPRESSION => true,
 336              Memcached::OPT_SERIALIZER => Memcached::SERIALIZER_PHP,
 337              Memcached::OPT_PREFIX_KEY => 'phpunit_',
 338              Memcached::OPT_BUFFER_WRITES => false
 339          ));
 340  
 341          // We must flush first to make sure nothing is there.
 342          $connection->flush();
 343  
 344          // Test the cachestore.
 345          $this->assertFalse($cachestore->get('test'));
 346          $this->assertTrue($cachestore->set('test', 'cachestore'));
 347          $this->assertSame('cachestore', $cachestore->get('test'));
 348  
 349          // Test the connection.
 350          $this->assertFalse($connection->get('test'));
 351          $this->assertEquals(Memcached::RES_NOTFOUND, $connection->getResultCode());
 352          $this->assertTrue($connection->set('test', 'connection'));
 353          $this->assertSame('connection', $connection->get('test'));
 354  
 355          // Test both again and make sure the values are correct.
 356          $this->assertSame('cachestore', $cachestore->get('test'));
 357          $this->assertSame('connection', $connection->get('test'));
 358  
 359          // Purge the cachestore and check the connection was also purged.
 360          $this->assertTrue($cachestore->purge());
 361          $this->assertFalse($cachestore->get('test'));
 362          $this->assertFalse($connection->get('test'));
 363      }
 364  
 365      /**
 366       * Given a server string this returns an array of servers.
 367       *
 368       * @param string $serverstring
 369       * @return array
 370       */
 371      public function get_servers($serverstring) {
 372          $servers = array();
 373          foreach (explode("\n", $serverstring) as $server) {
 374              if (!is_array($server)) {
 375                  $server = explode(':', $server, 3);
 376              }
 377              if (!array_key_exists(1, $server)) {
 378                  $server[1] = 11211;
 379                  $server[2] = 100;
 380              } else if (!array_key_exists(2, $server)) {
 381                  $server[2] = 100;
 382              }
 383              $servers[] = $server;
 384          }
 385          return $servers;
 386      }
 387  
 388      /**
 389       * Creates a test instance for unit tests.
 390       * @param cache_definition $definition
 391       * @param array $configuration
 392       * @return null|cachestore_memcached
 393       */
 394      private function create_test_cache_with_config(cache_definition $definition, $configuration = array()) {
 395          $class = $this->get_class_name();
 396  
 397          if (!$class::are_requirements_met()) {
 398              return null;
 399          }
 400          if (!defined('TEST_CACHESTORE_MEMCACHED_TESTSERVERS')) {
 401              return null;
 402          }
 403  
 404          $configuration['servers'] = explode("\n", TEST_CACHESTORE_MEMCACHED_TESTSERVERS);
 405  
 406          $store = new $class('Test memcached', $configuration);
 407          $store->initialise($definition);
 408  
 409          return $store;
 410      }
 411  }


Generated: Thu Aug 11 10:00:09 2016 Cross-referenced by PHPXref 0.7.1