1<?php 2 3namespace Drupal\Tests\Core\Site; 4 5use Drupal\Core\Site\Settings; 6use Drupal\Tests\Traits\ExpectDeprecationTrait; 7use Drupal\Tests\UnitTestCase; 8use org\bovigo\vfs\vfsStream; 9 10/** 11 * @coversDefaultClass \Drupal\Core\Site\Settings 12 * @group Site 13 */ 14class SettingsTest extends UnitTestCase { 15 16 use ExpectDeprecationTrait; 17 18 /** 19 * Simple settings array to test against. 20 * 21 * @var array 22 */ 23 protected $config = []; 24 25 /** 26 * The class under test. 27 * 28 * @var \Drupal\Core\Site\Settings 29 */ 30 protected $settings; 31 32 /** 33 * @covers ::__construct 34 */ 35 protected function setUp() { 36 $this->config = [ 37 'one' => '1', 38 'two' => '2', 39 'hash_salt' => $this->randomMachineName(), 40 ]; 41 $this->settings = new Settings($this->config); 42 } 43 44 /** 45 * @covers ::get 46 */ 47 public function testGet() { 48 // Test stored settings. 49 $this->assertEquals($this->config['one'], Settings::get('one'), 'The correct setting was not returned.'); 50 $this->assertEquals($this->config['two'], Settings::get('two'), 'The correct setting was not returned.'); 51 52 // Test setting that isn't stored with default. 53 $this->assertEquals('3', Settings::get('three', '3'), 'Default value for a setting not properly returned.'); 54 $this->assertNull(Settings::get('four'), 'Non-null value returned for a setting that should not exist.'); 55 } 56 57 /** 58 * @covers ::getAll 59 */ 60 public function testGetAll() { 61 $this->assertEquals($this->config, Settings::getAll()); 62 } 63 64 /** 65 * @covers ::getInstance 66 */ 67 public function testGetInstance() { 68 $singleton = $this->settings->getInstance(); 69 $this->assertEquals($singleton, $this->settings); 70 } 71 72 /** 73 * Tests Settings::getHashSalt(); 74 * 75 * @covers ::getHashSalt 76 */ 77 public function testGetHashSalt() { 78 $this->assertSame($this->config['hash_salt'], $this->settings->getHashSalt()); 79 } 80 81 /** 82 * Tests Settings::getHashSalt() with no hash salt value. 83 * 84 * @covers ::getHashSalt 85 * 86 * @dataProvider providerTestGetHashSaltEmpty 87 */ 88 public function testGetHashSaltEmpty(array $config) { 89 // Re-create settings with no 'hash_salt' key. 90 $settings = new Settings($config); 91 $this->expectException(\RuntimeException::class); 92 $settings->getHashSalt(); 93 } 94 95 /** 96 * Data provider for testGetHashSaltEmpty. 97 * 98 * @return array 99 */ 100 public function providerTestGetHashSaltEmpty() { 101 return [ 102 [[]], 103 [['hash_salt' => '']], 104 [['hash_salt' => NULL]], 105 ]; 106 } 107 108 /** 109 * Ensures settings cannot be serialized. 110 * 111 * @covers ::__sleep 112 */ 113 public function testSerialize() { 114 $this->expectException(\LogicException::class); 115 serialize(new Settings([])); 116 } 117 118 /** 119 * Tests Settings::getApcuPrefix(). 120 * 121 * @covers ::getApcuPrefix 122 */ 123 public function testGetApcuPrefix() { 124 $settings = new Settings([ 125 'hash_salt' => 123, 126 'apcu_ensure_unique_prefix' => TRUE, 127 ]); 128 $this->assertNotEquals($settings::getApcuPrefix('cache_test', '/test/a'), $settings::getApcuPrefix('cache_test', '/test/b')); 129 130 $settings = new Settings([ 131 'hash_salt' => 123, 132 'apcu_ensure_unique_prefix' => FALSE, 133 ]); 134 $this->assertNotEquals($settings::getApcuPrefix('cache_test', '/test/a'), $settings::getApcuPrefix('cache_test', '/test/b')); 135 } 136 137 /** 138 * Tests that an exception is thrown when settings are not initialized yet. 139 * 140 * @covers ::getInstance 141 */ 142 public function testGetInstanceReflection() { 143 $settings = new Settings([]); 144 145 $class = new \ReflectionClass(Settings::class); 146 $instace_property = $class->getProperty("instance"); 147 $instace_property->setAccessible(TRUE); 148 $instace_property->setValue(NULL); 149 150 $this->expectException(\BadMethodCallException::class); 151 $settings->getInstance(); 152 } 153 154 /** 155 * @runInSeparateProcess 156 * @group legacy 157 * @covers ::__construct 158 * @dataProvider configDirectoriesBcLayerProvider 159 */ 160 public function testConfigDirectoriesBcLayer($settings_file_content, $directory, $expect_deprecation) { 161 global $config_directories; 162 $class_loader = NULL; 163 164 $vfs_root = vfsStream::setup('root'); 165 $sites_directory = vfsStream::newDirectory('sites')->at($vfs_root); 166 vfsStream::newFile('settings.php') 167 ->at($sites_directory) 168 ->setContent($settings_file_content); 169 170 if ($expect_deprecation) { 171 $this->addExpectedDeprecationMessage('$config_directories[\'sync\'] has moved to $settings[\'config_sync_directory\']. See https://www.drupal.org/node/3018145.'); 172 } 173 174 Settings::initialize(vfsStream::url('root'), 'sites', $class_loader); 175 $this->assertSame($directory, Settings::get('config_sync_directory')); 176 $this->assertSame($directory, $config_directories['sync']); 177 } 178 179 /** 180 * Data provider for self::testConfigDirectoriesBcLayer(). 181 */ 182 public function configDirectoriesBcLayerProvider() { 183 $no_config_directories = <<<'EOD' 184<?php 185$settings['config_sync_directory'] = 'foo'; 186EOD; 187 188 $only_config_directories = <<<'EOD' 189<?php 190$config_directories['sync'] = 'bar'; 191EOD; 192 193 $both = <<<'EOD' 194<?php 195$settings['config_sync_directory'] = 'foo'; 196$config_directories['sync'] = 'bar'; 197EOD; 198 199 return [ 200 'Only $settings[\'config_sync_directory\']' => [ 201 $no_config_directories, 202 'foo', 203 FALSE, 204 ], 205 'Only $config_directories' => [$only_config_directories, 'bar', TRUE], 206 'Both' => [$both, 'foo', FALSE], 207 ]; 208 } 209 210 /** 211 * @runInSeparateProcess 212 * @group legacy 213 */ 214 public function testConfigDirectoriesBcLayerEmpty() { 215 global $config_directories; 216 $class_loader = NULL; 217 218 $vfs_root = vfsStream::setup('root'); 219 $sites_directory = vfsStream::newDirectory('sites')->at($vfs_root); 220 vfsStream::newFile('settings.php')->at($sites_directory)->setContent(<<<'EOD' 221<?php 222$settings = []; 223EOD 224 ); 225 226 Settings::initialize(vfsStream::url('root'), 'sites', $class_loader); 227 $this->assertNull(Settings::get('config_sync_directory')); 228 $this->assertNull($config_directories); 229 } 230 231 /** 232 * @runInSeparateProcess 233 * @group legacy 234 */ 235 public function testConfigDirectoriesBcLayerMultiple() { 236 global $config_directories; 237 $class_loader = NULL; 238 239 $vfs_root = vfsStream::setup('root'); 240 $sites_directory = vfsStream::newDirectory('sites')->at($vfs_root); 241 vfsStream::newFile('settings.php')->at($sites_directory)->setContent(<<<'EOD' 242<?php 243$settings['config_sync_directory'] = 'foo'; 244$config_directories['sync'] = 'bar'; 245$config_directories['custom'] = 'custom'; 246EOD 247 ); 248 249 Settings::initialize(vfsStream::url('root'), 'sites', $class_loader); 250 $this->assertSame('foo', Settings::get('config_sync_directory')); 251 $this->assertSame('foo', $config_directories['sync']); 252 $this->assertSame('custom', $config_directories['custom']); 253 } 254 255} 256