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