ConfigStorageTestBase.php 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. <?php
  2. namespace Drupal\KernelTests\Core\Config\Storage;
  3. use Drupal\KernelTests\KernelTestBase;
  4. /**
  5. * Base class for testing storage operations.
  6. *
  7. * All configuration storages are expected to behave identically in
  8. * terms of reading, writing, listing, deleting, as well as error handling.
  9. *
  10. * Therefore, storage tests use an uncommon test case class structure;
  11. * the base class defines the test method(s) to execute, which are identical
  12. * for all storages. The storage specific test case classes supply the
  13. * necessary helper methods to interact with the raw/native storage
  14. * directly.
  15. */
  16. abstract class ConfigStorageTestBase extends KernelTestBase {
  17. /**
  18. * @var \Drupal\Core\Config\StorageInterface
  19. */
  20. protected $storage;
  21. /**
  22. * @var \Drupal\Core\Config\StorageInterface
  23. */
  24. protected $invalidStorage;
  25. /**
  26. * Tests storage CRUD operations.
  27. *
  28. * @todo Coverage: Trigger PDOExceptions / Database exceptions.
  29. */
  30. public function testCRUD() {
  31. $name = 'config_test.storage';
  32. // Checking whether a non-existing name exists returns FALSE.
  33. $this->assertIdentical($this->storage->exists($name), FALSE);
  34. // Reading a non-existing name returns FALSE.
  35. $data = $this->storage->read($name);
  36. $this->assertIdentical($data, FALSE);
  37. // Writing data returns TRUE and the data has been written.
  38. $data = ['foo' => 'bar'];
  39. $result = $this->storage->write($name, $data);
  40. $this->assertIdentical($result, TRUE);
  41. $raw_data = $this->read($name);
  42. $this->assertIdentical($raw_data, $data);
  43. // Checking whether an existing name exists returns TRUE.
  44. $this->assertIdentical($this->storage->exists($name), TRUE);
  45. // Writing the identical data again still returns TRUE.
  46. $result = $this->storage->write($name, $data);
  47. $this->assertIdentical($result, TRUE);
  48. // Listing all names returns all.
  49. $names = $this->storage->listAll();
  50. $this->assertContains('system.performance', $names);
  51. $this->assertContains($name, $names);
  52. // Listing all names with prefix returns names with that prefix only.
  53. $names = $this->storage->listAll('config_test.');
  54. $this->assertNotContains('system.performance', $names);
  55. $this->assertContains($name, $names);
  56. // Rename the configuration storage object.
  57. $new_name = 'config_test.storage_rename';
  58. $this->storage->rename($name, $new_name);
  59. $raw_data = $this->read($new_name);
  60. $this->assertIdentical($raw_data, $data);
  61. // Rename it back so further tests work.
  62. $this->storage->rename($new_name, $name);
  63. // Deleting an existing name returns TRUE.
  64. $result = $this->storage->delete($name);
  65. $this->assertIdentical($result, TRUE);
  66. // Deleting a non-existing name returns FALSE.
  67. $result = $this->storage->delete($name);
  68. $this->assertIdentical($result, FALSE);
  69. // Deleting all names with prefix deletes the appropriate data and returns
  70. // TRUE.
  71. $files = [
  72. 'config_test.test.biff',
  73. 'config_test.test.bang',
  74. 'config_test.test.pow',
  75. ];
  76. foreach ($files as $name) {
  77. $this->storage->write($name, $data);
  78. }
  79. // Test that deleting a prefix that returns no configuration returns FALSE
  80. // because nothing is deleted.
  81. $this->assertFalse($this->storage->deleteAll('some_thing_that_cannot_exist'));
  82. $result = $this->storage->deleteAll('config_test.');
  83. $names = $this->storage->listAll('config_test.');
  84. $this->assertIdentical($result, TRUE);
  85. $this->assertIdentical($names, []);
  86. // Test renaming an object that does not exist returns FALSE.
  87. $this->assertFalse($this->storage->rename('config_test.storage_does_not_exist', 'config_test.storage_does_not_exist_rename'));
  88. // Test renaming to an object that already returns FALSE.
  89. $data = ['foo' => 'bar'];
  90. $this->assertTrue($this->storage->write($name, $data));
  91. $this->assertFalse($this->storage->rename('config_test.storage_does_not_exist', $name));
  92. }
  93. /**
  94. * Tests an invalid storage.
  95. */
  96. public function testInvalidStorage() {
  97. $name = 'config_test.storage';
  98. // Write something to the valid storage to prove that the storages do not
  99. // pollute one another.
  100. $data = ['foo' => 'bar'];
  101. $result = $this->storage->write($name, $data);
  102. $this->assertIdentical($result, TRUE);
  103. $raw_data = $this->read($name);
  104. $this->assertIdentical($raw_data, $data);
  105. // Reading from a non-existing storage bin returns FALSE.
  106. $result = $this->invalidStorage->read($name);
  107. $this->assertIdentical($result, FALSE);
  108. // Deleting from a non-existing storage bin throws an exception.
  109. try {
  110. $this->invalidStorage->delete($name);
  111. $this->fail('Exception not thrown upon deleting from a non-existing storage bin.');
  112. }
  113. catch (\Exception $e) {
  114. // An exception occurred as expected; just continue.
  115. }
  116. // Listing on a non-existing storage bin returns an empty array.
  117. $result = $this->invalidStorage->listAll();
  118. $this->assertIdentical($result, []);
  119. // Getting all collections on a non-existing storage bin return an empty
  120. // array.
  121. $this->assertSame([], $this->invalidStorage->getAllCollectionNames());
  122. // Writing to a non-existing storage bin creates the bin.
  123. $this->invalidStorage->write($name, ['foo' => 'bar']);
  124. $result = $this->invalidStorage->read($name);
  125. $this->assertIdentical($result, ['foo' => 'bar']);
  126. }
  127. /**
  128. * Tests storage writing and reading data preserving data type.
  129. */
  130. public function testDataTypes() {
  131. $name = 'config_test.types';
  132. $data = [
  133. 'array' => [],
  134. 'boolean' => TRUE,
  135. 'exp' => 1.2e+34,
  136. 'float' => 3.14159,
  137. 'hex' => 0xC,
  138. 'int' => 99,
  139. 'octal' => 0775,
  140. 'string' => 'string',
  141. 'string_int' => '1',
  142. ];
  143. $result = $this->storage->write($name, $data);
  144. $this->assertIdentical($result, TRUE);
  145. $read_data = $this->storage->read($name);
  146. $this->assertIdentical($read_data, $data);
  147. }
  148. /**
  149. * Tests that the storage supports collections.
  150. */
  151. public function testCollection() {
  152. $name = 'config_test.storage';
  153. $data = ['foo' => 'bar'];
  154. $result = $this->storage->write($name, $data);
  155. $this->assertIdentical($result, TRUE);
  156. $this->assertSame($data, $this->storage->read($name));
  157. // Create configuration in a new collection.
  158. $new_storage = $this->storage->createCollection('collection.sub.new');
  159. $this->assertFalse($new_storage->exists($name));
  160. $this->assertEqual([], $new_storage->listAll());
  161. $this->assertFalse($new_storage->delete($name));
  162. $this->assertFalse($new_storage->deleteAll('config_test.'));
  163. $this->assertFalse($new_storage->deleteAll());
  164. $this->assertFalse($new_storage->rename($name, 'config_test.another_name'));
  165. $new_storage->write($name, $data);
  166. $this->assertIdentical($result, TRUE);
  167. $this->assertSame($data, $new_storage->read($name));
  168. $this->assertEqual([$name], $new_storage->listAll());
  169. $this->assertTrue($new_storage->exists($name));
  170. $new_data = ['foo' => 'baz'];
  171. $new_storage->write($name, $new_data);
  172. $this->assertIdentical($result, TRUE);
  173. $this->assertSame($new_data, $new_storage->read($name));
  174. // Create configuration in another collection.
  175. $another_storage = $this->storage->createCollection('collection.sub.another');
  176. $this->assertFalse($another_storage->exists($name));
  177. $this->assertEqual([], $another_storage->listAll());
  178. $another_storage->write($name, $new_data);
  179. $this->assertIdentical($result, TRUE);
  180. $this->assertSame($new_data, $another_storage->read($name));
  181. $this->assertEqual([$name], $another_storage->listAll());
  182. $this->assertTrue($another_storage->exists($name));
  183. // Create configuration in yet another collection.
  184. $alt_storage = $this->storage->createCollection('alternate');
  185. $alt_storage->write($name, $new_data);
  186. $this->assertIdentical($result, TRUE);
  187. $this->assertSame($new_data, $alt_storage->read($name));
  188. // Switch back to the collection-less mode and check the data still exists
  189. // add has not been touched.
  190. $this->assertSame($data, $this->storage->read($name));
  191. // Check that the getAllCollectionNames() method works.
  192. $this->assertSame(['alternate', 'collection.sub.another', 'collection.sub.new'], $this->storage->getAllCollectionNames());
  193. // Check that the collections are removed when they are empty.
  194. $alt_storage->delete($name);
  195. $this->assertSame(['collection.sub.another', 'collection.sub.new'], $this->storage->getAllCollectionNames());
  196. // Create configuration in collection called 'collection'. This ensures that
  197. // FileStorage's collection storage works regardless of its use of
  198. // subdirectories.
  199. $parent_storage = $this->storage->createCollection('collection');
  200. $this->assertFalse($parent_storage->exists($name));
  201. $this->assertEqual([], $parent_storage->listAll());
  202. $parent_storage->write($name, $new_data);
  203. $this->assertIdentical($result, TRUE);
  204. $this->assertSame($new_data, $parent_storage->read($name));
  205. $this->assertEqual([$name], $parent_storage->listAll());
  206. $this->assertTrue($parent_storage->exists($name));
  207. $this->assertSame(['collection', 'collection.sub.another', 'collection.sub.new'], $this->storage->getAllCollectionNames());
  208. $parent_storage->deleteAll();
  209. $this->assertSame(['collection.sub.another', 'collection.sub.new'], $this->storage->getAllCollectionNames());
  210. // Test operations on a collection emptied through deletion.
  211. $this->assertFalse($parent_storage->exists($name));
  212. $this->assertEqual([], $parent_storage->listAll());
  213. $this->assertFalse($parent_storage->delete($name));
  214. $this->assertFalse($parent_storage->deleteAll('config_test.'));
  215. $this->assertFalse($parent_storage->deleteAll());
  216. $this->assertFalse($parent_storage->rename($name, 'config_test.another_name'));
  217. // Check that the having an empty collection-less storage does not break
  218. // anything. Before deleting check that the previous delete did not affect
  219. // data in another collection.
  220. $this->assertSame($data, $this->storage->read($name));
  221. $this->storage->delete($name);
  222. $this->assertSame(['collection.sub.another', 'collection.sub.new'], $this->storage->getAllCollectionNames());
  223. }
  224. abstract protected function read($name);
  225. abstract protected function insert($name, $data);
  226. abstract protected function update($name, $data);
  227. abstract protected function delete($name);
  228. }