3 namespace Friendica\Test\src\Core;
6 use Friendica\Core\Config\IConfig;
7 use Friendica\Core\Config\PreloadConfig;
8 use Friendica\Core\Hook;
9 use Friendica\Core\L10n;
10 use Friendica\Core\Session\ISession;
11 use Friendica\Core\StorageManager;
12 use Friendica\Database\Database;
14 use Friendica\Factory\ConfigFactory;
15 use Friendica\Model\Config\Config;
16 use Friendica\Model\Storage;
17 use Friendica\Core\Session;
18 use Friendica\Test\DatabaseTest;
19 use Friendica\Test\Util\Database\StaticDatabase;
20 use Friendica\Test\Util\VFSTrait;
21 use Friendica\Util\ConfigFileLoader;
22 use Friendica\Util\Profiler;
23 use Psr\Log\LoggerInterface;
24 use Psr\Log\NullLogger;
25 use Friendica\Test\Util\SampleStorageBackend;
27 class StorageManagerTest extends DatabaseTest
33 /** @var LoggerInterface */
40 public function setUp()
46 $this->logger = new NullLogger();
48 $profiler = \Mockery::mock(Profiler::class);
49 $profiler->shouldReceive('saveTimestamp')->withAnyArgs()->andReturn(true);
51 // load real config to avoid mocking every config-entry which is related to the Database class
52 $configFactory = new ConfigFactory();
53 $loader = new ConfigFileLoader($this->root->url());
54 $configCache = $configFactory->createCache($loader);
56 $this->dba = new StaticDatabase($configCache, $profiler, $this->logger);
58 $configModel = new Config($this->dba);
59 $this->config = new PreloadConfig($configCache, $configModel);
61 $this->l10n = \Mockery::mock(L10n::class);
65 * Test plain instancing first
67 public function testInstance()
69 $storageManager = new StorageManager($this->dba, $this->config, $this->logger, $this->l10n);
71 $this->assertInstanceOf(StorageManager::class, $storageManager);
74 public function dataStorages()
81 'userBackend' => false,
84 'name' => Storage\Database::NAME,
85 'assert' => Storage\Database::class,
86 'assertName' => Storage\Database::NAME,
87 'userBackend' => true,
90 'name' => Storage\Filesystem::NAME,
91 'assert' => Storage\Filesystem::class,
92 'assertName' => Storage\Filesystem::NAME,
93 'userBackend' => true,
96 'name' => Storage\SystemResource::NAME,
97 'assert' => Storage\SystemResource::class,
98 'assertName' => Storage\SystemResource::NAME,
99 // false here, because SystemResource isn't meant to be a user backend,
100 // it's for system resources only
101 'userBackend' => false,
107 'userBackend' => false,
113 * Data array for legacy backends
115 * @todo 2020.09 After 2 releases, remove the legacy functionality and these data array with it
119 public function dataLegacyBackends()
122 'legacyDatabase' => [
123 'name' => 'Friendica\Model\Storage\Database',
124 'assert' => Storage\Database::class,
125 'assertName' => Storage\Database::NAME,
126 'userBackend' => true,
128 'legacyFilesystem' => [
129 'name' => 'Friendica\Model\Storage\Filesystem',
130 'assert' => Storage\Filesystem::class,
131 'assertName' => Storage\Filesystem::NAME,
132 'userBackend' => true,
134 'legacySystemResource' => [
135 'name' => 'Friendica\Model\Storage\SystemResource',
136 'assert' => Storage\SystemResource::class,
137 'assertName' => Storage\SystemResource::NAME,
138 'userBackend' => false,
144 * Test the getByName() method
146 * @dataProvider dataStorages
147 * @dataProvider dataLegacyBackends
149 public function testGetByName($name, $assert, $assertName, $userBackend)
151 $storageManager = new StorageManager($this->dba, $this->config, $this->logger, $this->l10n);
153 $storage = $storageManager->getByName($name, $userBackend);
155 if (!empty($assert)) {
156 $this->assertInstanceOf(Storage\IStorage::class, $storage);
157 $this->assertInstanceOf($assert, $storage);
159 $this->assertNull($storage);
161 $this->assertEquals($assertName, $storage);
165 * Test the isValidBackend() method
167 * @dataProvider dataStorages
169 public function testIsValidBackend($name, $assert, $assertName, $userBackend)
171 $storageManager = new StorageManager($this->dba, $this->config, $this->logger, $this->l10n);
173 // true in every of the backends
174 $this->assertEquals(!empty($assertName), $storageManager->isValidBackend($name));
176 // if userBackend is set to true, filter out e.g. SystemRessource
177 $this->assertEquals($userBackend, $storageManager->isValidBackend($name, true));
181 * Test the method listBackends() with default setting
183 public function testListBackends()
185 $storageManager = new StorageManager($this->dba, $this->config, $this->logger, $this->l10n);
187 $this->assertEquals(StorageManager::DEFAULT_BACKENDS, $storageManager->listBackends());
191 * Test the method getBackend()
193 * @dataProvider dataStorages
195 public function testGetBackend($name, $assert, $assertName, $userBackend)
197 $storageManager = new StorageManager($this->dba, $this->config, $this->logger, $this->l10n);
199 $this->assertNull($storageManager->getBackend());
202 $storageManager->setBackend($name);
204 $this->assertInstanceOf($assert, $storageManager->getBackend());
209 * Test the method getBackend() with a pre-configured backend
211 * @dataProvider dataStorages
212 * @dataProvider dataLegacyBackends
214 public function testPresetBackend($name, $assert, $assertName, $userBackend)
216 $this->config->set('storage', 'name', $name);
218 $storageManager = new StorageManager($this->dba, $this->config, $this->logger, $this->l10n);
221 $this->assertInstanceOf($assert, $storageManager->getBackend());
223 $this->assertNull($storageManager->getBackend());
228 * Tests the register and unregister methods for a new backend storage class
230 * Uses a sample storage for testing
232 * @see SampleStorageBackend
234 public function testRegisterUnregisterBackends()
236 /// @todo Remove dice once "Hook" is dynamic and mockable
238 ->addRules(include __DIR__ . '/../../../static/dependencies.config.php')
239 ->addRule(Database::class, ['instanceOf' => StaticDatabase::class, 'shared' => true])
240 ->addRule(ISession::class, ['instanceOf' => Session\Memory::class, 'shared' => true, 'call' => null]);
243 $storageManager = new StorageManager($this->dba, $this->config, $this->logger, $this->l10n);
245 $this->assertTrue($storageManager->register(SampleStorageBackend::class));
247 $this->assertEquals(array_merge(StorageManager::DEFAULT_BACKENDS, [
248 SampleStorageBackend::getName() => SampleStorageBackend::class,
249 ]), $storageManager->listBackends());
250 $this->assertEquals(array_merge(StorageManager::DEFAULT_BACKENDS, [
251 SampleStorageBackend::getName() => SampleStorageBackend::class,
252 ]), $this->config->get('storage', 'backends'));
254 // inline call to register own class as hook (testing purpose only)
255 SampleStorageBackend::registerHook();
258 $this->assertTrue($storageManager->setBackend(SampleStorageBackend::NAME));
259 $this->assertEquals(SampleStorageBackend::NAME, $this->config->get('storage', 'name'));
261 $this->assertInstanceOf(SampleStorageBackend::class, $storageManager->getBackend());
263 $this->assertTrue($storageManager->unregister(SampleStorageBackend::class));
264 $this->assertEquals(StorageManager::DEFAULT_BACKENDS, $this->config->get('storage', 'backends'));
265 $this->assertEquals(StorageManager::DEFAULT_BACKENDS, $storageManager->listBackends());
267 $this->assertNull($storageManager->getBackend());
268 $this->assertNull($this->config->get('storage', 'name'));
272 * Test moving data to a new storage (currently testing db & filesystem)
274 * @dataProvider dataStorages
276 public function testMoveStorage($name, $assert, $assertName, $userBackend)
282 $this->loadFixture(__DIR__ . '/../../datasets/storage/database.fixture.php', $this->dba);
284 $storageManager = new StorageManager($this->dba, $this->config, $this->logger, $this->l10n);
285 $storage = $storageManager->getByName($name);
286 $storageManager->move($storage);
288 $photos = $this->dba->select('photo', ['backend-ref', 'backend-class', 'id', 'data']);
290 while ($photo = $this->dba->fetch($photos)) {
292 $this->assertEmpty($photo['data']);
294 $storage = $storageManager->getByName($photo['backend-class']);
295 $data = $storage->get($photo['backend-ref']);
297 $this->assertNotEmpty($data);
302 * Test moving data to a WRONG storage
304 * @expectedException \Friendica\Model\Storage\StorageException
305 * @expectedExceptionMessage Can't move to storage backend 'SystemResource'
307 public function testMoveStorageWrong()
309 $storageManager = new StorageManager($this->dba, $this->config, $this->logger, $this->l10n);
310 $storage = $storageManager->getByName(Storage\SystemResource::getName());
311 $storageManager->move($storage);