3 * @copyright Copyright (C) 2010-2021, the Friendica project
5 * @license GNU AGPL version 3 or any later version
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Affero General Public License as
9 * published by the Free Software Foundation, either version 3 of the
10 * License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Affero General Public License for more details.
17 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
22 namespace Friendica\Test\src\Core\Config;
24 use DMS\PHPUnitExtensions\ArraySubset\ArraySubsetAsserts;
25 use Friendica\Core\Config\Capability\IManageConfigValues;
26 use Friendica\Core\Config\Repository\Config as ConfigModel;
27 use Friendica\Core\Config\ValueObject\Cache;
28 use Friendica\Test\MockedTest;
29 use Mockery\MockInterface;
32 abstract class ConfigTest extends MockedTest
34 use ArraySubsetAsserts;
36 /** @var ConfigModel|MockInterface */
37 protected $configModel;
40 protected $configCache;
42 /** @var IManageConfigValues */
43 protected $testedConfig;
46 * Assert a config tree
48 * @param string $cat The category to assert
49 * @param array $data The result data array
51 protected function assertConfig(string $cat, array $data)
53 $result = $this->testedConfig->getCache()->getAll();
55 self::assertNotEmpty($result);
56 self::assertArrayHasKey($cat, $result);
57 self::assertArraySubset($data, $result[$cat]);
61 protected function setUp(): void
65 // Create the config model
66 $this->configModel = Mockery::mock(ConfigModel::class);
67 $this->configCache = new Cache();
71 * @return IManageConfigValues
73 abstract public function getInstance();
75 public function dataTests()
78 'string' => ['data' => 'it'],
79 'boolTrue' => ['data' => true],
80 'boolFalse' => ['data' => false],
81 'integer' => ['data' => 235],
82 'decimal' => ['data' => 2.456],
83 'array' => ['data' => ['1', 2, '3', true, false]],
84 'boolIntTrue' => ['data' => 1],
85 'boolIntFalse' => ['Data' => 0],
89 public function dataConfigLoad()
158 * Test the configuration initialization
160 public function testSetUp(array $data)
162 $this->configModel->shouldReceive('isConnected')
166 $this->testedConfig = $this->getInstance();
167 self::assertInstanceOf(Cache::class, $this->testedConfig->getCache());
169 // assert config is loaded everytime
170 self::assertConfig('config', $data['config']);
174 * Test the configuration load() method
179 public function testLoad(array $data, array $load)
181 $this->testedConfig = $this->getInstance();
182 self::assertInstanceOf(Cache::class, $this->testedConfig->getCache());
184 foreach ($load as $loadedCats) {
185 $this->testedConfig->load($loadedCats);
188 // Assert at least loaded cats are loaded
189 foreach ($load as $loadedCats) {
190 self::assertConfig($loadedCats, $data[$loadedCats]);
194 public function dataDoubleLoad()
206 'key1' => 'overwritten!',
212 // load should overwrite values everytime!
213 'key1' => 'overwritten!',
232 'key1' => 'overwritten!',
242 // load should overwrite values everytime!
243 'key1' => 'overwritten!',
258 * Test the configuration load() method with overwrite
260 public function testCacheLoadDouble(array $data1, array $data2, array $expect = [])
262 $this->testedConfig = $this->getInstance();
263 self::assertInstanceOf(Cache::class, $this->testedConfig->getCache());
265 foreach ($data1 as $cat => $data) {
266 $this->testedConfig->load($cat);
269 // Assert at least loaded cats are loaded
270 foreach ($data1 as $cat => $data) {
271 self::assertConfig($cat, $data);
274 foreach ($data2 as $cat => $data) {
275 $this->testedConfig->load($cat);
280 * Test the configuration load without result
282 public function testLoadWrong()
284 $this->configModel->shouldReceive('isConnected')->andReturn(true)->once();
285 $this->configModel->shouldReceive('load')->withAnyArgs()->andReturn([])->once();
287 $this->testedConfig = $this->getInstance();
288 self::assertInstanceOf(Cache::class, $this->testedConfig->getCache());
290 self::assertEmpty($this->testedConfig->getCache()->getAll());
294 * Test the configuration get() and set() methods without adapter
296 * @dataProvider dataTests
298 public function testSetGetWithoutDB($data)
300 $this->configModel->shouldReceive('isConnected')
304 $this->testedConfig = $this->getInstance();
305 self::assertInstanceOf(Cache::class, $this->testedConfig->getCache());
307 self::assertTrue($this->testedConfig->set('test', 'it', $data));
309 self::assertEquals($data, $this->testedConfig->get('test', 'it'));
310 self::assertEquals($data, $this->testedConfig->getCache()->get('test', 'it'));
314 * Test the configuration get() and set() methods with a model/db
316 * @dataProvider dataTests
318 public function testSetGetWithDB($data)
320 $this->configModel->shouldReceive('set')->with('test', 'it', $data)->andReturn(true)->once();
322 $this->testedConfig = $this->getInstance();
323 self::assertInstanceOf(Cache::class, $this->testedConfig->getCache());
325 self::assertTrue($this->testedConfig->set('test', 'it', $data));
327 self::assertEquals($data, $this->testedConfig->get('test', 'it'));
328 self::assertEquals($data, $this->testedConfig->getCache()->get('test', 'it'));
332 * Test the configuration get() method with wrong value and no db
334 public function testGetWrongWithoutDB()
336 $this->testedConfig = $this->getInstance();
337 self::assertInstanceOf(Cache::class, $this->testedConfig->getCache());
340 self::assertNull($this->testedConfig->get('test', 'it'));
342 /// beware that the cache returns '!<unset>!' and not null for a non existing value
343 self::assertNull($this->testedConfig->getCache()->get('test', 'it'));
345 // with default value
346 self::assertEquals('default', $this->testedConfig->get('test', 'it', 'default'));
348 // with default value and refresh
349 self::assertEquals('default', $this->testedConfig->get('test', 'it', 'default', true));
353 * Test the configuration get() method with refresh
355 * @dataProvider dataTests
357 public function testGetWithRefresh($data)
359 $this->configCache->load(['test' => ['it' => 'now']], Cache::SOURCE_FILE);
361 $this->testedConfig = $this->getInstance();
362 self::assertInstanceOf(Cache::class, $this->testedConfig->getCache());
365 self::assertEquals('now', $this->testedConfig->get('test', 'it'));
366 self::assertEquals('now', $this->testedConfig->getCache()->get('test', 'it'));
369 self::assertEquals($data, $this->testedConfig->get('test', 'it', null, true));
370 self::assertEquals($data, $this->testedConfig->getCache()->get('test', 'it'));
372 // without refresh and wrong value and default
373 self::assertEquals('default', $this->testedConfig->get('test', 'not', 'default'));
374 self::assertNull($this->testedConfig->getCache()->get('test', 'not'));
378 * Test the configuration delete() method without a model/db
380 * @dataProvider dataTests
382 public function testDeleteWithoutDB($data)
384 $this->configCache->load(['test' => ['it' => $data]], Cache::SOURCE_FILE);
386 $this->testedConfig = $this->getInstance();
387 self::assertInstanceOf(Cache::class, $this->testedConfig->getCache());
389 self::assertEquals($data, $this->testedConfig->get('test', 'it'));
390 self::assertEquals($data, $this->testedConfig->getCache()->get('test', 'it'));
392 self::assertTrue($this->testedConfig->delete('test', 'it'));
393 self::assertNull($this->testedConfig->get('test', 'it'));
394 self::assertNull($this->testedConfig->getCache()->get('test', 'it'));
396 self::assertEmpty($this->testedConfig->getCache()->getAll());
400 * Test the configuration delete() method with a model/db
402 public function testDeleteWithDB()
404 $this->configCache->load(['test' => ['it' => 'now', 'quarter' => 'true']], Cache::SOURCE_FILE);
406 $this->configModel->shouldReceive('delete')
410 $this->configModel->shouldReceive('delete')
411 ->with('test', 'second')
414 $this->configModel->shouldReceive('delete')
415 ->with('test', 'third')
418 $this->configModel->shouldReceive('delete')
419 ->with('test', 'quarter')
423 $this->testedConfig = $this->getInstance();
424 self::assertInstanceOf(Cache::class, $this->testedConfig->getCache());
426 // directly set the value to the cache
427 $this->testedConfig->getCache()->set('test', 'it', 'now');
429 self::assertEquals('now', $this->testedConfig->get('test', 'it'));
430 self::assertEquals('now', $this->testedConfig->getCache()->get('test', 'it'));
432 // delete from cache only
433 self::assertTrue($this->testedConfig->delete('test', 'it'));
434 // delete from db only
435 self::assertTrue($this->testedConfig->delete('test', 'second'));
437 self::assertFalse($this->testedConfig->delete('test', 'third'));
439 self::assertTrue($this->testedConfig->delete('test', 'quarter'));
441 self::assertEmpty($this->testedConfig->getCache()->getAll());
445 * Test the configuration get() and set() method where the db value has a higher prio than the config file
447 public function testSetGetHighPrio()
449 $this->testedConfig = $this->getInstance();
450 self::assertInstanceOf(Cache::class, $this->testedConfig->getCache());
452 $this->testedConfig->getCache()->set('config', 'test', 'prio', Cache::SOURCE_FILE);
453 self::assertEquals('prio', $this->testedConfig->get('config', 'test'));
455 // now you have to get the new variable entry because of the new set the get refresh succeed as well
456 self::assertTrue($this->testedConfig->set('config', 'test', '123'));
457 self::assertEquals('123', $this->testedConfig->get('config', 'test', '', true));
461 * Test the configuration get() and set() method where the db value has a lower prio than the env
463 public function testSetGetLowPrio()
465 $this->testedConfig = $this->getInstance();
466 self::assertInstanceOf(Cache::class, $this->testedConfig->getCache());
467 self::assertEquals('it', $this->testedConfig->get('config', 'test'));
469 $this->testedConfig->getCache()->set('config', 'test', 'prio', Cache::SOURCE_ENV);
470 // now you have to get the env variable entry as output, even with a new set (which failed) and a get refresh
471 self::assertFalse($this->testedConfig->set('config', 'test', '123'));
472 self::assertEquals('prio', $this->testedConfig->get('config', 'test', '', true));