Upgraded drupal core with security updates
[yaffs-website] / web / core / tests / Drupal / Tests / Core / Config / ConfigTest.php
1 <?php
2
3 namespace Drupal\Tests\Core\Config;
4
5 use Drupal\Core\DependencyInjection\ContainerBuilder;
6 use Drupal\Core\Render\Markup;
7 use Drupal\Tests\UnitTestCase;
8 use Drupal\Core\Config\Config;
9 use Drupal\Core\Config\ConfigValueException;
10
11 /**
12  * Tests the Config.
13  *
14  * @coversDefaultClass \Drupal\Core\Config\Config
15  *
16  * @group Config
17  *
18  * @see \Drupal\Core\Config\Config
19  */
20 class ConfigTest extends UnitTestCase {
21
22   /**
23    * Config.
24    *
25    * @var \Drupal\Core\Config\Config
26    */
27   protected $config;
28
29   /**
30    * Storage.
31    *
32    * @var \Drupal\Core\Config\StorageInterface|\PHPUnit_Framework_MockObject_MockObject
33    */
34   protected $storage;
35
36   /**
37    * Event Dispatcher.
38    *
39    * @var \Symfony\Component\EventDispatcher\EventDispatcherInterface|\PHPUnit_Framework_MockObject_MockObject
40    */
41   protected $eventDispatcher;
42
43   /**
44    * Typed Config.
45    *
46    * @var \Drupal\Core\Config\TypedConfigManagerInterface|\PHPUnit_Framework_MockObject_MockObject
47    */
48   protected $typedConfig;
49
50   /**
51    * The mocked cache tags invalidator.
52    *
53    * @var \Drupal\Core\Cache\CacheTagsInvalidatorInterface|\PHPUnit_Framework_MockObject_MockObject
54    */
55   protected $cacheTagsInvalidator;
56
57   protected function setUp() {
58     $this->storage = $this->getMock('Drupal\Core\Config\StorageInterface');
59     $this->eventDispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface');
60     $this->typedConfig = $this->getMock('\Drupal\Core\Config\TypedConfigManagerInterface');
61     $this->config = new Config('config.test', $this->storage, $this->eventDispatcher, $this->typedConfig);
62     $this->cacheTagsInvalidator = $this->getMock('Drupal\Core\Cache\CacheTagsInvalidatorInterface');
63
64     $container = new ContainerBuilder();
65     $container->set('cache_tags.invalidator', $this->cacheTagsInvalidator);
66     \Drupal::setContainer($container);
67   }
68
69   /**
70    * @covers ::setName
71    * @dataProvider setNameProvider
72    */
73   public function testSetName($name) {
74     // Set the name.
75     $this->config->setName($name);
76
77     // Check that the name has been set correctly.
78     $this->assertEquals($name, $this->config->getName());
79
80     // Check that the name validates.
81     // Should throw \Drupal\Core\Config\ConfigNameException if invalid.
82     $this->config->validateName($name);
83   }
84
85   /**
86    * Provides config names to test.
87    *
88    * @see \Drupal\Tests\Core\Config\ConfigTest::testSetName()
89    */
90   public function setNameProvider() {
91     return [
92       // Valid name with dot.
93       [
94         'test.name',
95       ],
96       // Maximum length.
97       [
98         'test.' . str_repeat('a', Config::MAX_NAME_LENGTH - 5),
99       ],
100     ];
101   }
102
103   /**
104    * @covers ::isNew
105    */
106   public function testIsNew() {
107     // Config should be new by default.
108     $this->assertTrue($this->config->isNew());
109
110     // Config is no longer new once saved.
111     $this->config->save();
112     $this->assertFalse($this->config->isNew());
113   }
114
115   /**
116    * @covers ::setData
117    * @dataProvider nestedDataProvider
118    */
119   public function testSetData($data) {
120     $this->config->setData($data);
121     $this->assertEquals($data, $this->config->getRawData());
122     $this->assertConfigDataEquals($data);
123   }
124
125   /**
126    * @covers ::save
127    * @dataProvider nestedDataProvider
128    */
129   public function testSaveNew($data) {
130     $this->cacheTagsInvalidator->expects($this->never())
131       ->method('invalidateTags');
132
133     // Set initial data.
134     $this->config->setData($data);
135
136     // Check that original data has not been set yet.
137     foreach ($data as $key => $value) {
138       $this->assertNull($this->config->getOriginal($key, FALSE));
139     }
140
141     // Save so that the original data is set.
142     $config = $this->config->save();
143
144     // Check that returned $config is instance of Config.
145     $this->assertInstanceOf('\Drupal\Core\Config\Config', $config);
146
147     // Check that the original data it saved.
148     $this->assertOriginalConfigDataEquals($data, TRUE);
149   }
150
151   /**
152    * @covers ::save
153    * @dataProvider nestedDataProvider
154    */
155   public function testSaveExisting($data) {
156     $this->cacheTagsInvalidator->expects($this->once())
157       ->method('invalidateTags')
158       ->with(['config:config.test']);
159
160     // Set initial data.
161     $this->config->setData($data);
162     $this->config->save();
163
164     // Update.
165     $new_data = $data;
166     $new_data['a']['d'] = 2;
167     $this->config->setData($new_data);
168     $this->config->save();
169     $this->assertOriginalConfigDataEquals($new_data, TRUE);
170   }
171
172   /**
173    * @covers ::setModuleOverride
174    * @covers ::setSettingsOverride
175    * @covers ::getOriginal
176    * @dataProvider overrideDataProvider
177    */
178   public function testOverrideData($data, $module_data, $setting_data) {
179     // Set initial data.
180     $this->config->setData($data);
181
182     // Check original data was set correctly.
183     $this->assertConfigDataEquals($data);
184
185     // Save so that the original data is stored.
186     $this->config->save();
187
188     // Set module override data and check value before and after save.
189     $this->config->setModuleOverride($module_data);
190     $this->assertConfigDataEquals($module_data);
191     $this->config->save();
192     $this->assertConfigDataEquals($module_data);
193
194     // Set setting override data and check value before and after save.
195     $this->config->setSettingsOverride($setting_data);
196     $this->assertConfigDataEquals($setting_data);
197     $this->config->save();
198     $this->assertConfigDataEquals($setting_data);
199
200     // Set module overrides again to ensure override order is correct.
201     $this->config->setModuleOverride($module_data);
202
203     // Setting data should be overriding module data.
204     $this->assertConfigDataEquals($setting_data);
205     $this->config->save();
206     $this->assertConfigDataEquals($setting_data);
207
208     // Check original data has not changed.
209     $this->assertOriginalConfigDataEquals($data, FALSE);
210
211     // Check setting overrides are returned with $apply_overrides = TRUE.
212     $this->assertOriginalConfigDataEquals($setting_data, TRUE);
213
214     // Check that $apply_overrides defaults to TRUE.
215     foreach ($setting_data as $key => $value) {
216       $config_value = $this->config->getOriginal($key);
217       $this->assertEquals($value, $config_value);
218     }
219   }
220
221   /**
222    * @covers ::set
223    * @dataProvider nestedDataProvider
224    */
225   public function testSetValue($data) {
226     foreach ($data as $key => $value) {
227       $this->config->set($key, $value);
228     }
229     $this->assertConfigDataEquals($data);
230   }
231
232   /**
233    * @covers ::set
234    */
235   public function testSetValidation() {
236     $this->setExpectedException(ConfigValueException::class);
237     $this->config->set('testData', ['dot.key' => 1]);
238   }
239
240   /**
241    * @covers ::set
242    */
243   public function testSetIllegalOffsetValue() {
244     // Set a single value.
245     $this->config->set('testData', 1);
246
247     // Attempt to treat the single value as a nested item.
248     $this->setExpectedException(\PHPUnit_Framework_Error_Warning::class);
249     $this->config->set('testData.illegalOffset', 1);
250   }
251
252   /**
253    * @covers ::initWithData
254    * @dataProvider nestedDataProvider
255    */
256   public function testInitWithData($data) {
257     $config = $this->config->initWithData($data);
258
259     // Should return the Config object.
260     $this->assertInstanceOf('\Drupal\Core\Config\Config', $config);
261
262     // Check config is not new.
263     $this->assertEquals(FALSE, $this->config->isNew());
264
265     // Check that data value was set correctly.
266     $this->assertConfigDataEquals($data);
267
268     // Check that original data was set.
269     $this->assertOriginalConfigDataEquals($data, TRUE);
270
271     // Check without applying overrides.
272     $this->assertOriginalConfigDataEquals($data, FALSE);
273   }
274
275   /**
276    * @covers ::clear
277    * @dataProvider simpleDataProvider
278    */
279   public function testClear($data) {
280     foreach ($data as $key => $value) {
281       // Check that values are cleared.
282       $this->config->set($key, $value);
283       $this->assertEquals($value, $this->config->get($key));
284       $this->config->clear($key);
285       $this->assertNull($this->config->get($key));
286     }
287   }
288
289   /**
290    * @covers ::clear
291    * @dataProvider nestedDataProvider
292    */
293   public function testNestedClear($data) {
294     foreach ($data as $key => $value) {
295       // Check that values are cleared.
296       $this->config->set($key, $value);
297       // Check each nested value.
298       foreach ($value as $nested_key => $nested_value) {
299         $full_nested_key = $key . '.' . $nested_key;
300         $this->assertEquals($nested_value, $this->config->get($full_nested_key));
301         $this->config->clear($full_nested_key);
302         $this->assertNull($this->config->get($full_nested_key));
303       }
304     }
305   }
306
307   /**
308    * @covers ::delete
309    * @dataProvider overrideDataProvider
310    */
311   public function testDelete($data, $module_data) {
312     $this->cacheTagsInvalidator->expects($this->once())
313       ->method('invalidateTags')
314       ->with(['config:config.test']);
315
316     // Set initial data.
317     foreach ($data as $key => $value) {
318       $this->config->set($key, $value);
319     }
320     // Set overrides.
321     $this->config->setModuleOverride($module_data);
322
323     // Save.
324     $this->config->save();
325
326     // Check that original data is still correct.
327     $this->assertOriginalConfigDataEquals($data, FALSE);
328
329     // Check overrides have been set.
330     $this->assertConfigDataEquals($module_data);
331     $this->assertOriginalConfigDataEquals($module_data, TRUE);
332
333     // Check that config is new.
334     $this->assertFalse($this->config->isNew());
335
336     // Delete.
337     $this->config->delete();
338
339     // Check object properties have been reset.
340     $this->assertTrue($this->config->isNew());
341     foreach ($data as $key => $value) {
342       $this->assertEmpty($this->config->getOriginal($key, FALSE));
343     }
344
345     // Check that overrides have persisted.
346     foreach ($module_data as $key => $value) {
347       $this->assertConfigDataEquals($module_data);
348       $this->assertOriginalConfigDataEquals($module_data, TRUE);
349     }
350   }
351
352   /**
353    * @covers ::merge
354    * @dataProvider mergeDataProvider
355    */
356   public function testMerge($data, $data_to_merge, $merged_data) {
357     // Set initial data.
358     $this->config->setData($data);
359
360     // Data to merge.
361     $this->config->merge($data_to_merge);
362
363     // Check that data has merged correctly.
364     $this->assertEquals($merged_data, $this->config->getRawData());
365   }
366
367   /**
368    * Provides data to test merges.
369    *
370    * @see \Drupal\Tests\Core\Config\ConfigTest::testMerge()
371    */
372   public function mergeDataProvider() {
373     return [
374       [
375         // Data.
376         ['a' => 1, 'b' => 2, 'c' => ['d' => 3]],
377         // Data to merge.
378         ['a' => 2, 'e' => 4, 'c' => ['f' => 5]],
379         // Data merged.
380         ['a' => 2, 'b' => 2, 'c' => ['d' => 3, 'f' => 5], 'e' => 4],
381       ],
382     ];
383   }
384
385   /**
386    * @covers ::validateName
387    * @dataProvider validateNameProvider
388    */
389   public function testValidateNameException($name, $exception_message) {
390     $this->setExpectedException('\Drupal\Core\Config\ConfigNameException', $exception_message);
391     $this->config->validateName($name);
392   }
393
394   /**
395    * @covers ::getCacheTags
396    */
397   public function testGetCacheTags() {
398     $this->assertSame(['config:' . $this->config->getName()], $this->config->getCacheTags());
399   }
400
401   /**
402    * Provides data to test name validation.
403    *
404    * @see \Drupal\Tests\Core\Config\ConfigTest::testValidateNameException()
405    */
406   public function validateNameProvider() {
407     $return = [
408       // Name missing namespace (dot).
409       [
410         'MissingNamespace',
411         'Missing namespace in Config object name MissingNamespace.',
412       ],
413       // Exceeds length (max length plus an extra dot).
414       [
415         str_repeat('a', Config::MAX_NAME_LENGTH) . ".",
416         'Config object name ' . str_repeat('a', Config::MAX_NAME_LENGTH) . '. exceeds maximum allowed length of ' . Config::MAX_NAME_LENGTH . ' characters.',
417       ],
418     ];
419     // Name must not contain : ? * < > " ' / \
420     foreach ([':', '?', '*', '<', '>', '"', "'", '/', '\\'] as $char) {
421       $name = 'name.' . $char;
422       $return[] = [
423         $name,
424         "Invalid character in Config object name $name.",
425       ];
426     }
427     return $return;
428   }
429
430   /**
431    * Provides override data.
432    *
433    * @see \Drupal\Tests\Core\Config\ConfigTest::testOverrideData()
434    * @see \Drupal\Tests\Core\Config\ConfigTest::testDelete()
435    */
436   public function overrideDataProvider() {
437     return [
438       [
439         // Original data.
440         [
441           'a' => 'originalValue',
442         ],
443         // Module overrides.
444         [
445           'a' => 'moduleValue',
446         ],
447         // Setting overrides.
448         [
449           'a' => 'settingValue',
450         ],
451       ],
452     ];
453   }
454
455   /**
456    * Provides simple test data.
457    *
458    * @see \Drupal\Tests\Core\Config\ConfigTest::testClear()
459    */
460   public function simpleDataProvider() {
461     return [
462       [
463         [
464           'a' => '1',
465           'b' => '2',
466           'c' => '3',
467         ],
468       ],
469     ];
470   }
471
472   /**
473    * Provides nested test data.
474    *
475    * @see \Drupal\Tests\Core\Config\ConfigTest::testSetData()
476    * @see \Drupal\Tests\Core\Config\ConfigTest::testSave()
477    * @see \Drupal\Tests\Core\Config\ConfigTest::testSetValue()
478    * @see \Drupal\Tests\Core\Config\ConfigTest::testInitWithData()
479    * @see \Drupal\Tests\Core\Config\ConfigTest::testNestedClear()
480    */
481   public function nestedDataProvider() {
482     return [
483       [
484         [
485           'a' => [
486             'd' => 1,
487           ],
488           'b' => [
489             'e' => 2,
490           ],
491           'c' => [
492             'f' => 3,
493           ],
494         ],
495       ],
496     ];
497   }
498
499   /**
500    * Asserts all config data equals $data provided.
501    *
502    * @param array $data
503    *   Config data to be checked.
504    */
505   public function assertConfigDataEquals($data) {
506     foreach ($data as $key => $value) {
507       $this->assertEquals($value, $this->config->get($key));
508     }
509   }
510
511   /**
512    * Asserts all original config data equals $data provided.
513    *
514    * @param array $data
515    *   Config data to be checked.
516    * @param bool $apply_overrides
517    *   Apply any overrides to the original data.
518    */
519   public function assertOriginalConfigDataEquals($data, $apply_overrides) {
520     foreach ($data as $key => $value) {
521       $config_value = $this->config->getOriginal($key, $apply_overrides);
522       $this->assertEquals($value, $config_value);
523     }
524   }
525
526   /**
527    * @covers ::setData
528    * @covers ::set
529    * @covers ::initWithData
530    */
531   public function testSafeStringHandling() {
532     // Safe strings are cast when using ::set().
533     $safe_string = Markup::create('bar');
534     $this->config->set('foo', $safe_string);
535     $this->assertSame('bar', $this->config->get('foo'));
536     $this->config->set('foo', ['bar' => $safe_string]);
537     $this->assertSame('bar', $this->config->get('foo.bar'));
538
539     // Safe strings are cast when using ::setData().
540     $this->config->setData(['bar' => $safe_string]);
541     $this->assertSame('bar', $this->config->get('bar'));
542
543     // Safe strings are not cast when using ::initWithData().
544     $this->config->initWithData(['bar' => $safe_string]);
545     $this->assertSame($safe_string, $this->config->get('bar'));
546   }
547
548 }