3 * @copyright Copyright (C) 2020, Friendica
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 Friendica\Core\Config\Cache;
25 use Friendica\Core\Config\IConfig;
26 use Friendica\Model\Config\Config as ConfigModel;
27 use Friendica\Test\MockedTest;
28 use Mockery\MockInterface;
31 abstract class ConfigTest extends MockedTest
33 /** @var ConfigModel|MockInterface */
34 protected $configModel;
37 protected $configCache;
40 protected $testedConfig;
43 * Assert a config tree
45 * @param string $cat The category to assert
46 * @param array $data The result data array
48 protected function assertConfig(string $cat, array $data)
50 $result = $this->testedConfig->getCache()->getAll();
52 self::assertNotEmpty($result);
53 self::assertArrayHasKey($cat, $result);
54 self::assertArraySubset($data, $result[$cat]);
58 protected function setUp()
62 // Create the config model
63 $this->configModel = Mockery::mock(ConfigModel::class);
64 $this->configCache = new Cache();
70 abstract public function getInstance();
72 public function dataTests()
75 'string' => ['data' => 'it'],
76 'boolTrue' => ['data' => true],
77 'boolFalse' => ['data' => false],
78 'integer' => ['data' => 235],
79 'decimal' => ['data' => 2.456],
80 'array' => ['data' => ['1', 2, '3', true, false]],
81 'boolIntTrue' => ['data' => 1],
82 'boolIntFalse' => ['Data' => 0],
86 public function dataConfigLoad()
155 * Test the configuration initialization
157 public function testSetUp(array $data)
159 $this->configModel->shouldReceive('isConnected')
163 $this->testedConfig = $this->getInstance();
164 self::assertInstanceOf(Cache::class, $this->testedConfig->getCache());
166 // assert config is loaded everytime
167 self::assertConfig('config', $data['config']);
171 * Test the configuration load() method
176 public function testLoad(array $data, array $load)
178 $this->testedConfig = $this->getInstance();
179 self::assertInstanceOf(Cache::class, $this->testedConfig->getCache());
181 foreach ($load as $loadedCats) {
182 $this->testedConfig->load($loadedCats);
185 // Assert at least loaded cats are loaded
186 foreach ($load as $loadedCats) {
187 self::assertConfig($loadedCats, $data[$loadedCats]);
191 public function dataDoubleLoad()
203 'key1' => 'overwritten!',
209 // load should overwrite values everytime!
210 'key1' => 'overwritten!',
229 'key1' => 'overwritten!',
239 // load should overwrite values everytime!
240 'key1' => 'overwritten!',
255 * Test the configuration load() method with overwrite
257 public function testCacheLoadDouble(array $data1, array $data2, array $expect = [])
259 $this->testedConfig = $this->getInstance();
260 self::assertInstanceOf(Cache::class, $this->testedConfig->getCache());
262 foreach ($data1 as $cat => $data) {
263 $this->testedConfig->load($cat);
266 // Assert at least loaded cats are loaded
267 foreach ($data1 as $cat => $data) {
268 self::assertConfig($cat, $data);
271 foreach ($data2 as $cat => $data) {
272 $this->testedConfig->load($cat);
277 * Test the configuration load without result
279 public function testLoadWrong()
281 $this->configModel->shouldReceive('isConnected')->andReturn(true)->once();
282 $this->configModel->shouldReceive('load')->withAnyArgs()->andReturn([])->once();
284 $this->testedConfig = $this->getInstance();
285 self::assertInstanceOf(Cache::class, $this->testedConfig->getCache());
287 self::assertEmpty($this->testedConfig->getCache()->getAll());
291 * Test the configuration get() and set() methods without adapter
293 * @dataProvider dataTests
295 public function testSetGetWithoutDB($data)
297 $this->configModel->shouldReceive('isConnected')
301 $this->testedConfig = $this->getInstance();
302 self::assertInstanceOf(Cache::class, $this->testedConfig->getCache());
304 self::assertTrue($this->testedConfig->set('test', 'it', $data));
306 self::assertEquals($data, $this->testedConfig->get('test', 'it'));
307 self::assertEquals($data, $this->testedConfig->getCache()->get('test', 'it'));
311 * Test the configuration get() and set() methods with a model/db
313 * @dataProvider dataTests
315 public function testSetGetWithDB($data)
317 $this->configModel->shouldReceive('set')->with('test', 'it', $data)->andReturn(true)->once();
319 $this->testedConfig = $this->getInstance();
320 self::assertInstanceOf(Cache::class, $this->testedConfig->getCache());
322 self::assertTrue($this->testedConfig->set('test', 'it', $data));
324 self::assertEquals($data, $this->testedConfig->get('test', 'it'));
325 self::assertEquals($data, $this->testedConfig->getCache()->get('test', 'it'));
329 * Test the configuration get() method with wrong value and no db
331 public function testGetWrongWithoutDB()
333 $this->testedConfig = $this->getInstance();
334 self::assertInstanceOf(Cache::class, $this->testedConfig->getCache());
337 self::assertNull($this->testedConfig->get('test', 'it'));
339 /// beware that the cache returns '!<unset>!' and not null for a non existing value
340 self::assertNull($this->testedConfig->getCache()->get('test', 'it'));
342 // with default value
343 self::assertEquals('default', $this->testedConfig->get('test', 'it', 'default'));
345 // with default value and refresh
346 self::assertEquals('default', $this->testedConfig->get('test', 'it', 'default', true));
350 * Test the configuration get() method with refresh
352 * @dataProvider dataTests
354 public function testGetWithRefresh($data)
356 $this->configCache->load(['test' => ['it' => 'now']], Cache::SOURCE_FILE);
358 $this->testedConfig = $this->getInstance();
359 self::assertInstanceOf(Cache::class, $this->testedConfig->getCache());
362 self::assertEquals('now', $this->testedConfig->get('test', 'it'));
363 self::assertEquals('now', $this->testedConfig->getCache()->get('test', 'it'));
366 self::assertEquals($data, $this->testedConfig->get('test', 'it', null, true));
367 self::assertEquals($data, $this->testedConfig->getCache()->get('test', 'it'));
369 // without refresh and wrong value and default
370 self::assertEquals('default', $this->testedConfig->get('test', 'not', 'default'));
371 self::assertNull($this->testedConfig->getCache()->get('test', 'not'));
375 * Test the configuration delete() method without a model/db
377 * @dataProvider dataTests
379 public function testDeleteWithoutDB($data)
381 $this->configCache->load(['test' => ['it' => $data]], Cache::SOURCE_FILE);
383 $this->testedConfig = $this->getInstance();
384 self::assertInstanceOf(Cache::class, $this->testedConfig->getCache());
386 self::assertEquals($data, $this->testedConfig->get('test', 'it'));
387 self::assertEquals($data, $this->testedConfig->getCache()->get('test', 'it'));
389 self::assertTrue($this->testedConfig->delete('test', 'it'));
390 self::assertNull($this->testedConfig->get('test', 'it'));
391 self::assertNull($this->testedConfig->getCache()->get('test', 'it'));
393 self::assertEmpty($this->testedConfig->getCache()->getAll());
397 * Test the configuration delete() method with a model/db
399 public function testDeleteWithDB()
401 $this->configCache->load(['test' => ['it' => 'now', 'quarter' => 'true']], Cache::SOURCE_FILE);
403 $this->configModel->shouldReceive('delete')
407 $this->configModel->shouldReceive('delete')
408 ->with('test', 'second')
411 $this->configModel->shouldReceive('delete')
412 ->with('test', 'third')
415 $this->configModel->shouldReceive('delete')
416 ->with('test', 'quarter')
420 $this->testedConfig = $this->getInstance();
421 self::assertInstanceOf(Cache::class, $this->testedConfig->getCache());
423 // directly set the value to the cache
424 $this->testedConfig->getCache()->set('test', 'it', 'now');
426 self::assertEquals('now', $this->testedConfig->get('test', 'it'));
427 self::assertEquals('now', $this->testedConfig->getCache()->get('test', 'it'));
429 // delete from cache only
430 self::assertTrue($this->testedConfig->delete('test', 'it'));
431 // delete from db only
432 self::assertTrue($this->testedConfig->delete('test', 'second'));
434 self::assertFalse($this->testedConfig->delete('test', 'third'));
436 self::assertTrue($this->testedConfig->delete('test', 'quarter'));
438 self::assertEmpty($this->testedConfig->getCache()->getAll());
442 * Test the configuration get() and set() method where the db value has a higher prio than the config file
444 public function testSetGetHighPrio()
446 $this->testedConfig = $this->getInstance();
447 self::assertInstanceOf(Cache::class, $this->testedConfig->getCache());
449 $this->testedConfig->getCache()->set('config', 'test', 'prio', Cache::SOURCE_FILE);
450 self::assertEquals('prio', $this->testedConfig->get('config', 'test'));
452 // now you have to get the new variable entry because of the new set the get refresh succeed as well
453 self::assertTrue($this->testedConfig->set('config', 'test', '123'));
454 self::assertEquals('123', $this->testedConfig->get('config', 'test', '', true));
458 * Test the configuration get() and set() method where the db value has a lower prio than the env
460 public function testSetGetLowPrio()
462 $this->testedConfig = $this->getInstance();
463 self::assertInstanceOf(Cache::class, $this->testedConfig->getCache());
464 self::assertEquals('it', $this->testedConfig->get('config', 'test'));
466 $this->testedConfig->getCache()->set('config', 'test', 'prio', Cache::SOURCE_ENV);
467 // now you have to get the env variable entry as output, even with a new set (which failed) and a get refresh
468 self::assertFalse($this->testedConfig->set('config', 'test', '123'));
469 self::assertEquals('prio', $this->testedConfig->get('config', 'test', '', true));