]> git.mxchange.org Git - friendica.git/blob - tests/src/Core/StorageManagerTest.php
Merge pull request #10257 from annando/apcontact-no-normalize
[friendica.git] / tests / src / Core / StorageManagerTest.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;
23
24 use Dice\Dice;
25 use Friendica\Core\Config\IConfig;
26 use Friendica\Core\Config\PreloadConfig;
27 use Friendica\Core\Hook;
28 use Friendica\Core\L10n;
29 use Friendica\Core\Session\ISession;
30 use Friendica\Core\StorageManager;
31 use Friendica\Database\Database;
32 use Friendica\DI;
33 use Friendica\Factory\ConfigFactory;
34 use Friendica\Model\Config\Config;
35 use Friendica\Model\Storage;
36 use Friendica\Core\Session;
37 use Friendica\Model\Storage\StorageException;
38 use Friendica\Test\DatabaseTest;
39 use Friendica\Test\Util\Database\StaticDatabase;
40 use Friendica\Test\Util\VFSTrait;
41 use Friendica\Util\ConfigFileLoader;
42 use Friendica\Util\Profiler;
43 use Psr\Log\LoggerInterface;
44 use Psr\Log\NullLogger;
45 use Friendica\Test\Util\SampleStorageBackend;
46
47 class StorageManagerTest extends DatabaseTest
48 {
49         /** @var Database */
50         private $dba;
51         /** @var IConfig */
52         private $config;
53         /** @var LoggerInterface */
54         private $logger;
55         /** @var L10n */
56         private $l10n;
57
58         use VFSTrait;
59
60         protected function setUp(): void
61         {
62                 parent::setUp();
63
64                 $this->setUpVfsDir();
65
66                 $this->logger = new NullLogger();
67
68                 $profiler = \Mockery::mock(Profiler::class);
69                 $profiler->shouldReceive('saveTimestamp')->withAnyArgs()->andReturn(true);
70
71                 // load real config to avoid mocking every config-entry which is related to the Database class
72                 $configFactory = new ConfigFactory();
73                 $loader        = new ConfigFileLoader($this->root->url());
74                 $configCache   = $configFactory->createCache($loader);
75
76                 $this->dba = new StaticDatabase($configCache, $profiler, $this->logger);
77
78                 $configModel  = new Config($this->dba);
79                 $this->config = new PreloadConfig($configCache, $configModel);
80
81                 $this->l10n = \Mockery::mock(L10n::class);
82         }
83
84         /**
85          * Test plain instancing first
86          */
87         public function testInstance()
88         {
89                 $storageManager = new StorageManager($this->dba, $this->config, $this->logger, $this->l10n);
90
91                 self::assertInstanceOf(StorageManager::class, $storageManager);
92         }
93
94         public function dataStorages()
95         {
96                 return [
97                         'empty'          => [
98                                 'name'        => '',
99                                 'assert'      => null,
100                                 'assertName'  => '',
101                                 'userBackend' => false,
102                         ],
103                         'database'       => [
104                                 'name'        => Storage\Database::NAME,
105                                 'assert'      => Storage\Database::class,
106                                 'assertName'  => Storage\Database::NAME,
107                                 'userBackend' => true,
108                         ],
109                         'filesystem'     => [
110                                 'name'        => Storage\Filesystem::NAME,
111                                 'assert'      => Storage\Filesystem::class,
112                                 'assertName'  => Storage\Filesystem::NAME,
113                                 'userBackend' => true,
114                         ],
115                         'systemresource' => [
116                                 'name'        => Storage\SystemResource::NAME,
117                                 'assert'      => Storage\SystemResource::class,
118                                 'assertName'  => Storage\SystemResource::NAME,
119                                 // false here, because SystemResource isn't meant to be a user backend,
120                                 // it's for system resources only
121                                 'userBackend' => false,
122                         ],
123                         'invalid'        => [
124                                 'name'        => 'invalid',
125                                 'assert'      => null,
126                                 'assertName'  => '',
127                                 'userBackend' => false,
128                         ],
129                 ];
130         }
131
132         /**
133          * Data array for legacy backends
134          *
135          * @todo 2020.09 After 2 releases, remove the legacy functionality and these data array with it
136          *
137          * @return array
138          */
139         public function dataLegacyBackends()
140         {
141                 return [
142                         'legacyDatabase'          => [
143                                 'name'        => 'Friendica\Model\Storage\Database',
144                                 'assert'      => Storage\Database::class,
145                                 'assertName'  => Storage\Database::NAME,
146                                 'userBackend' => true,
147                         ],
148                         'legacyFilesystem'       => [
149                                 'name'        => 'Friendica\Model\Storage\Filesystem',
150                                 'assert'      => Storage\Filesystem::class,
151                                 'assertName'  => Storage\Filesystem::NAME,
152                                 'userBackend' => true,
153                         ],
154                         'legacySystemResource'     => [
155                                 'name'        => 'Friendica\Model\Storage\SystemResource',
156                                 'assert'      => Storage\SystemResource::class,
157                                 'assertName'  => Storage\SystemResource::NAME,
158                                 'userBackend' => false,
159                         ],
160                 ];
161         }
162
163         /**
164          * Test the getByName() method
165          *
166          * @dataProvider dataStorages
167          * @dataProvider dataLegacyBackends
168          */
169         public function testGetByName($name, $assert, $assertName, $userBackend)
170         {
171                 $storageManager = new StorageManager($this->dba, $this->config, $this->logger, $this->l10n);
172
173                 $storage = $storageManager->getByName($name, $userBackend);
174
175                 if (!empty($assert)) {
176                         self::assertInstanceOf(Storage\IStorage::class, $storage);
177                         self::assertInstanceOf($assert, $storage);
178                 } else {
179                         self::assertNull($storage);
180                 }
181                 self::assertEquals($assertName, $storage);
182         }
183
184         /**
185          * Test the isValidBackend() method
186          *
187          * @dataProvider dataStorages
188          */
189         public function testIsValidBackend($name, $assert, $assertName, $userBackend)
190         {
191                 $storageManager = new StorageManager($this->dba, $this->config, $this->logger, $this->l10n);
192
193                 // true in every of the backends
194                 self::assertEquals(!empty($assertName), $storageManager->isValidBackend($name));
195
196                 // if userBackend is set to true, filter out e.g. SystemRessource
197                 self::assertEquals($userBackend, $storageManager->isValidBackend($name, true));
198         }
199
200         /**
201          * Test the method listBackends() with default setting
202          */
203         public function testListBackends()
204         {
205                 $storageManager = new StorageManager($this->dba, $this->config, $this->logger, $this->l10n);
206
207                 self::assertEquals(StorageManager::DEFAULT_BACKENDS, $storageManager->listBackends());
208         }
209
210         /**
211          * Test the method getBackend()
212          *
213          * @dataProvider dataStorages
214          */
215         public function testGetBackend($name, $assert, $assertName, $userBackend)
216         {
217                 $storageManager = new StorageManager($this->dba, $this->config, $this->logger, $this->l10n);
218
219                 self::assertNull($storageManager->getBackend());
220
221                 if ($userBackend) {
222                         $storageManager->setBackend($name);
223
224                         self::assertInstanceOf($assert, $storageManager->getBackend());
225                 }
226         }
227
228         /**
229          * Test the method getBackend() with a pre-configured backend
230          *
231          * @dataProvider dataStorages
232          * @dataProvider dataLegacyBackends
233          */
234         public function testPresetBackend($name, $assert, $assertName, $userBackend)
235         {
236                 $this->config->set('storage', 'name', $name);
237
238                 $storageManager = new StorageManager($this->dba, $this->config, $this->logger, $this->l10n);
239
240                 if ($userBackend) {
241                         self::assertInstanceOf($assert, $storageManager->getBackend());
242                 } else {
243                         self::assertNull($storageManager->getBackend());
244                 }
245         }
246
247         /**
248          * Tests the register and unregister methods for a new backend storage class
249          *
250          * Uses a sample storage for testing
251          *
252          * @see SampleStorageBackend
253          */
254         public function testRegisterUnregisterBackends()
255         {
256                 /// @todo Remove dice once "Hook" is dynamic and mockable
257                 $dice   = (new Dice())
258                         ->addRules(include __DIR__ . '/../../../static/dependencies.config.php')
259                         ->addRule(Database::class, ['instanceOf' => StaticDatabase::class, 'shared' => true])
260                         ->addRule(ISession::class, ['instanceOf' => Session\Memory::class, 'shared' => true, 'call' => null]);
261                 DI::init($dice);
262
263                 $storageManager = new StorageManager($this->dba, $this->config, $this->logger, $this->l10n);
264
265                 self::assertTrue($storageManager->register(SampleStorageBackend::class));
266
267                 self::assertEquals(array_merge(StorageManager::DEFAULT_BACKENDS, [
268                         SampleStorageBackend::getName() => SampleStorageBackend::class,
269                 ]), $storageManager->listBackends());
270                 self::assertEquals(array_merge(StorageManager::DEFAULT_BACKENDS, [
271                         SampleStorageBackend::getName() => SampleStorageBackend::class,
272                 ]), $this->config->get('storage', 'backends'));
273
274                 // inline call to register own class as hook (testing purpose only)
275                 SampleStorageBackend::registerHook();
276                 Hook::loadHooks();
277
278                 self::assertTrue($storageManager->setBackend(SampleStorageBackend::NAME));
279                 self::assertEquals(SampleStorageBackend::NAME, $this->config->get('storage', 'name'));
280
281                 self::assertInstanceOf(SampleStorageBackend::class, $storageManager->getBackend());
282
283                 self::assertTrue($storageManager->unregister(SampleStorageBackend::class));
284                 self::assertEquals(StorageManager::DEFAULT_BACKENDS, $this->config->get('storage', 'backends'));
285                 self::assertEquals(StorageManager::DEFAULT_BACKENDS, $storageManager->listBackends());
286
287                 self::assertNull($storageManager->getBackend());
288                 self::assertNull($this->config->get('storage', 'name'));
289         }
290
291         /**
292          * Test moving data to a new storage (currently testing db & filesystem)
293          *
294          * @dataProvider dataStorages
295          */
296         public function testMoveStorage($name, $assert, $assertName, $userBackend)
297         {
298                 if (!$userBackend) {
299                         self::markTestSkipped("No user backend");
300                 }
301
302                 $this->loadFixture(__DIR__ . '/../../datasets/storage/database.fixture.php', $this->dba);
303
304                 $storageManager = new StorageManager($this->dba, $this->config, $this->logger, $this->l10n);
305                 $storage = $storageManager->getByName($name);
306                 $storageManager->move($storage);
307
308                 $photos = $this->dba->select('photo', ['backend-ref', 'backend-class', 'id', 'data']);
309
310                 while ($photo = $this->dba->fetch($photos)) {
311
312                         self::assertEmpty($photo['data']);
313
314                         $storage = $storageManager->getByName($photo['backend-class']);
315                         $data = $storage->get($photo['backend-ref']);
316
317                         self::assertNotEmpty($data);
318                 }
319         }
320
321         /**
322          * Test moving data to a WRONG storage
323          */
324         public function testMoveStorageWrong()
325         {
326                 $this->expectExceptionMessage("Can't move to storage backend 'SystemResource'");
327                 $this->expectException(StorageException::class);
328
329                 $storageManager = new StorageManager($this->dba, $this->config, $this->logger, $this->l10n);
330                 $storage = $storageManager->getByName(Storage\SystemResource::getName());
331                 $storageManager->move($storage);
332         }
333 }