]> git.mxchange.org Git - friendica.git/blob - tests/src/Core/Config/ConfigTest.php
Improved logging
[friendica.git] / tests / src / Core / Config / ConfigTest.php
1 <?php
2 /**
3  * @copyright Copyright (C) 2010-2023, 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\Model\DatabaseConfig;
27 use Friendica\Core\Config\Model\ReadOnlyFileConfig;
28 use Friendica\Core\Config\Util\ConfigFileManager;
29 use Friendica\Core\Config\ValueObject\Cache;
30 use Friendica\Test\DatabaseTest;
31 use Friendica\Test\Util\CreateDatabaseTrait;
32 use Friendica\Test\Util\VFSTrait;
33 use org\bovigo\vfs\vfsStream;
34
35 class ConfigTest extends DatabaseTest
36 {
37         use ArraySubsetAsserts;
38         use VFSTrait;
39         use CreateDatabaseTrait;
40
41         /** @var Cache */
42         protected $configCache;
43
44         /** @var ConfigFileManager */
45         protected $configFileManager;
46
47         /** @var IManageConfigValues */
48         protected $testedConfig;
49
50         /**
51          * Assert a config tree
52          *
53          * @param string $cat  The category to assert
54          * @param array  $data The result data array
55          */
56         protected function assertConfig(string $cat, array $data)
57         {
58                 $result = $this->testedConfig->getCache()->getAll();
59
60                 self::assertNotEmpty($result);
61                 self::assertArrayHasKey($cat, $result);
62                 self::assertArraySubset($data, $result[$cat]);
63         }
64
65
66         protected function setUp(): void
67         {
68                 $this->setUpVfsDir();
69
70                 parent::setUp();
71
72                 $this->configCache = new Cache();
73                 $this->configFileManager = new ConfigFileManager($this->root->url(), $this->root->url() . '/config/', $this->root->url() . '/static/');
74         }
75
76         /**
77          * @return IManageConfigValues
78          */
79         public function getInstance()
80         {
81                 $this->configFileManager->setupCache($this->configCache);
82                 return new DatabaseConfig($this->getDbInstance(), $this->configCache);
83         }
84
85         public function dataTests()
86         {
87                 return [
88                         'string'       => ['data' => 'it'],
89                         'boolTrue'     => ['data' => true],
90                         'boolFalse'    => ['data' => false],
91                         'integer'      => ['data' => 235],
92                         'decimal'      => ['data' => 2.456],
93                         'array'        => ['data' => ['1', 2, '3', true, false]],
94                         'boolIntTrue'  => ['data' => 1],
95                         'boolIntFalse' => ['Data' => 0],
96                 ];
97         }
98
99         public function dataConfigLoad()
100         {
101                 $data = [
102                         'system' => [
103                                 'key1' => 'value1',
104                                 'key2' => 'value2',
105                                 'key3' => 'value3',
106                         ],
107                         'config' => [
108                                 'key1' => 'value1a',
109                                 'key4' => 'value4',
110                         ],
111                         'other'  => [
112                                 'key5' => 'value5',
113                                 'key6' => 'value6',
114                         ],
115                 ];
116
117                 return [
118                         'system' => [
119                                 'data'         => $data,
120                                 'possibleCats' => [
121                                         'system',
122                                         'config',
123                                         'other'
124                                 ],
125                                 'load'         => [
126                                         'system',
127                                 ],
128                         ],
129                         'other'  => [
130                                 'data'         => $data,
131                                 'possibleCats' => [
132                                         'system',
133                                         'config',
134                                         'other'
135                                 ],
136                                 'load'         => [
137                                         'other',
138                                 ],
139                         ],
140                         'config' => [
141                                 'data'         => $data,
142                                 'possibleCats' => [
143                                         'system',
144                                         'config',
145                                         'other'
146                                 ],
147                                 'load'         => [
148                                         'config',
149                                 ],
150                         ],
151                         'all'    => [
152                                 'data'         => $data,
153                                 'possibleCats' => [
154                                         'system',
155                                         'config',
156                                         'other'
157                                 ],
158                                 'load'         => [
159                                         'system',
160                                         'config',
161                                         'other'
162                                 ],
163                         ],
164                 ];
165         }
166
167         public function configToDbArray(array $config): array
168         {
169                 $dbarray = [];
170
171                 foreach ($config as $category => $data) {
172                         foreach ($data as $key => $value) {
173                                 $dbarray[] = [
174                                         'cat' => $category,
175                                         'k'   => $key,
176                                         'v'   => $value,
177                                 ];
178                         }
179                 }
180
181                 return ['config' => $dbarray];
182         }
183
184         /**
185          * Test the configuration initialization
186          * @dataProvider dataConfigLoad
187          */
188         public function testSetUp(array $data)
189         {
190                 $this->loadDirectFixture($this->configToDbArray($data) , $this->getDbInstance());
191
192                 $this->testedConfig = $this->getInstance();
193                 self::assertInstanceOf(Cache::class, $this->testedConfig->getCache());
194
195                 // assert config is loaded everytime
196                 self::assertConfig('config', $data['config']);
197         }
198
199         /**
200          * Test the configuration reload() method
201          *
202          * @param array $data
203          * @param array $load
204          *
205          * @dataProvider dataConfigLoad
206          */
207         public function testReload(array $data, array $load)
208         {
209                 $this->loadDirectFixture($this->configToDbArray($data), $this->getDbInstance());
210
211                 $this->testedConfig = $this->getInstance();
212                 self::assertInstanceOf(Cache::class, $this->testedConfig->getCache());
213
214                 $this->testedConfig->reload();
215
216                 // Assert at least loaded cats are loaded
217                 foreach ($load as $loadedCats) {
218                         self::assertConfig($loadedCats, $data[$loadedCats]);
219                 }
220         }
221
222         public function dataDoubleLoad()
223         {
224                 return [
225                         'config' => [
226                                 'data1'  => [
227                                         'config' => [
228                                                 'key1' => 'value1',
229                                                 'key2' => 'value2',
230                                         ],
231                                 ],
232                                 'data2'  => [
233                                         'config' => [
234                                                 'key1' => 'overwritten!',
235                                                 'key3' => 'value3',
236                                         ],
237                                 ],
238                                 'expect' => [
239                                         'config' => [
240                                                 // load should overwrite values everytime!
241                                                 'key1' => 'overwritten!',
242                                                 'key2' => 'value2',
243                                                 'key3' => 'value3',
244                                         ],
245                                 ],
246                         ],
247                         'other'  => [
248                                 'data1'  => [
249                                         'config' => [
250                                                 'key12' => 'data4',
251                                                 'key45' => 7,
252                                         ],
253                                         'other'  => [
254                                                 'key1' => 'value1',
255                                                 'key2' => 'value2',
256                                         ],
257                                 ],
258                                 'data2'  => [
259                                         'other'  => [
260                                                 'key1' => 'overwritten!',
261                                                 'key3' => 'value3',
262                                         ],
263                                         'config' => [
264                                                 'key45' => 45,
265                                                 'key52' => true,
266                                         ]
267                                 ],
268                                 'expect' => [
269                                         'other'  => [
270                                                 // load should overwrite values everytime!
271                                                 'key1' => 'overwritten!',
272                                                 'key2' => 'value2',
273                                                 'key3' => 'value3',
274                                         ],
275                                         'config' => [
276                                                 'key12' => 'data4',
277                                                 'key45' => 45,
278                                                 'key52' => true,
279                                         ],
280                                 ],
281                         ],
282                 ];
283         }
284
285         /**
286          * Test the configuration load() method with overwrite
287          *
288          * @dataProvider dataDoubleLoad
289          */
290         public function testCacheLoadDouble(array $data1, array $data2, array $expect = [])
291         {
292                 $this->loadDirectFixture($this->configToDbArray($data1), $this->getDbInstance());
293
294                 $this->testedConfig = $this->getInstance();
295                 self::assertInstanceOf(Cache::class, $this->testedConfig->getCache());
296
297                 // Assert at least loaded cats are loaded
298                 foreach ($data1 as $cat => $data) {
299                         self::assertConfig($cat, $data);
300                 }
301
302                 $this->loadDirectFixture($this->configToDbArray($data2), $this->getDbInstance());
303
304                 $this->testedConfig->reload();
305
306                 foreach ($data2 as $cat => $data) {
307                         self::assertConfig($cat, $data);
308                 }
309         }
310
311         /**
312          * Test the configuration load without result
313          */
314         public function testLoadWrong()
315         {
316                 $this->testedConfig = new ReadOnlyFileConfig(new Cache());
317                 self::assertInstanceOf(Cache::class, $this->testedConfig->getCache());
318
319                 self::assertEmpty($this->testedConfig->getCache()->getAll());
320         }
321
322         /**
323          * Test the configuration get() and set() methods
324          *
325          * @dataProvider dataTests
326          */
327         public function testSetGet($data)
328         {
329                 $this->testedConfig = $this->getInstance();
330                 self::assertInstanceOf(Cache::class, $this->testedConfig->getCache());
331
332                 self::assertTrue($this->testedConfig->set('test', 'it', $data));
333
334                 self::assertEquals($data, $this->testedConfig->get('test', 'it'));
335                 self::assertEquals($data, $this->testedConfig->getCache()->get('test', 'it'));
336         }
337
338         /**
339          * Test the configuration get() method with wrong value and no db
340          */
341         public function testGetWrongWithoutDB()
342         {
343                 $this->testedConfig = $this->getInstance();
344                 self::assertInstanceOf(Cache::class, $this->testedConfig->getCache());
345
346                 // without refresh
347                 self::assertNull($this->testedConfig->get('test', 'it'));
348
349                 /// beware that the cache returns '!<unset>!' and not null for a nonexistent value
350                 self::assertNull($this->testedConfig->getCache()->get('test', 'it'));
351
352                 // with default value
353                 self::assertEquals('default', $this->testedConfig->get('test', 'it', 'default'));
354
355                 // with default value and refresh
356                 self::assertEquals('default', $this->testedConfig->get('test', 'it', 'default', true));
357         }
358
359         /**
360          * Test the configuration delete() method without a model/db
361          *
362          * @dataProvider dataTests
363          */
364         public function testDelete($data)
365         {
366                 $this->configCache->load(['test' => ['it' => $data]], Cache::SOURCE_FILE);
367
368                 $this->testedConfig = new DatabaseConfig($this->getDbInstance(), $this->configCache);
369                 self::assertInstanceOf(Cache::class, $this->testedConfig->getCache());
370
371                 self::assertEquals($data, $this->testedConfig->get('test', 'it'));
372                 self::assertEquals($data, $this->testedConfig->getCache()->get('test', 'it'));
373
374                 self::assertTrue($this->testedConfig->delete('test', 'it'));
375                 self::assertNull($this->testedConfig->get('test', 'it'));
376                 self::assertNull($this->testedConfig->getCache()->get('test', 'it'));
377         }
378
379         /**
380          * Test the configuration get() and set() method where the db value has a higher prio than the config file
381          */
382         public function testSetGetHighPrio()
383         {
384                 $this->testedConfig = $this->getInstance();
385                 self::assertInstanceOf(Cache::class, $this->testedConfig->getCache());
386
387                 $this->testedConfig->getCache()->set('config', 'test', 'prio', Cache::SOURCE_FILE);
388                 self::assertEquals('prio', $this->testedConfig->get('config', 'test'));
389
390                 // now you have to get the new variable entry because of the new set the get refresh succeed as well
391                 self::assertTrue($this->testedConfig->set('config', 'test', '123'));
392                 self::assertEquals('123', $this->testedConfig->get('config', 'test', '', true));
393         }
394
395         /**
396          * Test the configuration get() and set() method where the db value has a lower prio than the env
397          */
398         public function testSetGetLowPrio()
399         {
400                 $this->loadDirectFixture(['config' => [['cat' => 'config', 'k' => 'test', 'v' => 'it']]], $this->getDbInstance());
401
402                 $this->testedConfig = $this->getInstance();
403                 self::assertInstanceOf(Cache::class, $this->testedConfig->getCache());
404                 self::assertEquals('it', $this->testedConfig->get('config', 'test'));
405
406                 $this->testedConfig->getCache()->set('config', 'test', 'prio', Cache::SOURCE_ENV);
407                 // You can set a config value, but if there's a value with a higher priority (environment), this value will persist when retrieving
408                 self::assertTrue($this->testedConfig->set('config', 'test', '123'));
409                 self::assertEquals('prio', $this->testedConfig->get('config', 'test', '', true));
410         }
411
412
413         public function dataTestCat()
414         {
415                 return [
416                         'test_with_hashmap'     => [
417                                 'data'      => [
418                                         'test_with_hashmap' => [
419                                                 'notifyall' => [
420                                                         'last_update' => 1671051565,
421                                                         'admin'       => true,
422                                                 ],
423                                                 'blockbot'  => [
424                                                         'last_update' => 1658952852,
425                                                         'admin'       => true,
426                                                 ],
427                                         ],
428                                         'config'            => [
429                                                 'register_policy' => 2,
430                                                 'register_text'   => '',
431                                                 'sitename'        => 'Friendica Social Network23',
432                                                 'hostname'        => 'friendica.local',
433                                                 'private_addons'  => false,
434                                         ],
435                                         'system'            => [
436                                                 'dbclean_expire_conversation' => 90,
437                                         ],
438                                 ],
439                                 'cat'       => 'test_with_hashmap',
440                                 'assertion' => [
441                                         'notifyall' => [
442                                                 'last_update' => 1671051565,
443                                                 'admin'       => true,
444                                         ],
445                                         'blockbot'  => [
446                                                 'last_update' => 1658952852,
447                                                 'admin'       => true,
448                                         ],
449                                 ],
450                         ],
451                         'test_with_keys'        => [
452                                 'data'      => [
453                                         'test_with_keys' => [
454                                                 [
455                                                         'last_update' => 1671051565,
456                                                         'admin'       => true,
457                                                 ],
458                                                 [
459                                                         'last_update' => 1658952852,
460                                                         'admin'       => true,
461                                                 ],
462                                         ],
463                                         'config'            => [
464                                                 'register_policy' => 2,
465                                                 'register_text'   => '',
466                                                 'sitename'        => 'Friendica Social Network23',
467                                                 'hostname'        => 'friendica.local',
468                                                 'private_addons'  => false,
469                                         ],
470                                         'system'            => [
471                                                 'dbclean_expire_conversation' => 90,
472                                         ],
473                                 ],
474                                 'cat'       => 'test_with_keys',
475                                 'assertion' => [
476                                         [
477                                                 'last_update' => 1671051565,
478                                                 'admin'       => true,
479                                         ],
480                                         [
481                                                 'last_update' => 1658952852,
482                                                 'admin'       => true,
483                                         ],
484                                 ],
485                         ],
486                         'test_with_inner_array' => [
487                                 'data'      => [
488                                         'test_with_inner_array' => [
489                                                 'notifyall' => [
490                                                         'last_update' => 1671051565,
491                                                         'admin'       => [
492                                                                 'yes' => true,
493                                                                 'no'  => 1.5,
494                                                         ],
495                                                 ],
496                                                 'blogbot'   => [
497                                                         'last_update' => 1658952852,
498                                                         'admin'       => true,
499                                                 ],
500                                         ],
501                                         'config'                => [
502                                                 'register_policy' => 2,
503                                                 'register_text'   => '',
504                                                 'sitename'        => 'Friendica Social Network23',
505                                                 'hostname'        => 'friendica.local',
506                                                 'private_addons'  => false,
507                                         ],
508                                         'system'                => [
509                                                 'dbclean_expire_conversation' => 90,
510                                         ],
511                                 ],
512                                 'cat'       => 'test_with_inner_array',
513                                 'assertion' => [
514                                         'notifyall' => [
515                                                 'last_update' => 1671051565,
516                                                 'admin'       => [
517                                                         'yes' => true,
518                                                         'no'  => 1.5,
519                                                 ],
520                                         ],
521                                         'blogbot'   => [
522                                                 'last_update' => 1658952852,
523                                                 'admin'       => true,
524                                         ],
525                                 ],
526                         ],
527                 ];
528         }
529
530         /**
531          * @dataProvider dataTestCat
532          */
533         public function testGetCategory(array $data, string $category, array $assertion)
534         {
535                 $this->configCache = new Cache($data);
536                 $config = new ReadOnlyFileConfig($this->configCache);
537
538                 self::assertEquals($assertion, $config->get($category));
539         }
540
541         public function dataSerialized(): array
542         {
543                 return [
544                         'default' => [
545                                 'value' => ['test' => ['array']],
546                                 'assertion' => ['test' => ['array']],
547                         ],
548                         'issue-12803' => [
549                                 'value' => 's:48:"s:40:"s:32:"https://punkrock-underground.com";";";',
550                                 'assertion' => 'https://punkrock-underground.com',
551                         ],
552                         'double-serialized-array' => [
553                                 'value' => 's:53:"a:1:{s:9:"testArray";a:1:{s:4:"with";s:7:"entries";}}";',
554                                 'assertion' => ['testArray' => ['with' => 'entries']],
555                         ],
556                 ];
557         }
558
559         /**
560          * @dataProvider dataSerialized
561          */
562         public function testSerializedValues($value, $assertion)
563         {
564                 $config = $this->getInstance();
565
566                 $config->set('test', 'it', $value);
567                 self:self::assertEquals($assertion, $config->get('test', 'it'));
568         }
569
570         public function dataEnv(): array
571         {
572                 $data = [
573                         'config' => [
574                                 'admin_email' => 'value1',
575                                 'timezone' => 'value2',
576                                 'language' => 'value3',
577                                 'sitename' => 'value',
578                         ],
579                         'system' => [
580                                 'url' => 'value1a',
581                                 'debugging' => true,
582                                 'logfile' => 'value4',
583                                 'loglevel' => 'notice',
584                                 'proflier' => true,
585                         ],
586                         'proxy'  => [
587                                 'trusted_proxies' => 'value5',
588                         ],
589                 ];
590
591                 return [
592                         'empty' => [
593                                 'data'   => $data,
594                                 'server' => [],
595                                 'assertDisabled' => [],
596                         ],
597                         'mixed' => [
598                                 'data'   => $data,
599                                 'server' => [
600                                         'FRIENDICA_ADMIN_MAIL' => 'test@friendica.local',
601                                         'FRIENDICA_DEBUGGING' => true,
602                                 ],
603                                 'assertDisabled' => [
604                                         'config' => [
605                                                 'admin_email' => true,
606                                         ],
607                                         'system' => [
608                                                 'debugging' => true,
609                                         ],
610                                 ],
611                         ],
612                 ];
613         }
614
615         /**
616          * Tests if environment variables can change the permission to write a config key
617          *
618          * @dataProvider dataEnv
619          */
620         public function testIsWritable(array $data, array $server, array $assertDisabled)
621         {
622                 $this->setConfigFile('static' . DIRECTORY_SEPARATOR . 'env.config.php', true);
623                 $this->loadDirectFixture($this->configToDbArray($data), $this->getDbInstance());
624
625                 $configFileManager = new ConfigFileManager($this->root->url(), $this->root->url() . '/config/', $this->root->url() . '/static/', $server);
626                 $configFileManager->setupCache($this->configCache);
627                 $config = new DatabaseConfig($this->getDbInstance(), $this->configCache);
628
629                 foreach ($data as $category => $keyvalues) {
630                         foreach ($keyvalues as $key => $value) {
631                                 if (empty($assertDisabled[$category][$key])) {
632                                         static::assertTrue($config->isWritable($category, $key), sprintf('%s.%s is not true', $category, $key));
633                                 } else {
634                                         static::assertFalse($config->isWritable($category, $key), sprintf('%s.%s is not false', $category, $key));
635                                 }
636                         }
637                 }
638         }
639 }