StorageTestBase.php 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. <?php
  2. namespace Drupal\KernelTests\Core\KeyValueStore;
  3. use Drupal\KernelTests\KernelTestBase;
  4. /**
  5. * Base class for testing key-value storages.
  6. */
  7. abstract class StorageTestBase extends KernelTestBase {
  8. /**
  9. * An array of random stdClass objects.
  10. *
  11. * @var array
  12. */
  13. protected $objects = [];
  14. /**
  15. * An array of data collection labels.
  16. *
  17. * @var array
  18. */
  19. protected $collections = [];
  20. /**
  21. * Whether we are using an expirable key/value store.
  22. *
  23. * @var bool
  24. */
  25. protected $factory = 'keyvalue';
  26. protected function setUp() {
  27. parent::setUp();
  28. // Define two data collections,
  29. $this->collections = [0 => 'zero', 1 => 'one'];
  30. // Create several objects for testing.
  31. for ($i = 0; $i <= 5; $i++) {
  32. $this->objects[$i] = $this->randomObject();
  33. }
  34. }
  35. /**
  36. * Tests CRUD operations.
  37. */
  38. public function testCRUD() {
  39. $stores = $this->createStorage();
  40. // Verify that each store returns its own collection name.
  41. $this->assertIdentical($stores[0]->getCollectionName(), $this->collections[0]);
  42. $this->assertIdentical($stores[1]->getCollectionName(), $this->collections[1]);
  43. // Verify that an item can be stored.
  44. $stores[0]->set('foo', $this->objects[0]);
  45. $this->assertTrue($stores[0]->has('foo'));
  46. $this->assertIdenticalObject($this->objects[0], $stores[0]->get('foo'));
  47. // Verify that the other collection is not affected.
  48. $this->assertFalse($stores[1]->has('foo'));
  49. $this->assertFalse($stores[1]->get('foo'));
  50. // Verify that an item can be updated.
  51. $stores[0]->set('foo', $this->objects[1]);
  52. $this->assertIdenticalObject($this->objects[1], $stores[0]->get('foo'));
  53. // Verify that the other collection is still not affected.
  54. $this->assertFalse($stores[1]->get('foo'));
  55. // Verify that a collection/name pair is unique.
  56. $stores[1]->set('foo', $this->objects[2]);
  57. $this->assertIdenticalObject($this->objects[1], $stores[0]->get('foo'));
  58. $this->assertIdenticalObject($this->objects[2], $stores[1]->get('foo'));
  59. // Verify that an item can be deleted.
  60. $stores[0]->delete('foo');
  61. $this->assertFalse($stores[0]->has('foo'));
  62. $this->assertFalse($stores[0]->get('foo'));
  63. // Verify that the other collection is not affected.
  64. $this->assertTrue($stores[1]->has('foo'));
  65. $this->assertIdenticalObject($this->objects[2], $stores[1]->get('foo'));
  66. $stores[1]->delete('foo');
  67. $this->assertFalse($stores[1]->get('foo'));
  68. // Verify that multiple items can be stored.
  69. $values = [
  70. 'foo' => $this->objects[3],
  71. 'bar' => $this->objects[4],
  72. ];
  73. $stores[0]->setMultiple($values);
  74. // Verify that multiple items can be retrieved.
  75. $result = $stores[0]->getMultiple(['foo', 'bar']);
  76. foreach ($values as $j => $value) {
  77. $this->assertIdenticalObject($value, $result[$j]);
  78. }
  79. // Verify that the other collection was not affected.
  80. $this->assertFalse($stores[1]->get('foo'));
  81. $this->assertFalse($stores[1]->get('bar'));
  82. // Verify that all items in a collection can be retrieved.
  83. // Ensure that an item with the same name exists in the other collection.
  84. $stores[1]->set('foo', $this->objects[5]);
  85. $result = $stores[0]->getAll();
  86. // Not using assertSame(), since the order is not defined for getAll().
  87. $this->assertEqual(count($result), count($values));
  88. foreach ($result as $key => $value) {
  89. $this->assertEqual($values[$key], $value);
  90. }
  91. // Verify that all items in the other collection are different.
  92. $result = $stores[1]->getAll();
  93. $this->assertEqual($result, ['foo' => $this->objects[5]]);
  94. // Verify that multiple items can be deleted.
  95. $stores[0]->deleteMultiple(array_keys($values));
  96. $this->assertFalse($stores[0]->get('foo'));
  97. $this->assertFalse($stores[0]->get('bar'));
  98. $this->assertFalse($stores[0]->getMultiple(['foo', 'bar']));
  99. // Verify that deleting no items does not cause an error.
  100. $stores[0]->deleteMultiple([]);
  101. // Verify that the item in the other collection still exists.
  102. $this->assertIdenticalObject($this->objects[5], $stores[1]->get('foo'));
  103. }
  104. /**
  105. * Tests expected behavior for non-existing keys.
  106. */
  107. public function testNonExistingKeys() {
  108. $stores = $this->createStorage();
  109. // Verify that a non-existing key returns NULL as value.
  110. $this->assertNull($stores[0]->get('foo'));
  111. // Verify that a non-existing key with a default returns the default.
  112. $this->assertIdentical($stores[0]->get('foo', 'bar'), 'bar');
  113. // Verify that a FALSE value can be stored.
  114. $stores[0]->set('foo', FALSE);
  115. $this->assertIdentical($stores[0]->get('foo'), FALSE);
  116. // Verify that a deleted key returns NULL as value.
  117. $stores[0]->delete('foo');
  118. $this->assertNull($stores[0]->get('foo'));
  119. // Verify that a non-existing key is not returned when getting multiple keys.
  120. $stores[0]->set('bar', 'baz');
  121. $values = $stores[0]->getMultiple(['foo', 'bar']);
  122. $this->assertFalse(isset($values['foo']), "Key 'foo' not found.");
  123. $this->assertIdentical($values['bar'], 'baz');
  124. }
  125. /**
  126. * Tests the setIfNotExists() method.
  127. */
  128. public function testSetIfNotExists() {
  129. $stores = $this->createStorage();
  130. $key = $this->randomMachineName();
  131. // Test that setIfNotExists() succeeds only the first time.
  132. for ($i = 0; $i <= 1; $i++) {
  133. // setIfNotExists() should be TRUE the first time (when $i is 0) and
  134. // FALSE the second time (when $i is 1).
  135. $this->assertEqual(!$i, $stores[0]->setIfNotExists($key, $this->objects[$i]));
  136. $this->assertIdenticalObject($this->objects[0], $stores[0]->get($key));
  137. // Verify that the other collection is not affected.
  138. $this->assertFalse($stores[1]->get($key));
  139. }
  140. // Remove the item and try to set it again.
  141. $stores[0]->delete($key);
  142. $stores[0]->setIfNotExists($key, $this->objects[1]);
  143. // This time it should succeed.
  144. $this->assertIdenticalObject($this->objects[1], $stores[0]->get($key));
  145. // Verify that the other collection is still not affected.
  146. $this->assertFalse($stores[1]->get($key));
  147. }
  148. /**
  149. * Tests the rename operation.
  150. */
  151. public function testRename() {
  152. $stores = $this->createStorage();
  153. $store = $stores[0];
  154. $store->set('old', 'thing');
  155. $this->assertIdentical($store->get('old'), 'thing');
  156. $store->rename('old', 'new');
  157. $this->assertIdentical($store->get('new'), 'thing');
  158. $this->assertNull($store->get('old'));
  159. }
  160. /**
  161. * Creates storage objects for each collection defined for this class.
  162. *
  163. * Storing the storage objects in a class member variable causes a fatal
  164. * exception in DatabaseStorageExpirableTest, because in that situation
  165. * garbage collection is not triggered until the test class itself is
  166. * destructed, after tearDown() has deleted the database tables. Instead,
  167. * create the storage objects locally in each test using this method.
  168. *
  169. * @see \Drupal\system\Tests\KeyValueStore\DatabaseStorageExpirable
  170. * @see \Drupal\Core\KeyValueStore\DatabaseStorageExpirable::garbageCollection()
  171. */
  172. protected function createStorage() {
  173. $stores = [];
  174. foreach ($this->collections as $i => $collection) {
  175. $stores[$i] = $this->container->get($this->factory)->get($collection);
  176. }
  177. return $stores;
  178. }
  179. }