3 namespace Drupal\KernelTests\Core\Config\Storage;
5 use Drupal\KernelTests\KernelTestBase;
8 * Base class for testing storage operations.
10 * All configuration storages are expected to behave identically in
11 * terms of reading, writing, listing, deleting, as well as error handling.
13 * Therefore, storage tests use an uncommon test case class structure;
14 * the base class defines the test method(s) to execute, which are identical
15 * for all storages. The storage specific test case classes supply the
16 * necessary helper methods to interact with the raw/native storage
19 abstract class ConfigStorageTestBase extends KernelTestBase {
22 * @var \Drupal\Core\Config\StorageInterface
27 * @var \Drupal\Core\Config\StorageInterface
29 protected $invalidStorage;
32 * Tests storage CRUD operations.
34 * @todo Coverage: Trigger PDOExceptions / Database exceptions.
36 public function testCRUD() {
37 $name = 'config_test.storage';
39 // Checking whether a non-existing name exists returns FALSE.
40 $this->assertIdentical($this->storage->exists($name), FALSE);
42 // Reading a non-existing name returns FALSE.
43 $data = $this->storage->read($name);
44 $this->assertIdentical($data, FALSE);
46 // Writing data returns TRUE and the data has been written.
47 $data = ['foo' => 'bar'];
48 $result = $this->storage->write($name, $data);
49 $this->assertIdentical($result, TRUE);
51 $raw_data = $this->read($name);
52 $this->assertIdentical($raw_data, $data);
54 // Checking whether an existing name exists returns TRUE.
55 $this->assertIdentical($this->storage->exists($name), TRUE);
57 // Writing the identical data again still returns TRUE.
58 $result = $this->storage->write($name, $data);
59 $this->assertIdentical($result, TRUE);
61 // Listing all names returns all.
62 $names = $this->storage->listAll();
63 $this->assertTrue(in_array('system.performance', $names));
64 $this->assertTrue(in_array($name, $names));
66 // Listing all names with prefix returns names with that prefix only.
67 $names = $this->storage->listAll('config_test.');
68 $this->assertFalse(in_array('system.performance', $names));
69 $this->assertTrue(in_array($name, $names));
71 // Rename the configuration storage object.
72 $new_name = 'config_test.storage_rename';
73 $this->storage->rename($name, $new_name);
74 $raw_data = $this->read($new_name);
75 $this->assertIdentical($raw_data, $data);
76 // Rename it back so further tests work.
77 $this->storage->rename($new_name, $name);
79 // Deleting an existing name returns TRUE.
80 $result = $this->storage->delete($name);
81 $this->assertIdentical($result, TRUE);
83 // Deleting a non-existing name returns FALSE.
84 $result = $this->storage->delete($name);
85 $this->assertIdentical($result, FALSE);
87 // Deleting all names with prefix deletes the appropriate data and returns
90 'config_test.test.biff',
91 'config_test.test.bang',
92 'config_test.test.pow',
94 foreach ($files as $name) {
95 $this->storage->write($name, $data);
98 $result = $this->storage->deleteAll('config_test.');
99 $names = $this->storage->listAll('config_test.');
100 $this->assertIdentical($result, TRUE);
101 $this->assertIdentical($names, []);
103 // Test renaming an object that does not exist throws an exception.
105 $this->storage->rename('config_test.storage_does_not_exist', 'config_test.storage_does_not_exist_rename');
107 catch (\Exception $e) {
108 $class = get_class($e);
109 $this->pass($class . ' thrown upon renaming a nonexistent storage bin.');
112 // Test renaming to an object that already exists throws an exception.
114 $this->storage->rename('system.cron', 'system.performance');
116 catch (\Exception $e) {
117 $class = get_class($e);
118 $this->pass($class . ' thrown upon renaming a nonexistent storage bin.');
123 * Tests an invalid storage.
125 public function testInvalidStorage() {
126 $name = 'config_test.storage';
128 // Write something to the valid storage to prove that the storages do not
129 // pollute one another.
130 $data = ['foo' => 'bar'];
131 $result = $this->storage->write($name, $data);
132 $this->assertIdentical($result, TRUE);
134 $raw_data = $this->read($name);
135 $this->assertIdentical($raw_data, $data);
137 // Reading from a non-existing storage bin returns FALSE.
138 $result = $this->invalidStorage->read($name);
139 $this->assertIdentical($result, FALSE);
141 // Deleting from a non-existing storage bin throws an exception.
143 $this->invalidStorage->delete($name);
144 $this->fail('Exception not thrown upon deleting from a non-existing storage bin.');
146 catch (\Exception $e) {
147 $class = get_class($e);
148 $this->pass($class . ' thrown upon deleting from a non-existing storage bin.');
151 // Listing on a non-existing storage bin returns an empty array.
152 $result = $this->invalidStorage->listAll();
153 $this->assertIdentical($result, []);
154 // Writing to a non-existing storage bin creates the bin.
155 $this->invalidStorage->write($name, ['foo' => 'bar']);
156 $result = $this->invalidStorage->read($name);
157 $this->assertIdentical($result, ['foo' => 'bar']);
161 * Tests storage writing and reading data preserving data type.
163 public function testDataTypes() {
164 $name = 'config_test.types';
173 'string' => 'string',
177 $result = $this->storage->write($name, $data);
178 $this->assertIdentical($result, TRUE);
180 $read_data = $this->storage->read($name);
181 $this->assertIdentical($read_data, $data);
185 * Tests that the storage supports collections.
187 public function testCollection() {
188 $name = 'config_test.storage';
189 $data = ['foo' => 'bar'];
190 $result = $this->storage->write($name, $data);
191 $this->assertIdentical($result, TRUE);
192 $this->assertSame($data, $this->storage->read($name));
194 // Create configuration in a new collection.
195 $new_storage = $this->storage->createCollection('collection.sub.new');
196 $this->assertFalse($new_storage->exists($name));
197 $this->assertEqual([], $new_storage->listAll());
198 $new_storage->write($name, $data);
199 $this->assertIdentical($result, TRUE);
200 $this->assertSame($data, $new_storage->read($name));
201 $this->assertEqual([$name], $new_storage->listAll());
202 $this->assertTrue($new_storage->exists($name));
203 $new_data = ['foo' => 'baz'];
204 $new_storage->write($name, $new_data);
205 $this->assertIdentical($result, TRUE);
206 $this->assertSame($new_data, $new_storage->read($name));
208 // Create configuration in another collection.
209 $another_storage = $this->storage->createCollection('collection.sub.another');
210 $this->assertFalse($another_storage->exists($name));
211 $this->assertEqual([], $another_storage->listAll());
212 $another_storage->write($name, $new_data);
213 $this->assertIdentical($result, TRUE);
214 $this->assertSame($new_data, $another_storage->read($name));
215 $this->assertEqual([$name], $another_storage->listAll());
216 $this->assertTrue($another_storage->exists($name));
218 // Create configuration in yet another collection.
219 $alt_storage = $this->storage->createCollection('alternate');
220 $alt_storage->write($name, $new_data);
221 $this->assertIdentical($result, TRUE);
222 $this->assertSame($new_data, $alt_storage->read($name));
224 // Switch back to the collection-less mode and check the data still exists
225 // add has not been touched.
226 $this->assertSame($data, $this->storage->read($name));
228 // Check that the getAllCollectionNames() method works.
229 $this->assertSame(['alternate', 'collection.sub.another', 'collection.sub.new'], $this->storage->getAllCollectionNames());
231 // Check that the collections are removed when they are empty.
232 $alt_storage->delete($name);
233 $this->assertSame(['collection.sub.another', 'collection.sub.new'], $this->storage->getAllCollectionNames());
235 // Create configuration in collection called 'collection'. This ensures that
236 // FileStorage's collection storage works regardless of its use of
238 $parent_storage = $this->storage->createCollection('collection');
239 $this->assertFalse($parent_storage->exists($name));
240 $this->assertEqual([], $parent_storage->listAll());
241 $parent_storage->write($name, $new_data);
242 $this->assertIdentical($result, TRUE);
243 $this->assertSame($new_data, $parent_storage->read($name));
244 $this->assertEqual([$name], $parent_storage->listAll());
245 $this->assertTrue($parent_storage->exists($name));
246 $this->assertSame(['collection', 'collection.sub.another', 'collection.sub.new'], $this->storage->getAllCollectionNames());
247 $parent_storage->deleteAll();
248 $this->assertSame(['collection.sub.another', 'collection.sub.new'], $this->storage->getAllCollectionNames());
250 // Check that the having an empty collection-less storage does not break
251 // anything. Before deleting check that the previous delete did not affect
252 // data in another collection.
253 $this->assertSame($data, $this->storage->read($name));
254 $this->storage->delete($name);
255 $this->assertSame(['collection.sub.another', 'collection.sub.new'], $this->storage->getAllCollectionNames());
258 abstract protected function read($name);
260 abstract protected function insert($name, $data);
262 abstract protected function update($name, $data);
264 abstract protected function delete($name);