]> git.mxchange.org Git - friendica.git/blob - tests/src/Core/Config/ConfigTest.php
Use ArraySubsetAsserts
[friendica.git] / tests / src / Core / Config / ConfigTest.php
1 <?php
2 /**
3  * @copyright Copyright (C) 2010-2021, the Friendica project
4  *
5  * @license GNU AGPL version 3 or any later version
6  *
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.
11  *
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.
16  *
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/>.
19  *
20  */
21
22 namespace Friendica\Test\src\Core\Config;
23
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;
30 use Mockery;
31
32 abstract class ConfigTest extends MockedTest
33 {
34         use ArraySubsetAsserts;
35
36         /** @var ConfigModel|MockInterface */
37         protected $configModel;
38
39         /** @var Cache */
40         protected $configCache;
41
42         /** @var IManageConfigValues */
43         protected $testedConfig;
44
45         /**
46          * Assert a config tree
47          *
48          * @param string $cat  The category to assert
49          * @param array  $data The result data array
50          */
51         protected function assertConfig(string $cat, array $data)
52         {
53                 $result = $this->testedConfig->getCache()->getAll();
54
55                 self::assertNotEmpty($result);
56                 self::assertArrayHasKey($cat, $result);
57                 self::assertArraySubset($data, $result[$cat]);
58         }
59
60
61         protected function setUp(): void
62         {
63                 parent::setUp();
64
65                 // Create the config model
66                 $this->configModel = Mockery::mock(ConfigModel::class);
67                 $this->configCache = new Cache();
68         }
69
70         /**
71          * @return IManageConfigValues
72          */
73         abstract public function getInstance();
74
75         public function dataTests()
76         {
77                 return [
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],
86                 ];
87         }
88
89         public function dataConfigLoad()
90         {
91                 $data = [
92                         'system' => [
93                                 'key1' => 'value1',
94                                 'key2' => 'value2',
95                                 'key3' => 'value3',
96                         ],
97                         'config' => [
98                                 'key1' => 'value1a',
99                                 'key4' => 'value4',
100                         ],
101                         'other'  => [
102                                 'key5' => 'value5',
103                                 'key6' => 'value6',
104                         ],
105                 ];
106
107                 return [
108                         'system' => [
109                                 'data'         => $data,
110                                 'possibleCats' => [
111                                         'system',
112                                         'config',
113                                         'other'
114                                 ],
115                                 'load'         => [
116                                         'system',
117                                 ],
118                         ],
119                         'other'  => [
120                                 'data'         => $data,
121                                 'possibleCats' => [
122                                         'system',
123                                         'config',
124                                         'other'
125                                 ],
126                                 'load'         => [
127                                         'other',
128                                 ],
129                         ],
130                         'config' => [
131                                 'data'         => $data,
132                                 'possibleCats' => [
133                                         'system',
134                                         'config',
135                                         'other'
136                                 ],
137                                 'load'         => [
138                                         'config',
139                                 ],
140                         ],
141                         'all'    => [
142                                 'data'         => $data,
143                                 'possibleCats' => [
144                                         'system',
145                                         'config',
146                                         'other'
147                                 ],
148                                 'load'         => [
149                                         'system',
150                                         'config',
151                                         'other'
152                                 ],
153                         ],
154                 ];
155         }
156
157         /**
158          * Test the configuration initialization
159          */
160         public function testSetUp(array $data)
161         {
162                 $this->configModel->shouldReceive('isConnected')
163                                   ->andReturn(true)
164                                   ->once();
165
166                 $this->testedConfig = $this->getInstance();
167                 self::assertInstanceOf(Cache::class, $this->testedConfig->getCache());
168
169                 // assert config is loaded everytime
170                 self::assertConfig('config', $data['config']);
171         }
172
173         /**
174          * Test the configuration load() method
175          *
176          * @param array $data
177          * @param array $load
178          */
179         public function testLoad(array $data, array $load)
180         {
181                 $this->testedConfig = $this->getInstance();
182                 self::assertInstanceOf(Cache::class, $this->testedConfig->getCache());
183
184                 foreach ($load as $loadedCats) {
185                         $this->testedConfig->load($loadedCats);
186                 }
187
188                 // Assert at least loaded cats are loaded
189                 foreach ($load as $loadedCats) {
190                         self::assertConfig($loadedCats, $data[$loadedCats]);
191                 }
192         }
193
194         public function dataDoubleLoad()
195         {
196                 return [
197                         'config' => [
198                                 'data1'  => [
199                                         'config' => [
200                                                 'key1' => 'value1',
201                                                 'key2' => 'value2',
202                                         ],
203                                 ],
204                                 'data2'  => [
205                                         'config' => [
206                                                 'key1' => 'overwritten!',
207                                                 'key3' => 'value3',
208                                         ],
209                                 ],
210                                 'expect' => [
211                                         'config' => [
212                                                 // load should overwrite values everytime!
213                                                 'key1' => 'overwritten!',
214                                                 'key2' => 'value2',
215                                                 'key3' => 'value3',
216                                         ],
217                                 ],
218                         ],
219                         'other'  => [
220                                 'data1'  => [
221                                         'config' => [
222                                                 'key12' => 'data4',
223                                                 'key45' => 7,
224                                         ],
225                                         'other'  => [
226                                                 'key1' => 'value1',
227                                                 'key2' => 'value2',
228                                         ],
229                                 ],
230                                 'data2'  => [
231                                         'other'  => [
232                                                 'key1' => 'overwritten!',
233                                                 'key3' => 'value3',
234                                         ],
235                                         'config' => [
236                                                 'key45' => 45,
237                                                 'key52' => true,
238                                         ]
239                                 ],
240                                 'expect' => [
241                                         'other'  => [
242                                                 // load should overwrite values everytime!
243                                                 'key1' => 'overwritten!',
244                                                 'key2' => 'value2',
245                                                 'key3' => 'value3',
246                                         ],
247                                         'config' => [
248                                                 'key12' => 'data4',
249                                                 'key45' => 45,
250                                                 'key52' => true,
251                                         ],
252                                 ],
253                         ],
254                 ];
255         }
256
257         /**
258          * Test the configuration load() method with overwrite
259          */
260         public function testCacheLoadDouble(array $data1, array $data2, array $expect = [])
261         {
262                 $this->testedConfig = $this->getInstance();
263                 self::assertInstanceOf(Cache::class, $this->testedConfig->getCache());
264
265                 foreach ($data1 as $cat => $data) {
266                         $this->testedConfig->load($cat);
267                 }
268
269                 // Assert at least loaded cats are loaded
270                 foreach ($data1 as $cat => $data) {
271                         self::assertConfig($cat, $data);
272                 }
273
274                 foreach ($data2 as $cat => $data) {
275                         $this->testedConfig->load($cat);
276                 }
277         }
278
279         /**
280          * Test the configuration load without result
281          */
282         public function testLoadWrong()
283         {
284                 $this->configModel->shouldReceive('isConnected')->andReturn(true)->once();
285                 $this->configModel->shouldReceive('load')->withAnyArgs()->andReturn([])->once();
286
287                 $this->testedConfig = $this->getInstance();
288                 self::assertInstanceOf(Cache::class, $this->testedConfig->getCache());
289
290                 self::assertEmpty($this->testedConfig->getCache()->getAll());
291         }
292
293         /**
294          * Test the configuration get() and set() methods without adapter
295          *
296          * @dataProvider dataTests
297          */
298         public function testSetGetWithoutDB($data)
299         {
300                 $this->configModel->shouldReceive('isConnected')
301                                   ->andReturn(false)
302                                   ->times(3);
303
304                 $this->testedConfig = $this->getInstance();
305                 self::assertInstanceOf(Cache::class, $this->testedConfig->getCache());
306
307                 self::assertTrue($this->testedConfig->set('test', 'it', $data));
308
309                 self::assertEquals($data, $this->testedConfig->get('test', 'it'));
310                 self::assertEquals($data, $this->testedConfig->getCache()->get('test', 'it'));
311         }
312
313         /**
314          * Test the configuration get() and set() methods with a model/db
315          *
316          * @dataProvider dataTests
317          */
318         public function testSetGetWithDB($data)
319         {
320                 $this->configModel->shouldReceive('set')->with('test', 'it', $data)->andReturn(true)->once();
321
322                 $this->testedConfig = $this->getInstance();
323                 self::assertInstanceOf(Cache::class, $this->testedConfig->getCache());
324
325                 self::assertTrue($this->testedConfig->set('test', 'it', $data));
326
327                 self::assertEquals($data, $this->testedConfig->get('test', 'it'));
328                 self::assertEquals($data, $this->testedConfig->getCache()->get('test', 'it'));
329         }
330
331         /**
332          * Test the configuration get() method with wrong value and no db
333          */
334         public function testGetWrongWithoutDB()
335         {
336                 $this->testedConfig = $this->getInstance();
337                 self::assertInstanceOf(Cache::class, $this->testedConfig->getCache());
338
339                 // without refresh
340                 self::assertNull($this->testedConfig->get('test', 'it'));
341
342                 /// beware that the cache returns '!<unset>!' and not null for a non existing value
343                 self::assertNull($this->testedConfig->getCache()->get('test', 'it'));
344
345                 // with default value
346                 self::assertEquals('default', $this->testedConfig->get('test', 'it', 'default'));
347
348                 // with default value and refresh
349                 self::assertEquals('default', $this->testedConfig->get('test', 'it', 'default', true));
350         }
351
352         /**
353          * Test the configuration get() method with refresh
354          *
355          * @dataProvider dataTests
356          */
357         public function testGetWithRefresh($data)
358         {
359                 $this->configCache->load(['test' => ['it' => 'now']], Cache::SOURCE_FILE);
360
361                 $this->testedConfig = $this->getInstance();
362                 self::assertInstanceOf(Cache::class, $this->testedConfig->getCache());
363
364                 // without refresh
365                 self::assertEquals('now', $this->testedConfig->get('test', 'it'));
366                 self::assertEquals('now', $this->testedConfig->getCache()->get('test', 'it'));
367
368                 // with refresh
369                 self::assertEquals($data, $this->testedConfig->get('test', 'it', null, true));
370                 self::assertEquals($data, $this->testedConfig->getCache()->get('test', 'it'));
371
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'));
375         }
376
377         /**
378          * Test the configuration delete() method without a model/db
379          *
380          * @dataProvider dataTests
381          */
382         public function testDeleteWithoutDB($data)
383         {
384                 $this->configCache->load(['test' => ['it' => $data]], Cache::SOURCE_FILE);
385
386                 $this->testedConfig = $this->getInstance();
387                 self::assertInstanceOf(Cache::class, $this->testedConfig->getCache());
388
389                 self::assertEquals($data, $this->testedConfig->get('test', 'it'));
390                 self::assertEquals($data, $this->testedConfig->getCache()->get('test', 'it'));
391
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'));
395
396                 self::assertEmpty($this->testedConfig->getCache()->getAll());
397         }
398
399         /**
400          * Test the configuration delete() method with a model/db
401          */
402         public function testDeleteWithDB()
403         {
404                 $this->configCache->load(['test' => ['it' => 'now', 'quarter' => 'true']], Cache::SOURCE_FILE);
405
406                 $this->configModel->shouldReceive('delete')
407                                   ->with('test', 'it')
408                                   ->andReturn(false)
409                                   ->once();
410                 $this->configModel->shouldReceive('delete')
411                                   ->with('test', 'second')
412                                   ->andReturn(true)
413                                   ->once();
414                 $this->configModel->shouldReceive('delete')
415                                   ->with('test', 'third')
416                                   ->andReturn(false)
417                                   ->once();
418                 $this->configModel->shouldReceive('delete')
419                                   ->with('test', 'quarter')
420                                   ->andReturn(true)
421                                   ->once();
422
423                 $this->testedConfig = $this->getInstance();
424                 self::assertInstanceOf(Cache::class, $this->testedConfig->getCache());
425
426                 // directly set the value to the cache
427                 $this->testedConfig->getCache()->set('test', 'it', 'now');
428
429                 self::assertEquals('now', $this->testedConfig->get('test', 'it'));
430                 self::assertEquals('now', $this->testedConfig->getCache()->get('test', 'it'));
431
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'));
436                 // no delete
437                 self::assertFalse($this->testedConfig->delete('test', 'third'));
438                 // delete both
439                 self::assertTrue($this->testedConfig->delete('test', 'quarter'));
440
441                 self::assertEmpty($this->testedConfig->getCache()->getAll());
442         }
443
444         /**
445          * Test the configuration get() and set() method where the db value has a higher prio than the config file
446          */
447         public function testSetGetHighPrio()
448         {
449                 $this->testedConfig = $this->getInstance();
450                 self::assertInstanceOf(Cache::class, $this->testedConfig->getCache());
451
452                 $this->testedConfig->getCache()->set('config', 'test', 'prio', Cache::SOURCE_FILE);
453                 self::assertEquals('prio', $this->testedConfig->get('config', 'test'));
454
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));
458         }
459
460         /**
461          * Test the configuration get() and set() method where the db value has a lower prio than the env
462          */
463         public function testSetGetLowPrio()
464         {
465                 $this->testedConfig = $this->getInstance();
466                 self::assertInstanceOf(Cache::class, $this->testedConfig->getCache());
467                 self::assertEquals('it', $this->testedConfig->get('config', 'test'));
468
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));
473         }
474 }