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\PConfig;
24 use Friendica\Core\PConfig\Cache;
25 use Friendica\Core\PConfig\Type\AbstractPConfigValues;
26 use Friendica\Core\PConfig\Repository\PConfig as PConfigModel;
27 use Friendica\Test\MockedTest;
29 use Mockery\MockInterface;
31 abstract class PConfigTest extends MockedTest
33 /** @var PConfigModel|MockInterface */
34 protected $configModel;
36 /** @var \Friendica\Core\PConfig\ValueObject\Cache */
37 protected $configCache;
39 /** @var AbstractPConfigValues */
40 protected $testedConfig;
43 * Assert a config tree
45 * @param int $uid The uid to assert
46 * @param string $cat The category to assert
47 * @param array $data The result data array
49 protected function assertConfig(int $uid, string $cat, array $data)
51 $result = $this->testedConfig->getCache()->getAll();
53 self::assertNotEmpty($result);
54 self::assertArrayHasKey($uid, $result);
55 self::assertArrayHasKey($cat, $result[$uid]);
56 self::assertArraySubset($data, $result[$uid][$cat]);
60 protected function setUp(): void
64 // Create the config model
65 $this->configModel = Mockery::mock(PConfigModel::class);
66 $this->configCache = new \Friendica\Core\PConfig\ValueObject\Cache();
70 * @return \Friendica\Core\PConfig\Type\AbstractPConfigValues
72 abstract public function getInstance();
74 public function dataTests()
77 'string' => ['uid' => 1, 'data' => 'it'],
78 'boolTrue' => ['uid' => 2, 'data' => true],
79 'boolFalse' => ['uid' => 3, 'data' => false],
80 'integer' => ['uid' => 4, 'data' => 235],
81 'decimal' => ['uid' => 5, 'data' => 2.456],
82 'array' => ['uid' => 6, 'data' => ['1', 2, '3', true, false]],
83 'boolIntTrue' => ['uid' => 7, 'data' => 1],
84 'boolIntFalse' => ['uid' => 8, 'data' => 0],
88 public function dataConfigLoad()
161 * Test the configuration initialization
163 public function testSetUp()
165 $this->testedConfig = $this->getInstance();
166 self::assertInstanceOf(\Friendica\Core\PConfig\ValueObject\Cache::class, $this->testedConfig->getCache());
168 self::assertEmpty($this->testedConfig->getCache()->getAll());
172 * Test the configuration load() method
174 public function testLoad(int $uid, array $data, array $possibleCats, array $load)
176 $this->testedConfig = $this->getInstance();
177 self::assertInstanceOf(\Friendica\Core\PConfig\ValueObject\Cache::class, $this->testedConfig->getCache());
179 foreach ($load as $loadedCats) {
180 $this->testedConfig->load($uid, $loadedCats);
183 // Assert at least loaded cats are loaded
184 foreach ($load as $loadedCats) {
185 self::assertConfig($uid, $loadedCats, $data[$loadedCats]);
189 public function dataDoubleLoad()
202 'key1' => 'overwritten!',
208 // load should overwrite values everytime!
209 '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(int $uid, array $data1, array $data2, array $expect)
259 $this->testedConfig = $this->getInstance();
260 self::assertInstanceOf(\Friendica\Core\PConfig\ValueObject\Cache::class, $this->testedConfig->getCache());
262 foreach ($data1 as $cat => $data) {
263 $this->testedConfig->load($uid, $cat);
266 // Assert at least loaded cats are loaded
267 foreach ($data1 as $cat => $data) {
268 self::assertConfig($uid, $cat, $data);
271 foreach ($data2 as $cat => $data) {
272 $this->testedConfig->load($uid, $cat);
277 * Test the configuration get() and set() methods without adapter
279 * @dataProvider dataTests
281 public function testSetGetWithoutDB(int $uid, $data)
283 $this->testedConfig = $this->getInstance();
284 self::assertInstanceOf(\Friendica\Core\PConfig\ValueObject\Cache::class, $this->testedConfig->getCache());
286 self::assertTrue($this->testedConfig->set($uid, 'test', 'it', $data));
288 self::assertEquals($data, $this->testedConfig->get($uid, 'test', 'it'));
289 self::assertEquals($data, $this->testedConfig->getCache()->get($uid, 'test', 'it'));
293 * Test the configuration get() and set() methods with a model/db
295 * @dataProvider dataTests
297 public function testSetGetWithDB(int $uid, $data)
299 $this->configModel->shouldReceive('set')
300 ->with($uid, 'test', 'it', $data)
304 $this->testedConfig = $this->getInstance();
305 self::assertInstanceOf(\Friendica\Core\PConfig\ValueObject\Cache::class, $this->testedConfig->getCache());
307 self::assertTrue($this->testedConfig->set($uid, 'test', 'it', $data));
309 self::assertEquals($data, $this->testedConfig->get($uid, 'test', 'it'));
310 self::assertEquals($data, $this->testedConfig->getCache()->get($uid, 'test', 'it'));
314 * Test the configuration get() method with wrong value and no db
316 public function testGetWrongWithoutDB()
318 $this->testedConfig = $this->getInstance();
319 self::assertInstanceOf(\Friendica\Core\PConfig\ValueObject\Cache::class, $this->testedConfig->getCache());
322 self::assertNull($this->testedConfig->get(0, 'test', 'it'));
324 /// beware that the cache returns '!<unset>!' and not null for a non existing value
325 self::assertNull($this->testedConfig->getCache()->get(0, 'test', 'it'));
327 // with default value
328 self::assertEquals('default', $this->testedConfig->get(0, 'test', 'it', 'default'));
330 // with default value and refresh
331 self::assertEquals('default', $this->testedConfig->get(0, 'test', 'it', 'default', true));
335 * Test the configuration get() method with refresh
337 * @dataProvider dataTests
339 public function testGetWithRefresh(int $uid, $data)
341 $this->configCache->load($uid, ['test' => ['it' => 'now']]);
343 $this->testedConfig = $this->getInstance();
344 self::assertInstanceOf(\Friendica\Core\PConfig\ValueObject\Cache::class, $this->testedConfig->getCache());
347 self::assertEquals('now', $this->testedConfig->get($uid, 'test', 'it'));
348 self::assertEquals('now', $this->testedConfig->getCache()->get($uid, 'test', 'it'));
351 self::assertEquals($data, $this->testedConfig->get($uid, 'test', 'it', null, true));
352 self::assertEquals($data, $this->testedConfig->getCache()->get($uid, 'test', 'it'));
354 // without refresh and wrong value and default
355 self::assertEquals('default', $this->testedConfig->get($uid, 'test', 'not', 'default'));
356 self::assertNull($this->testedConfig->getCache()->get($uid, 'test', 'not'));
360 * Test the configuration delete() method without a model/db
362 * @dataProvider dataTests
364 public function testDeleteWithoutDB(int $uid, $data)
366 $this->configCache->load($uid, ['test' => ['it' => $data]]);
368 $this->testedConfig = $this->getInstance();
369 self::assertInstanceOf(\Friendica\Core\PConfig\ValueObject\Cache::class, $this->testedConfig->getCache());
371 self::assertEquals($data, $this->testedConfig->get($uid, 'test', 'it'));
372 self::assertEquals($data, $this->testedConfig->getCache()->get($uid, 'test', 'it'));
374 self::assertTrue($this->testedConfig->delete($uid, 'test', 'it'));
375 self::assertNull($this->testedConfig->get($uid, 'test', 'it'));
376 self::assertNull($this->testedConfig->getCache()->get($uid, 'test', 'it'));
378 self::assertEmpty($this->testedConfig->getCache()->getAll());
382 * Test the configuration delete() method with a model/db
384 public function testDeleteWithDB()
388 $this->configCache->load($uid, ['test' => ['it' => 'now', 'quarter' => 'true']]);
390 $this->configModel->shouldReceive('delete')
391 ->with($uid, 'test', 'it')
394 $this->configModel->shouldReceive('delete')
395 ->with($uid, 'test', 'second')
398 $this->configModel->shouldReceive('delete')
399 ->with($uid, 'test', 'third')
402 $this->configModel->shouldReceive('delete')
403 ->with($uid, 'test', 'quarter')
407 $this->testedConfig = $this->getInstance();
408 self::assertInstanceOf(\Friendica\Core\PConfig\ValueObject\Cache::class, $this->testedConfig->getCache());
410 // directly set the value to the cache
411 $this->testedConfig->getCache()->set($uid, 'test', 'it', 'now');
413 self::assertEquals('now', $this->testedConfig->get($uid, 'test', 'it'));
414 self::assertEquals('now', $this->testedConfig->getCache()->get($uid, 'test', 'it'));
416 // delete from cache only
417 self::assertTrue($this->testedConfig->delete($uid, 'test', 'it'));
418 // delete from db only
419 self::assertTrue($this->testedConfig->delete($uid, 'test', 'second'));
421 self::assertFalse($this->testedConfig->delete($uid, 'test', 'third'));
423 self::assertTrue($this->testedConfig->delete($uid, 'test', 'quarter'));
425 self::assertEmpty($this->testedConfig->getCache()->getAll());
428 public function dataMultiUid()
459 * Test if multiple uids for caching are usable without errors
460 * @dataProvider dataMultiUid
462 public function testMultipleUidsWithCache(array $data1, array $data2)
464 $this->configCache->load($data1['uid'], $data1['data']);
465 $this->configCache->load($data2['uid'], $data2['data']);
467 $this->testedConfig = $this->getInstance();
468 self::assertInstanceOf(\Friendica\Core\PConfig\ValueObject\Cache::class, $this->testedConfig->getCache());
470 self::assertConfig($data1['uid'], 'cat1', $data1['data']['cat1']);
471 self::assertConfig($data1['uid'], 'cat2', $data1['data']['cat2']);
472 self::assertConfig($data2['uid'], 'cat1', $data2['data']['cat1']);
473 self::assertConfig($data2['uid'], 'cat2', $data2['data']['cat2']);
477 * Test when using an invalid UID
478 * @todo check it the clean way before using the config class
480 public function testInvalidUid()
485 $this->testedConfig = $this->getInstance();
487 self::assertNull($this->testedConfig->get($uid, 'cat1', 'cat2'));
488 self::assertEquals('fallback!', $this->testedConfig->get($uid, 'cat1', 'cat2', 'fallback!'));
490 self::assertFalse($this->testedConfig->set($uid, 'cat1', 'key1', 'doesn\'t matter!'));
491 self::assertFalse($this->testedConfig->delete($uid, 'cat1', 'key1'));