aboutsummaryrefslogtreecommitdiffstats
path: root/tests/lib/AppConfigTest.php
diff options
context:
space:
mode:
Diffstat (limited to 'tests/lib/AppConfigTest.php')
-rw-r--r--tests/lib/AppConfigTest.php1596
1 files changed, 1346 insertions, 250 deletions
diff --git a/tests/lib/AppConfigTest.php b/tests/lib/AppConfigTest.php
index d4ae66cb2f1..86bd339bc7e 100644
--- a/tests/lib/AppConfigTest.php
+++ b/tests/lib/AppConfigTest.php
@@ -1,17 +1,36 @@
<?php
+
+declare(strict_types=1);
/**
- * Copyright (c) 2013 Christopher Schäpers <christopher@schaepers.it>
- * Copyright (c) 2013 Bart Visscher <bartv@thisnet.nl>
- * This file is licensed under the Affero General Public License version 3 or
- * later.
- * See the COPYING-README file.
+ * @copyright Copyright (c) 2024, Maxence Lange <maxence@artificial-owl.com>
+ *
+ * @author Maxence Lange <maxence@artificial-owl.com>
+ *
+ * @license AGPL-3.0 or later
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
*/
-
namespace Test;
+use InvalidArgumentException;
use OC\AppConfig;
-use OC\DB\Connection;
-use OCP\IConfig;
+use OCP\Exceptions\AppConfigTypeConflictException;
+use OCP\Exceptions\AppConfigUnknownKeyException;
+use OCP\IAppConfig;
+use OCP\IDBConnection;
+use OCP\Security\ICrypto;
+use Psr\Log\LoggerInterface;
/**
* Class AppConfigTest
@@ -21,348 +40,1425 @@ use OCP\IConfig;
* @package Test
*/
class AppConfigTest extends TestCase {
- /** @var \OCP\IAppConfig */
- protected $appConfig;
-
- /** @var Connection */
- protected $connection;
+ protected IAppConfig $appConfig;
+ protected IDBConnection $connection;
+ private LoggerInterface $logger;
+ private ICrypto $crypto;
+ private array $originalConfig;
- protected $originalConfig;
+ /**
+ * @var array<string, array<array<string, string, int, bool, bool>>>
+ * [appId => [configKey, configValue, valueType, lazy, sensitive]]
+ */
+ private array $baseStruct =
+ [
+ 'testapp' => [
+ 'enabled' => ['enabled', 'true'],
+ 'installed_version' => ['installed_version', '1.2.3'],
+ 'depends_on' => ['depends_on', 'someapp'],
+ 'deletethis' => ['deletethis', 'deletethis'],
+ 'key' => ['key', 'value']
+ ],
+ 'someapp' => [
+ 'key' => ['key', 'value'],
+ 'otherkey' => ['otherkey', 'othervalue']
+ ],
+ '123456' => [
+ 'enabled' => ['enabled', 'true'],
+ 'key' => ['key', 'value']
+ ],
+ 'anotherapp' => [
+ 'enabled' => ['enabled', 'false'],
+ 'key' => ['key', 'value']
+ ],
+ 'non-sensitive-app' => [
+ 'lazy-key' => ['lazy-key', 'value', IAppConfig::VALUE_STRING, true, false],
+ 'non-lazy-key' => ['non-lazy-key', 'value', IAppConfig::VALUE_STRING, false, false],
+ ],
+ 'sensitive-app' => [
+ 'lazy-key' => ['lazy-key', 'value', IAppConfig::VALUE_STRING, true, true],
+ 'non-lazy-key' => ['non-lazy-key', 'value', IAppConfig::VALUE_STRING, false, true],
+ ],
+ 'only-lazy' => [
+ 'lazy-key' => ['lazy-key', 'value', IAppConfig::VALUE_STRING, true]
+ ],
+ 'typed' => [
+ 'mixed' => ['mixed', 'mix', IAppConfig::VALUE_MIXED],
+ 'string' => ['string', 'value', IAppConfig::VALUE_STRING],
+ 'int' => ['int', '42', IAppConfig::VALUE_INT],
+ 'float' => ['float', '3.14', IAppConfig::VALUE_FLOAT],
+ 'bool' => ['bool', '1', IAppConfig::VALUE_BOOL],
+ 'array' => ['array', '{"test": 1}', IAppConfig::VALUE_ARRAY],
+ ],
+ 'prefix-app' => [
+ 'key1' => ['key1', 'value'],
+ 'prefix1' => ['prefix1', 'value'],
+ 'prefix-2' => ['prefix-2', 'value'],
+ 'key-2' => ['key-2', 'value'],
+ ]
+ ];
protected function setUp(): void {
parent::setUp();
- $this->connection = \OC::$server->get(Connection::class);
+ $this->connection = \OCP\Server::get(IDBConnection::class);
+ $this->logger = \OCP\Server::get(LoggerInterface::class);
+ $this->crypto = \OCP\Server::get(ICrypto::class);
+
+ // storing current config and emptying the data table
$sql = $this->connection->getQueryBuilder();
$sql->select('*')
->from('appconfig');
- $result = $sql->execute();
+ $result = $sql->executeQuery();
$this->originalConfig = $result->fetchAll();
$result->closeCursor();
$sql = $this->connection->getQueryBuilder();
$sql->delete('appconfig');
- $sql->execute();
-
- $this->overwriteService(AppConfig::class, new \OC\AppConfig($this->connection));
+ $sql->executeStatement();
$sql = $this->connection->getQueryBuilder();
$sql->insert('appconfig')
- ->values([
- 'appid' => $sql->createParameter('appid'),
- 'configkey' => $sql->createParameter('configkey'),
- 'configvalue' => $sql->createParameter('configvalue'),
- ]);
-
- $sql->setParameters([
- 'appid' => 'testapp',
- 'configkey' => 'enabled',
- 'configvalue' => 'true',
- ])->execute();
- $sql->setParameters([
- 'appid' => 'testapp',
- 'configkey' => 'installed_version',
- 'configvalue' => '1.2.3',
- ])->execute();
- $sql->setParameters([
- 'appid' => 'testapp',
- 'configkey' => 'depends_on',
- 'configvalue' => 'someapp',
- ])->execute();
- $sql->setParameters([
- 'appid' => 'testapp',
- 'configkey' => 'deletethis',
- 'configvalue' => 'deletethis',
- ])->execute();
- $sql->setParameters([
- 'appid' => 'testapp',
- 'configkey' => 'key',
- 'configvalue' => 'value',
- ])->execute();
-
- $sql->setParameters([
- 'appid' => 'someapp',
- 'configkey' => 'key',
- 'configvalue' => 'value',
- ])->execute();
- $sql->setParameters([
- 'appid' => 'someapp',
- 'configkey' => 'otherkey',
- 'configvalue' => 'othervalue',
- ])->execute();
-
- $sql->setParameters([
- 'appid' => '123456',
- 'configkey' => 'key',
- 'configvalue' => 'value',
- ])->execute();
- $sql->setParameters([
- 'appid' => '123456',
- 'configkey' => 'enabled',
- 'configvalue' => 'false',
- ])->execute();
-
- $sql->setParameters([
- 'appid' => 'anotherapp',
- 'configkey' => 'key',
- 'configvalue' => 'value',
- ])->execute();
- $sql->setParameters([
- 'appid' => 'anotherapp',
- 'configkey' => 'enabled',
- 'configvalue' => 'false',
- ])->execute();
+ ->values(
+ [
+ 'appid' => $sql->createParameter('appid'),
+ 'configkey' => $sql->createParameter('configkey'),
+ 'configvalue' => $sql->createParameter('configvalue'),
+ 'type' => $sql->createParameter('type'),
+ 'lazy' => $sql->createParameter('lazy')
+ ]
+ );
+
+ foreach ($this->baseStruct as $appId => $appData) {
+ foreach ($appData as $key => $row) {
+ $value = $row[1];
+ $type = $row[2] ?? IAppConfig::VALUE_MIXED;
+ if (($row[4] ?? false) === true) {
+ $type |= IAppConfig::VALUE_SENSITIVE;
+ $value = self::invokePrivate(AppConfig::class, 'ENCRYPTION_PREFIX') . $this->crypto->encrypt($value);
+ $this->baseStruct[$appId][$key]['encrypted'] = $value;
+ }
+
+ $sql->setParameters(
+ [
+ 'appid' => $appId,
+ 'configkey' => $row[0],
+ 'configvalue' => $value,
+ 'type' => $type,
+ 'lazy' => (($row[3] ?? false) === true) ? 1 : 0
+ ]
+ )->executeStatement();
+ }
+ }
}
protected function tearDown(): void {
$sql = $this->connection->getQueryBuilder();
$sql->delete('appconfig');
- $sql->execute();
+ $sql->executeStatement();
$sql = $this->connection->getQueryBuilder();
$sql->insert('appconfig')
- ->values([
- 'appid' => $sql->createParameter('appid'),
- 'configkey' => $sql->createParameter('configkey'),
- 'configvalue' => $sql->createParameter('configvalue'),
- ]);
-
- foreach ($this->originalConfig as $configs) {
+ ->values(
+ [
+ 'appid' => $sql->createParameter('appid'),
+ 'configkey' => $sql->createParameter('configkey'),
+ 'configvalue' => $sql->createParameter('configvalue'),
+ 'lazy' => $sql->createParameter('lazy'),
+ 'type' => $sql->createParameter('type'),
+ ]
+ );
+
+ foreach ($this->originalConfig as $key => $configs) {
$sql->setParameter('appid', $configs['appid'])
->setParameter('configkey', $configs['configkey'])
- ->setParameter('configvalue', $configs['configvalue']);
- $sql->execute();
+ ->setParameter('configvalue', $configs['configvalue'])
+ ->setParameter('lazy', ($configs['lazy'] === '1') ? '1' : '0')
+ ->setParameter('type', $configs['type']);
+ $sql->executeStatement();
}
- $this->restoreService(AppConfig::class);
+ // $this->restoreService(AppConfig::class);
parent::tearDown();
}
- public function testGetApps() {
- $config = new \OC\AppConfig(\OC::$server->get(Connection::class));
+ /**
+ * @param bool $preLoading TRUE will preload the 'fast' cache, which is the normal behavior of usual
+ * IAppConfig
+ *
+ * @return IAppConfig
+ */
+ private function generateAppConfig(bool $preLoading = true): IAppConfig {
+ /** @var AppConfig $config */
+ $config = new \OC\AppConfig(
+ $this->connection,
+ $this->logger,
+ $this->crypto,
+ );
+ $msg = ' generateAppConfig() failed to confirm cache status';
+
+ // confirm cache status
+ $status = $config->statusCache();
+ $this->assertSame(false, $status['fastLoaded'], $msg);
+ $this->assertSame(false, $status['lazyLoaded'], $msg);
+ $this->assertSame([], $status['fastCache'], $msg);
+ $this->assertSame([], $status['lazyCache'], $msg);
+ if ($preLoading) {
+ // simple way to initiate the load of non-lazy config values in cache
+ $config->getValueString('core', 'preload', '');
+
+ // confirm cache status
+ $status = $config->statusCache();
+ $this->assertSame(true, $status['fastLoaded'], $msg);
+ $this->assertSame(false, $status['lazyLoaded'], $msg);
+
+ $apps = array_values(array_diff(array_keys($this->baseStruct), ['only-lazy']));
+ $this->assertEqualsCanonicalizing($apps, array_keys($status['fastCache']), $msg);
+ $this->assertSame([], array_keys($status['lazyCache']), $msg);
+ }
+
+ return $config;
+ }
+
+ public function testGetApps(): void {
+ $config = $this->generateAppConfig(false);
+
+ $this->assertEqualsCanonicalizing(array_keys($this->baseStruct), $config->getApps());
+ }
+
+ /**
+ * returns list of app and their keys
+ *
+ * @return array<string, string[]> ['appId' => ['key1', 'key2', ]]
+ * @see testGetKeys
+ */
+ public function providerGetAppKeys(): array {
+ $appKeys = [];
+ foreach ($this->baseStruct as $appId => $appData) {
+ $keys = [];
+ foreach ($appData as $row) {
+ $keys[] = $row[0];
+ }
+ $appKeys[] = [(string)$appId, $keys];
+ }
- $this->assertEqualsCanonicalizing([
- 'anotherapp',
- 'someapp',
- 'testapp',
- 123456,
- ], $config->getApps());
+ return $appKeys;
}
- public function testGetKeys() {
- $config = new \OC\AppConfig(\OC::$server->get(Connection::class));
+ /**
+ * returns list of config keys
+ *
+ * @return array<string, string, string, int, bool, bool> [appId, key, value, type, lazy, sensitive]
+ * @see testIsSensitive
+ * @see testIsLazy
+ * @see testGetKeys
+ */
+ public function providerGetKeys(): array {
+ $appKeys = [];
+ foreach ($this->baseStruct as $appId => $appData) {
+ foreach ($appData as $row) {
+ $appKeys[] = [
+ (string)$appId, $row[0], $row[1], $row[2] ?? IAppConfig::VALUE_MIXED, $row[3] ?? false,
+ $row[4] ?? false
+ ];
+ }
+ }
- $keys = $config->getKeys('testapp');
- $this->assertEqualsCanonicalizing([
- 'deletethis',
- 'depends_on',
- 'enabled',
- 'installed_version',
- 'key',
- ], $keys);
+ return $appKeys;
}
- public function testGetValue() {
- $config = new \OC\AppConfig(\OC::$server->get(Connection::class));
+ /**
+ * @dataProvider providerGetAppKeys
+ *
+ * @param string $appId
+ * @param array $expectedKeys
+ */
+ public function testGetKeys(string $appId, array $expectedKeys): void {
+ $config = $this->generateAppConfig();
+ $this->assertEqualsCanonicalizing($expectedKeys, $config->getKeys($appId));
+ }
- $value = $config->getValue('testapp', 'installed_version');
- $this->assertConfigKey('testapp', 'installed_version', $value);
+ public function testGetKeysOnUnknownAppShouldReturnsEmptyArray(): void {
+ $config = $this->generateAppConfig();
+ $this->assertEqualsCanonicalizing([], $config->getKeys('unknown-app'));
+ }
- $value = $config->getValue('testapp', 'nonexistant');
- $this->assertNull($value);
+ /**
+ * @dataProvider providerGetKeys
+ *
+ * @param string $appId
+ * @param string $configKey
+ * @param string $value
+ * @param bool $lazy
+ */
+ public function testHasKey(string $appId, string $configKey, string $value, int $type, bool $lazy): void {
+ $config = $this->generateAppConfig();
+ $this->assertEquals(true, $config->hasKey($appId, $configKey, $lazy));
+ }
- $value = $config->getValue('testapp', 'nonexistant', 'default');
- $this->assertEquals('default', $value);
+ public function testHasKeyOnNonExistentKeyReturnsFalse(): void {
+ $config = $this->generateAppConfig();
+ $this->assertEquals(false, $config->hasKey(array_keys($this->baseStruct)[0], 'inexistant-key'));
}
- public function testHasKey() {
- $config = new \OC\AppConfig(\OC::$server->get(Connection::class));
+ public function testHasKeyOnUnknownAppReturnsFalse(): void {
+ $config = $this->generateAppConfig();
+ $this->assertEquals(false, $config->hasKey('inexistant-app', 'inexistant-key'));
+ }
- $this->assertTrue($config->hasKey('testapp', 'installed_version'));
- $this->assertFalse($config->hasKey('testapp', 'nonexistant'));
- $this->assertFalse($config->hasKey('nonexistant', 'nonexistant'));
+ public function testHasKeyOnMistypedAsLazyReturnsFalse(): void {
+ $config = $this->generateAppConfig();
+ $this->assertSame(false, $config->hasKey('non-sensitive-app', 'non-lazy-key', true));
}
- public function testSetValueUpdate() {
- $config = new \OC\AppConfig(\OC::$server->get(Connection::class));
+ public function testHasKeyOnMistypeAsNonLazyReturnsFalse(): void {
+ $config = $this->generateAppConfig();
+ $this->assertSame(false, $config->hasKey('non-sensitive-app', 'lazy-key', false));
+ }
- $this->assertEquals('1.2.3', $config->getValue('testapp', 'installed_version'));
- $this->assertConfigKey('testapp', 'installed_version', '1.2.3');
+ public function testHasKeyOnMistypeAsNonLazyReturnsTrueWithLazyArgumentIsNull(): void {
+ $config = $this->generateAppConfig();
+ $this->assertSame(true, $config->hasKey('non-sensitive-app', 'lazy-key', null));
+ }
- $wasModified = $config->setValue('testapp', 'installed_version', '1.2.3');
- if (!(\OC::$server->get(Connection::class) instanceof \OC\DB\OracleConnection)) {
- $this->assertFalse($wasModified);
- }
+ /**
+ * @dataProvider providerGetKeys
+ */
+ public function testIsSensitive(
+ string $appId, string $configKey, string $configValue, int $type, bool $lazy, bool $sensitive
+ ): void {
+ $config = $this->generateAppConfig();
+ $this->assertEquals($sensitive, $config->isSensitive($appId, $configKey, $lazy));
+ }
- $this->assertEquals('1.2.3', $config->getValue('testapp', 'installed_version'));
- $this->assertConfigKey('testapp', 'installed_version', '1.2.3');
+ public function testIsSensitiveOnNonExistentKeyThrowsException(): void {
+ $config = $this->generateAppConfig();
+ $this->expectException(AppConfigUnknownKeyException::class);
+ $config->isSensitive(array_keys($this->baseStruct)[0], 'inexistant-key');
+ }
- $this->assertTrue($config->setValue('testapp', 'installed_version', '1.33.7'));
+ public function testIsSensitiveOnUnknownAppThrowsException(): void {
+ $config = $this->generateAppConfig();
+ $this->expectException(AppConfigUnknownKeyException::class);
+ $config->isSensitive('unknown-app', 'inexistant-key');
+ }
+ public function testIsSensitiveOnSensitiveMistypedAsLazy(): void {
+ $config = $this->generateAppConfig();
+ $this->assertSame(true, $config->isSensitive('sensitive-app', 'non-lazy-key', true));
+ }
- $this->assertEquals('1.33.7', $config->getValue('testapp', 'installed_version'));
- $this->assertConfigKey('testapp', 'installed_version', '1.33.7');
+ public function testIsSensitiveOnNonSensitiveMistypedAsLazy(): void {
+ $config = $this->generateAppConfig();
+ $this->assertSame(false, $config->isSensitive('non-sensitive-app', 'non-lazy-key', true));
+ }
- $config->setValue('someapp', 'somekey', 'somevalue');
- $this->assertConfigKey('someapp', 'somekey', 'somevalue');
+ public function testIsSensitiveOnSensitiveMistypedAsNonLazyThrowsException(): void {
+ $config = $this->generateAppConfig();
+ $this->expectException(AppConfigUnknownKeyException::class);
+ $config->isSensitive('sensitive-app', 'lazy-key', false);
}
- public function testSetValueInsert() {
- $config = new \OC\AppConfig(\OC::$server->get(Connection::class));
+ public function testIsSensitiveOnNonSensitiveMistypedAsNonLazyThrowsException(): void {
+ $config = $this->generateAppConfig();
+ $this->expectException(AppConfigUnknownKeyException::class);
+ $config->isSensitive('non-sensitive-app', 'lazy-key', false);
+ }
- $this->assertFalse($config->hasKey('someapp', 'somekey'));
- $this->assertNull($config->getValue('someapp', 'somekey'));
+ /**
+ * @dataProvider providerGetKeys
+ */
+ public function testIsLazy(string $appId, string $configKey, string $configValue, int $type, bool $lazy
+ ): void {
+ $config = $this->generateAppConfig();
+ $this->assertEquals($lazy, $config->isLazy($appId, $configKey));
+ }
- $this->assertTrue($config->setValue('someapp', 'somekey', 'somevalue'));
+ public function testIsLazyOnNonExistentKeyThrowsException(): void {
+ $config = $this->generateAppConfig();
+ $this->expectException(AppConfigUnknownKeyException::class);
+ $config->isLazy(array_keys($this->baseStruct)[0], 'inexistant-key');
+ }
- $this->assertTrue($config->hasKey('someapp', 'somekey'));
- $this->assertEquals('somevalue', $config->getValue('someapp', 'somekey'));
- $this->assertConfigKey('someapp', 'somekey', 'somevalue');
+ public function testIsLazyOnUnknownAppThrowsException(): void {
+ $config = $this->generateAppConfig();
+ $this->expectException(AppConfigUnknownKeyException::class);
+ $config->isLazy('unknown-app', 'inexistant-key');
+ }
- $wasInserted = $config->setValue('someapp', 'somekey', 'somevalue');
- if (!(\OC::$server->get(Connection::class) instanceof \OC\DB\OracleConnection)) {
- $this->assertFalse($wasInserted);
- }
+ public function testGetAllValuesWithEmptyApp(): void {
+ $config = $this->generateAppConfig();
+ $this->expectException(InvalidArgumentException::class);
+ $config->getAllValues('');
}
- public function testDeleteKey() {
- $config = new \OC\AppConfig(\OC::$server->get(Connection::class));
+ /**
+ * @dataProvider providerGetAppKeys
+ *
+ * @param string $appId
+ * @param array $keys
+ */
+ public function testGetAllValuesWithEmptyKey(string $appId, array $keys): void {
+ $config = $this->generateAppConfig();
+ $this->assertEqualsCanonicalizing($keys, array_keys($config->getAllValues($appId, '')));
+ }
- $this->assertTrue($config->hasKey('testapp', 'deletethis'));
+ public function testGetAllValuesWithPrefix(): void {
+ $config = $this->generateAppConfig();
+ $this->assertEqualsCanonicalizing(['prefix1', 'prefix-2'], array_keys($config->getAllValues('prefix-app', 'prefix')));
+ }
- $config->deleteKey('testapp', 'deletethis');
+ public function testSearchValues(): void {
+ $config = $this->generateAppConfig();
+ $this->assertEqualsCanonicalizing(['testapp' => 'true', '123456' => 'true', 'anotherapp' => 'false'], $config->searchValues('enabled'));
+ }
- $this->assertFalse($config->hasKey('testapp', 'deletethis'));
+ public function testGetValueString(): void {
+ $config = $this->generateAppConfig();
+ $this->assertSame('value', $config->getValueString('typed', 'string', ''));
+ }
- $sql = \OC::$server->getDatabaseConnection()->getQueryBuilder();
- $sql->select('configvalue')
- ->from('appconfig')
- ->where($sql->expr()->eq('appid', $sql->createParameter('appid')))
- ->andWhere($sql->expr()->eq('configkey', $sql->createParameter('configkey')))
- ->setParameter('appid', 'testapp')
- ->setParameter('configkey', 'deletethis');
- $query = $sql->execute();
- $result = $query->fetch();
- $query->closeCursor();
- $this->assertFalse($result);
+ public function testGetValueStringOnUnknownAppReturnsDefault(): void {
+ $config = $this->generateAppConfig();
+ $this->assertSame('default-1', $config->getValueString('typed-1', 'string', 'default-1'));
}
- public function testDeleteApp() {
- $config = new \OC\AppConfig(\OC::$server->get(Connection::class));
+ public function testGetValueStringOnNonExistentKeyReturnsDefault(): void {
+ $config = $this->generateAppConfig();
+ $this->assertSame('default-2', $config->getValueString('typed', 'string-2', 'default-2'));
+ }
- $this->assertTrue($config->hasKey('someapp', 'otherkey'));
+ public function testGetValueStringOnWrongType(): void {
+ $config = $this->generateAppConfig();
+ $this->expectException(AppConfigTypeConflictException::class);
+ $config->getValueString('typed', 'int');
+ }
- $config->deleteApp('someapp');
+ public function testGetNonLazyValueStringAsLazy(): void {
+ $config = $this->generateAppConfig();
+ $this->assertSame('value', $config->getValueString('non-sensitive-app', 'non-lazy-key', 'default', lazy: true));
+ }
- $this->assertFalse($config->hasKey('someapp', 'otherkey'));
+ public function testGetValueInt() {
+ $config = $this->generateAppConfig();
+ $this->assertSame(42, $config->getValueInt('typed', 'int', 0));
+ }
- $sql = \OC::$server->getDatabaseConnection()->getQueryBuilder();
- $sql->select('configvalue')
- ->from('appconfig')
- ->where($sql->expr()->eq('appid', $sql->createParameter('appid')))
- ->setParameter('appid', 'someapp');
- $query = $sql->execute();
- $result = $query->fetch();
- $query->closeCursor();
- $this->assertFalse($result);
+ public function testGetValueIntOnUnknownAppReturnsDefault(): void {
+ $config = $this->generateAppConfig();
+ $this->assertSame(1, $config->getValueInt('typed-1', 'int', 1));
}
- public function testGetValuesNotAllowed() {
- $config = new \OC\AppConfig(\OC::$server->get(Connection::class));
+ public function testGetValueIntOnNonExistentKeyReturnsDefault() {
+ $config = $this->generateAppConfig();
+ $this->assertSame(2, $config->getValueInt('typed', 'int-2', 2));
+ }
+
+ public function testGetValueIntOnWrongType(): void {
+ $config = $this->generateAppConfig();
+ $this->expectException(AppConfigTypeConflictException::class);
+ $config->getValueInt('typed', 'float');
+ }
- $this->assertFalse($config->getValues('testapp', 'enabled'));
+ public function testGetValueFloat() {
+ $config = $this->generateAppConfig();
+ $this->assertSame(3.14, $config->getValueFloat('typed', 'float', 0));
+ }
- $this->assertFalse($config->getValues(false, false));
+ public function testGetValueFloatOnNonUnknownAppReturnsDefault(): void {
+ $config = $this->generateAppConfig();
+ $this->assertSame(1.11, $config->getValueFloat('typed-1', 'float', 1.11));
}
- public function testGetValues() {
- $config = new \OC\AppConfig(\OC::$server->get(Connection::class));
+ public function testGetValueFloatOnNonExistentKeyReturnsDefault() {
+ $config = $this->generateAppConfig();
+ $this->assertSame(2.22, $config->getValueFloat('typed', 'float-2', 2.22));
+ }
- $sql = \OC::$server->getDatabaseConnection()->getQueryBuilder();
- $sql->select(['configkey', 'configvalue'])
- ->from('appconfig')
- ->where($sql->expr()->eq('appid', $sql->createParameter('appid')))
- ->setParameter('appid', 'testapp');
- $query = $sql->execute();
- $expected = [];
- while ($row = $query->fetch()) {
- $expected[$row['configkey']] = $row['configvalue'];
- }
- $query->closeCursor();
+ public function testGetValueFloatOnWrongType(): void {
+ $config = $this->generateAppConfig();
+ $this->expectException(AppConfigTypeConflictException::class);
+ $config->getValueFloat('typed', 'bool');
+ }
- $values = $config->getValues('testapp', false);
- $this->assertEquals($expected, $values);
+ public function testGetValueBool(): void {
+ $config = $this->generateAppConfig();
+ $this->assertSame(true, $config->getValueBool('typed', 'bool'));
+ }
- $sql = \OC::$server->getDatabaseConnection()->getQueryBuilder();
- $sql->select(['appid', 'configvalue'])
- ->from('appconfig')
- ->where($sql->expr()->eq('configkey', $sql->createParameter('configkey')))
- ->setParameter('configkey', 'enabled');
- $query = $sql->execute();
- $expected = [];
- while ($row = $query->fetch()) {
- $expected[$row['appid']] = $row['configvalue'];
- }
- $query->closeCursor();
+ public function testGetValueBoolOnUnknownAppReturnsDefault(): void {
+ $config = $this->generateAppConfig();
+ $this->assertSame(false, $config->getValueBool('typed-1', 'bool', false));
+ }
+
+ public function testGetValueBoolOnNonExistentKeyReturnsDefault(): void {
+ $config = $this->generateAppConfig();
+ $this->assertSame(false, $config->getValueBool('typed', 'bool-2'));
+ }
- $values = $config->getValues(false, 'enabled');
- $this->assertEquals($expected, $values);
+ public function testGetValueBoolOnWrongType(): void {
+ $config = $this->generateAppConfig();
+ $this->expectException(AppConfigTypeConflictException::class);
+ $config->getValueBool('typed', 'array');
}
- public function testGetFilteredValues() {
- /** @var \OC\AppConfig|\PHPUnit\Framework\MockObject\MockObject $config */
- $config = $this->getMockBuilder(\OC\AppConfig::class)
- ->setConstructorArgs([\OC::$server->get(Connection::class)])
- ->setMethods(['getValues'])
- ->getMock();
+ public function testGetValueArray(): void {
+ $config = $this->generateAppConfig();
+ $this->assertEqualsCanonicalizing(['test' => 1], $config->getValueArray('typed', 'array', []));
+ }
- $config->expects($this->once())
- ->method('getValues')
- ->with('user_ldap', false)
- ->willReturn([
- 'ldap_agent_password' => 'secret',
- 's42ldap_agent_password' => 'secret',
- 'ldap_dn' => 'dn',
- ]);
+ public function testGetValueArrayOnUnknownAppReturnsDefault(): void {
+ $config = $this->generateAppConfig();
+ $this->assertSame([1], $config->getValueArray('typed-1', 'array', [1]));
+ }
- $values = $config->getFilteredValues('user_ldap');
- $this->assertEquals([
- 'ldap_agent_password' => IConfig::SENSITIVE_VALUE,
- 's42ldap_agent_password' => IConfig::SENSITIVE_VALUE,
- 'ldap_dn' => 'dn',
- ], $values);
+ public function testGetValueArrayOnNonExistentKeyReturnsDefault(): void {
+ $config = $this->generateAppConfig();
+ $this->assertSame([1, 2], $config->getValueArray('typed', 'array-2', [1, 2]));
}
- public function testSettingConfigParallel() {
- $appConfig1 = new \OC\AppConfig(\OC::$server->get(Connection::class));
- $appConfig2 = new \OC\AppConfig(\OC::$server->get(Connection::class));
- $appConfig1->getValue('testapp', 'foo', 'v1');
- $appConfig2->getValue('testapp', 'foo', 'v1');
+ public function testGetValueArrayOnWrongType(): void {
+ $config = $this->generateAppConfig();
+ $this->expectException(AppConfigTypeConflictException::class);
+ $config->getValueArray('typed', 'string');
+ }
- $appConfig1->setValue('testapp', 'foo', 'v1');
- $this->assertConfigKey('testapp', 'foo', 'v1');
- $appConfig2->setValue('testapp', 'foo', 'v2');
- $this->assertConfigKey('testapp', 'foo', 'v2');
+ /**
+ * @return array
+ * @see testGetValueType
+ *
+ * @see testGetValueMixed
+ */
+ public function providerGetValueMixed(): array {
+ return [
+ // key, value, type
+ ['mixed', 'mix', IAppConfig::VALUE_MIXED],
+ ['string', 'value', IAppConfig::VALUE_STRING],
+ ['int', '42', IAppConfig::VALUE_INT],
+ ['float', '3.14', IAppConfig::VALUE_FLOAT],
+ ['bool', '1', IAppConfig::VALUE_BOOL],
+ ['array', '{"test": 1}', IAppConfig::VALUE_ARRAY],
+ ];
+ }
+
+ /**
+ * @dataProvider providerGetValueMixed
+ *
+ * @param string $key
+ * @param string $value
+ */
+ public function testGetValueMixed(string $key, string $value): void {
+ $config = $this->generateAppConfig();
+ $this->assertSame($value, $config->getValueMixed('typed', $key));
}
/**
- * @param string $app
+ * @dataProvider providerGetValueMixed
+ *
* @param string $key
- * @param string $expected
+ * @param string $value
+ * @param int $type
*/
- protected function assertConfigKey($app, $key, $expected) {
- $sql = \OC::$server->getDatabaseConnection()->getQueryBuilder();
+ public function testGetValueType(string $key, string $value, int $type): void {
+ $config = $this->generateAppConfig();
+ $this->assertSame($type, $config->getValueType('typed', $key));
+ }
+
+ public function testGetValueTypeOnUnknownApp(): void {
+ $config = $this->generateAppConfig();
+ $this->expectException(AppConfigUnknownKeyException::class);
+ $config->getValueType('typed-1', 'string');
+ }
+
+ public function testGetValueTypeOnNonExistentKey(): void {
+ $config = $this->generateAppConfig();
+ $this->expectException(AppConfigUnknownKeyException::class);
+ $config->getValueType('typed', 'string-2');
+ }
+
+ public function testSetValueString(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueString('feed', 'string', 'value-1');
+ $this->assertSame('value-1', $config->getValueString('feed', 'string', ''));
+ }
+
+ public function testSetValueStringCache(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueString('feed', 'string', 'value-1');
+ $status = $config->statusCache();
+ $this->assertSame('value-1', $status['fastCache']['feed']['string']);
+ }
+
+ public function testSetValueStringDatabase(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueString('feed', 'string', 'value-1');
+ $config->clearCache();
+ $this->assertSame('value-1', $config->getValueString('feed', 'string', ''));
+ }
+
+ public function testSetValueStringIsUpdated(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueString('feed', 'string', 'value-1');
+ $this->assertSame(true, $config->setValueString('feed', 'string', 'value-2'));
+ }
+
+ public function testSetValueStringIsNotUpdated(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueString('feed', 'string', 'value-1');
+ $this->assertSame(false, $config->setValueString('feed', 'string', 'value-1'));
+ }
+
+ public function testSetValueStringIsUpdatedCache(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueString('feed', 'string', 'value-1');
+ $config->setValueString('feed', 'string', 'value-2');
+ $status = $config->statusCache();
+ $this->assertSame('value-2', $status['fastCache']['feed']['string']);
+ }
+
+ public function testSetValueStringIsUpdatedDatabase(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueString('feed', 'string', 'value-1');
+ $config->setValueString('feed', 'string', 'value-2');
+ $config->clearCache();
+ $this->assertSame('value-2', $config->getValueString('feed', 'string', ''));
+ }
+
+ public function testSetValueInt(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueInt('feed', 'int', 42);
+ $this->assertSame(42, $config->getValueInt('feed', 'int', 0));
+ }
+
+ public function testSetValueIntCache(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueInt('feed', 'int', 42);
+ $status = $config->statusCache();
+ $this->assertSame('42', $status['fastCache']['feed']['int']);
+ }
+
+ public function testSetValueIntDatabase(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueInt('feed', 'int', 42);
+ $config->clearCache();
+ $this->assertSame(42, $config->getValueInt('feed', 'int', 0));
+ }
+
+ public function testSetValueIntIsUpdated(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueInt('feed', 'int', 42);
+ $this->assertSame(true, $config->setValueInt('feed', 'int', 17));
+ }
+
+ public function testSetValueIntIsNotUpdated(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueInt('feed', 'int', 42);
+ $this->assertSame(false, $config->setValueInt('feed', 'int', 42));
+ }
+
+ public function testSetValueIntIsUpdatedCache(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueInt('feed', 'int', 42);
+ $config->setValueInt('feed', 'int', 17);
+ $status = $config->statusCache();
+ $this->assertSame('17', $status['fastCache']['feed']['int']);
+ }
+
+ public function testSetValueIntIsUpdatedDatabase(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueInt('feed', 'int', 42);
+ $config->setValueInt('feed', 'int', 17);
+ $config->clearCache();
+ $this->assertSame(17, $config->getValueInt('feed', 'int', 0));
+ }
+
+ public function testSetValueFloat(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueFloat('feed', 'float', 3.14);
+ $this->assertSame(3.14, $config->getValueFloat('feed', 'float', 0));
+ }
+
+ public function testSetValueFloatCache(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueFloat('feed', 'float', 3.14);
+ $status = $config->statusCache();
+ $this->assertSame('3.14', $status['fastCache']['feed']['float']);
+ }
+
+ public function testSetValueFloatDatabase(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueFloat('feed', 'float', 3.14);
+ $config->clearCache();
+ $this->assertSame(3.14, $config->getValueFloat('feed', 'float', 0));
+ }
+
+ public function testSetValueFloatIsUpdated(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueFloat('feed', 'float', 3.14);
+ $this->assertSame(true, $config->setValueFloat('feed', 'float', 1.23));
+ }
+
+ public function testSetValueFloatIsNotUpdated(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueFloat('feed', 'float', 3.14);
+ $this->assertSame(false, $config->setValueFloat('feed', 'float', 3.14));
+ }
+
+ public function testSetValueFloatIsUpdatedCache(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueFloat('feed', 'float', 3.14);
+ $config->setValueFloat('feed', 'float', 1.23);
+ $status = $config->statusCache();
+ $this->assertSame('1.23', $status['fastCache']['feed']['float']);
+ }
+
+ public function testSetValueFloatIsUpdatedDatabase(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueFloat('feed', 'float', 3.14);
+ $config->setValueFloat('feed', 'float', 1.23);
+ $config->clearCache();
+ $this->assertSame(1.23, $config->getValueFloat('feed', 'float', 0));
+ }
+
+ public function testSetValueBool(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueBool('feed', 'bool', true);
+ $this->assertSame(true, $config->getValueBool('feed', 'bool', false));
+ }
+
+ public function testSetValueBoolCache(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueBool('feed', 'bool', true);
+ $status = $config->statusCache();
+ $this->assertSame('1', $status['fastCache']['feed']['bool']);
+ }
+
+ public function testSetValueBoolDatabase(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueBool('feed', 'bool', true);
+ $config->clearCache();
+ $this->assertSame(true, $config->getValueBool('feed', 'bool', false));
+ }
+
+ public function testSetValueBoolIsUpdated(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueBool('feed', 'bool', true);
+ $this->assertSame(true, $config->setValueBool('feed', 'bool', false));
+ }
+
+ public function testSetValueBoolIsNotUpdated(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueBool('feed', 'bool', true);
+ $this->assertSame(false, $config->setValueBool('feed', 'bool', true));
+ }
+
+ public function testSetValueBoolIsUpdatedCache(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueBool('feed', 'bool', true);
+ $config->setValueBool('feed', 'bool', false);
+ $status = $config->statusCache();
+ $this->assertSame('0', $status['fastCache']['feed']['bool']);
+ }
+
+ public function testSetValueBoolIsUpdatedDatabase(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueBool('feed', 'bool', true);
+ $config->setValueBool('feed', 'bool', false);
+ $config->clearCache();
+ $this->assertSame(false, $config->getValueBool('feed', 'bool', true));
+ }
+
+
+ public function testSetValueArray(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueArray('feed', 'array', ['test' => 1]);
+ $this->assertSame(['test' => 1], $config->getValueArray('feed', 'array', []));
+ }
+
+ public function testSetValueArrayCache(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueArray('feed', 'array', ['test' => 1]);
+ $status = $config->statusCache();
+ $this->assertSame('{"test":1}', $status['fastCache']['feed']['array']);
+ }
+
+ public function testSetValueArrayDatabase(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueArray('feed', 'array', ['test' => 1]);
+ $config->clearCache();
+ $this->assertSame(['test' => 1], $config->getValueArray('feed', 'array', []));
+ }
+
+ public function testSetValueArrayIsUpdated(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueArray('feed', 'array', ['test' => 1]);
+ $this->assertSame(true, $config->setValueArray('feed', 'array', ['test' => 2]));
+ }
+
+ public function testSetValueArrayIsNotUpdated(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueArray('feed', 'array', ['test' => 1]);
+ $this->assertSame(false, $config->setValueArray('feed', 'array', ['test' => 1]));
+ }
+
+ public function testSetValueArrayIsUpdatedCache(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueArray('feed', 'array', ['test' => 1]);
+ $config->setValueArray('feed', 'array', ['test' => 2]);
+ $status = $config->statusCache();
+ $this->assertSame('{"test":2}', $status['fastCache']['feed']['array']);
+ }
+
+ public function testSetValueArrayIsUpdatedDatabase(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueArray('feed', 'array', ['test' => 1]);
+ $config->setValueArray('feed', 'array', ['test' => 2]);
+ $config->clearCache();
+ $this->assertSame(['test' => 2], $config->getValueArray('feed', 'array', []));
+ }
+
+ public function testSetLazyValueString(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueString('feed', 'string', 'value-1', true);
+ $this->assertSame('value-1', $config->getValueString('feed', 'string', '', true));
+ }
+
+ public function testSetLazyValueStringCache(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueString('feed', 'string', 'value-1', true);
+ $status = $config->statusCache();
+ $this->assertSame('value-1', $status['lazyCache']['feed']['string']);
+ }
+
+ public function testSetLazyValueStringDatabase(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueString('feed', 'string', 'value-1', true);
+ $config->clearCache();
+ $this->assertSame('value-1', $config->getValueString('feed', 'string', '', true));
+ }
+
+ public function testSetLazyValueStringAsNonLazy(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueString('feed', 'string', 'value-1', true);
+ $config->setValueString('feed', 'string', 'value-1', false);
+ $this->assertSame('value-1', $config->getValueString('feed', 'string', ''));
+ }
+
+ public function testSetNonLazyValueStringAsLazy(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueString('feed', 'string', 'value-1', false);
+ $config->setValueString('feed', 'string', 'value-1', true);
+ $this->assertSame('value-1', $config->getValueString('feed', 'string', '', true));
+ }
+
+ public function testSetSensitiveValueString(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueString('feed', 'string', 'value-1', sensitive: true);
+ $this->assertSame('value-1', $config->getValueString('feed', 'string', ''));
+ }
+
+ public function testSetSensitiveValueStringCache(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueString('feed', 'string', 'value-1', sensitive: true);
+ $status = $config->statusCache();
+ $this->assertStringStartsWith(self::invokePrivate(AppConfig::class, 'ENCRYPTION_PREFIX'), $status['fastCache']['feed']['string']);
+ }
+
+ public function testSetSensitiveValueStringDatabase(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueString('feed', 'string', 'value-1', sensitive: true);
+ $config->clearCache();
+ $this->assertSame('value-1', $config->getValueString('feed', 'string', ''));
+ }
+
+ public function testSetNonSensitiveValueStringAsSensitive(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueString('feed', 'string', 'value-1', sensitive: false);
+ $config->setValueString('feed', 'string', 'value-1', sensitive: true);
+ $this->assertSame(true, $config->isSensitive('feed', 'string'));
+
+ $this->assertConfigValueNotEquals('feed', 'string', 'value-1');
+ $this->assertConfigValueNotEquals('feed', 'string', 'value-2');
+ }
+
+ public function testSetSensitiveValueStringAsNonSensitiveStaysSensitive(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueString('feed', 'string', 'value-1', sensitive: true);
+ $config->setValueString('feed', 'string', 'value-2', sensitive: false);
+ $this->assertSame(true, $config->isSensitive('feed', 'string'));
+
+ $this->assertConfigValueNotEquals('feed', 'string', 'value-1');
+ $this->assertConfigValueNotEquals('feed', 'string', 'value-2');
+ }
+
+ public function testSetSensitiveValueStringAsNonSensitiveAreStillUpdated(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueString('feed', 'string', 'value-1', sensitive: true);
+ $config->setValueString('feed', 'string', 'value-2', sensitive: false);
+ $this->assertSame('value-2', $config->getValueString('feed', 'string', ''));
+
+ $this->assertConfigValueNotEquals('feed', 'string', 'value-1');
+ $this->assertConfigValueNotEquals('feed', 'string', 'value-2');
+ }
+
+ public function testSetLazyValueInt(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueInt('feed', 'int', 42, true);
+ $this->assertSame(42, $config->getValueInt('feed', 'int', 0, true));
+ }
+
+ public function testSetLazyValueIntCache(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueInt('feed', 'int', 42, true);
+ $status = $config->statusCache();
+ $this->assertSame('42', $status['lazyCache']['feed']['int']);
+ }
+
+ public function testSetLazyValueIntDatabase(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueInt('feed', 'int', 42, true);
+ $config->clearCache();
+ $this->assertSame(42, $config->getValueInt('feed', 'int', 0, true));
+ }
+
+ public function testSetLazyValueIntAsNonLazy(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueInt('feed', 'int', 42, true);
+ $config->setValueInt('feed', 'int', 42, false);
+ $this->assertSame(42, $config->getValueInt('feed', 'int', 0));
+ }
+
+ public function testSetNonLazyValueIntAsLazy(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueInt('feed', 'int', 42, false);
+ $config->setValueInt('feed', 'int', 42, true);
+ $this->assertSame(42, $config->getValueInt('feed', 'int', 0, true));
+ }
+
+ public function testSetSensitiveValueInt(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueInt('feed', 'int', 42, sensitive: true);
+ $this->assertSame(42, $config->getValueInt('feed', 'int', 0));
+ }
+
+ public function testSetSensitiveValueIntCache(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueInt('feed', 'int', 42, sensitive: true);
+ $status = $config->statusCache();
+ $this->assertStringStartsWith(self::invokePrivate(AppConfig::class, 'ENCRYPTION_PREFIX'), $status['fastCache']['feed']['int']);
+ }
+
+ public function testSetSensitiveValueIntDatabase(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueInt('feed', 'int', 42, sensitive: true);
+ $config->clearCache();
+ $this->assertSame(42, $config->getValueInt('feed', 'int', 0));
+ }
+
+ public function testSetNonSensitiveValueIntAsSensitive(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueInt('feed', 'int', 42);
+ $config->setValueInt('feed', 'int', 42, sensitive: true);
+ $this->assertSame(true, $config->isSensitive('feed', 'int'));
+ }
+
+ public function testSetSensitiveValueIntAsNonSensitiveStaysSensitive(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueInt('feed', 'int', 42, sensitive: true);
+ $config->setValueInt('feed', 'int', 17);
+ $this->assertSame(true, $config->isSensitive('feed', 'int'));
+ }
+
+ public function testSetSensitiveValueIntAsNonSensitiveAreStillUpdated(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueInt('feed', 'int', 42, sensitive: true);
+ $config->setValueInt('feed', 'int', 17);
+ $this->assertSame(17, $config->getValueInt('feed', 'int', 0));
+ }
+
+ public function testSetLazyValueFloat(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueFloat('feed', 'float', 3.14, true);
+ $this->assertSame(3.14, $config->getValueFloat('feed', 'float', 0, true));
+ }
+
+ public function testSetLazyValueFloatCache(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueFloat('feed', 'float', 3.14, true);
+ $status = $config->statusCache();
+ $this->assertSame('3.14', $status['lazyCache']['feed']['float']);
+ }
+
+ public function testSetLazyValueFloatDatabase(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueFloat('feed', 'float', 3.14, true);
+ $config->clearCache();
+ $this->assertSame(3.14, $config->getValueFloat('feed', 'float', 0, true));
+ }
+
+ public function testSetLazyValueFloatAsNonLazy(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueFloat('feed', 'float', 3.14, true);
+ $config->setValueFloat('feed', 'float', 3.14, false);
+ $this->assertSame(3.14, $config->getValueFloat('feed', 'float', 0));
+ }
+
+ public function testSetNonLazyValueFloatAsLazy(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueFloat('feed', 'float', 3.14, false);
+ $config->setValueFloat('feed', 'float', 3.14, true);
+ $this->assertSame(3.14, $config->getValueFloat('feed', 'float', 0, true));
+ }
+
+ public function testSetSensitiveValueFloat(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueFloat('feed', 'float', 3.14, sensitive: true);
+ $this->assertSame(3.14, $config->getValueFloat('feed', 'float', 0));
+ }
+
+ public function testSetSensitiveValueFloatCache(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueFloat('feed', 'float', 3.14, sensitive: true);
+ $status = $config->statusCache();
+ $this->assertStringStartsWith(self::invokePrivate(AppConfig::class, 'ENCRYPTION_PREFIX'), $status['fastCache']['feed']['float']);
+ }
+
+ public function testSetSensitiveValueFloatDatabase(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueFloat('feed', 'float', 3.14, sensitive: true);
+ $config->clearCache();
+ $this->assertSame(3.14, $config->getValueFloat('feed', 'float', 0));
+ }
+
+ public function testSetNonSensitiveValueFloatAsSensitive(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueFloat('feed', 'float', 3.14);
+ $config->setValueFloat('feed', 'float', 3.14, sensitive: true);
+ $this->assertSame(true, $config->isSensitive('feed', 'float'));
+ }
+
+ public function testSetSensitiveValueFloatAsNonSensitiveStaysSensitive(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueFloat('feed', 'float', 3.14, sensitive: true);
+ $config->setValueFloat('feed', 'float', 1.23);
+ $this->assertSame(true, $config->isSensitive('feed', 'float'));
+ }
+
+ public function testSetSensitiveValueFloatAsNonSensitiveAreStillUpdated(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueFloat('feed', 'float', 3.14, sensitive: true);
+ $config->setValueFloat('feed', 'float', 1.23);
+ $this->assertSame(1.23, $config->getValueFloat('feed', 'float', 0));
+ }
+
+ public function testSetLazyValueBool(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueBool('feed', 'bool', true, true);
+ $this->assertSame(true, $config->getValueBool('feed', 'bool', false, true));
+ }
+
+ public function testSetLazyValueBoolCache(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueBool('feed', 'bool', true, true);
+ $status = $config->statusCache();
+ $this->assertSame('1', $status['lazyCache']['feed']['bool']);
+ }
+
+ public function testSetLazyValueBoolDatabase(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueBool('feed', 'bool', true, true);
+ $config->clearCache();
+ $this->assertSame(true, $config->getValueBool('feed', 'bool', false, true));
+ }
+
+ public function testSetLazyValueBoolAsNonLazy(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueBool('feed', 'bool', true, true);
+ $config->setValueBool('feed', 'bool', true, false);
+ $this->assertSame(true, $config->getValueBool('feed', 'bool', false));
+ }
+
+ public function testSetNonLazyValueBoolAsLazy(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueBool('feed', 'bool', true, false);
+ $config->setValueBool('feed', 'bool', true, true);
+ $this->assertSame(true, $config->getValueBool('feed', 'bool', false, true));
+ }
+
+ public function testSetLazyValueArray(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueArray('feed', 'array', ['test' => 1], true);
+ $this->assertSame(['test' => 1], $config->getValueArray('feed', 'array', [], true));
+ }
+
+ public function testSetLazyValueArrayCache(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueArray('feed', 'array', ['test' => 1], true);
+ $status = $config->statusCache();
+ $this->assertSame('{"test":1}', $status['lazyCache']['feed']['array']);
+ }
+
+ public function testSetLazyValueArrayDatabase(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueArray('feed', 'array', ['test' => 1], true);
+ $config->clearCache();
+ $this->assertSame(['test' => 1], $config->getValueArray('feed', 'array', [], true));
+ }
+
+ public function testSetLazyValueArrayAsNonLazy(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueArray('feed', 'array', ['test' => 1], true);
+ $config->setValueArray('feed', 'array', ['test' => 1], false);
+ $this->assertSame(['test' => 1], $config->getValueArray('feed', 'array', []));
+ }
+
+ public function testSetNonLazyValueArrayAsLazy(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueArray('feed', 'array', ['test' => 1], false);
+ $config->setValueArray('feed', 'array', ['test' => 1], true);
+ $this->assertSame(['test' => 1], $config->getValueArray('feed', 'array', [], true));
+ }
+
+
+ public function testSetSensitiveValueArray(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueArray('feed', 'array', ['test' => 1], sensitive: true);
+ $this->assertEqualsCanonicalizing(['test' => 1], $config->getValueArray('feed', 'array', []));
+ }
+
+ public function testSetSensitiveValueArrayCache(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueArray('feed', 'array', ['test' => 1], sensitive: true);
+ $status = $config->statusCache();
+ $this->assertStringStartsWith(self::invokePrivate(AppConfig::class, 'ENCRYPTION_PREFIX'), $status['fastCache']['feed']['array']);
+ }
+
+ public function testSetSensitiveValueArrayDatabase(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueArray('feed', 'array', ['test' => 1], sensitive: true);
+ $config->clearCache();
+ $this->assertEqualsCanonicalizing(['test' => 1], $config->getValueArray('feed', 'array', []));
+ }
+
+ public function testSetNonSensitiveValueArrayAsSensitive(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueArray('feed', 'array', ['test' => 1]);
+ $config->setValueArray('feed', 'array', ['test' => 1], sensitive: true);
+ $this->assertSame(true, $config->isSensitive('feed', 'array'));
+ }
+
+ public function testSetSensitiveValueArrayAsNonSensitiveStaysSensitive(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueArray('feed', 'array', ['test' => 1], sensitive: true);
+ $config->setValueArray('feed', 'array', ['test' => 2]);
+ $this->assertSame(true, $config->isSensitive('feed', 'array'));
+ }
+
+ public function testSetSensitiveValueArrayAsNonSensitiveAreStillUpdated(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueArray('feed', 'array', ['test' => 1], sensitive: true);
+ $config->setValueArray('feed', 'array', ['test' => 2]);
+ $this->assertEqualsCanonicalizing(['test' => 2], $config->getValueArray('feed', 'array', []));
+ }
+
+ public function testUpdateNotSensitiveToSensitive(): void {
+ $config = $this->generateAppConfig();
+ $config->updateSensitive('non-sensitive-app', 'lazy-key', true);
+ $this->assertSame(true, $config->isSensitive('non-sensitive-app', 'lazy-key', true));
+ }
+
+ public function testUpdateSensitiveToNotSensitive(): void {
+ $config = $this->generateAppConfig();
+ $config->updateSensitive('sensitive-app', 'lazy-key', false);
+ $this->assertSame(false, $config->isSensitive('sensitive-app', 'lazy-key', true));
+ }
+
+ public function testUpdateSensitiveToSensitiveReturnsFalse(): void {
+ $config = $this->generateAppConfig();
+ $this->assertSame(false, $config->updateSensitive('sensitive-app', 'lazy-key', true));
+ }
+
+ public function testUpdateNotSensitiveToNotSensitiveReturnsFalse(): void {
+ $config = $this->generateAppConfig();
+ $this->assertSame(false, $config->updateSensitive('non-sensitive-app', 'lazy-key', false));
+ }
+
+ public function testUpdateSensitiveOnUnknownKeyReturnsFalse(): void {
+ $config = $this->generateAppConfig();
+ $this->assertSame(false, $config->updateSensitive('non-sensitive-app', 'unknown-key', true));
+ }
+
+ public function testUpdateNotLazyToLazy(): void {
+ $config = $this->generateAppConfig();
+ $config->updateLazy('non-sensitive-app', 'non-lazy-key', true);
+ $this->assertSame(true, $config->isLazy('non-sensitive-app', 'non-lazy-key'));
+ }
+
+ public function testUpdateLazyToNotLazy(): void {
+ $config = $this->generateAppConfig();
+ $config->updateLazy('non-sensitive-app', 'lazy-key', false);
+ $this->assertSame(false, $config->isLazy('non-sensitive-app', 'lazy-key'));
+ }
+
+ public function testUpdateLazyToLazyReturnsFalse(): void {
+ $config = $this->generateAppConfig();
+ $this->assertSame(false, $config->updateLazy('non-sensitive-app', 'lazy-key', true));
+ }
+
+ public function testUpdateNotLazyToNotLazyReturnsFalse(): void {
+ $config = $this->generateAppConfig();
+ $this->assertSame(false, $config->updateLazy('non-sensitive-app', 'non-lazy-key', false));
+ }
+
+ public function testUpdateLazyOnUnknownKeyReturnsFalse(): void {
+ $config = $this->generateAppConfig();
+ $this->assertSame(false, $config->updateLazy('non-sensitive-app', 'unknown-key', true));
+ }
+
+ public function testGetDetails(): void {
+ $config = $this->generateAppConfig();
+ $this->assertEquals(
+ [
+ 'app' => 'non-sensitive-app',
+ 'key' => 'lazy-key',
+ 'value' => 'value',
+ 'type' => 4,
+ 'lazy' => true,
+ 'typeString' => 'string',
+ 'sensitive' => false,
+ ],
+ $config->getDetails('non-sensitive-app', 'lazy-key')
+ );
+ }
+
+ public function testGetDetailsSensitive(): void {
+ $config = $this->generateAppConfig();
+ $this->assertEquals(
+ [
+ 'app' => 'sensitive-app',
+ 'key' => 'lazy-key',
+ 'value' => $this->baseStruct['sensitive-app']['lazy-key']['encrypted'],
+ 'type' => 4,
+ 'lazy' => true,
+ 'typeString' => 'string',
+ 'sensitive' => true,
+ ],
+ $config->getDetails('sensitive-app', 'lazy-key')
+ );
+ }
+
+ public function testGetDetailsInt(): void {
+ $config = $this->generateAppConfig();
+ $this->assertEquals(
+ [
+ 'app' => 'typed',
+ 'key' => 'int',
+ 'value' => '42',
+ 'type' => 8,
+ 'lazy' => false,
+ 'typeString' => 'integer',
+ 'sensitive' => false
+ ],
+ $config->getDetails('typed', 'int')
+ );
+ }
+
+ public function testGetDetailsFloat(): void {
+ $config = $this->generateAppConfig();
+ $this->assertEquals(
+ [
+ 'app' => 'typed',
+ 'key' => 'float',
+ 'value' => '3.14',
+ 'type' => 16,
+ 'lazy' => false,
+ 'typeString' => 'float',
+ 'sensitive' => false
+ ],
+ $config->getDetails('typed', 'float')
+ );
+ }
+
+ public function testGetDetailsBool(): void {
+ $config = $this->generateAppConfig();
+ $this->assertEquals(
+ [
+ 'app' => 'typed',
+ 'key' => 'bool',
+ 'value' => '1',
+ 'type' => 32,
+ 'lazy' => false,
+ 'typeString' => 'boolean',
+ 'sensitive' => false
+ ],
+ $config->getDetails('typed', 'bool')
+ );
+ }
+
+ public function testGetDetailsArray(): void {
+ $config = $this->generateAppConfig();
+ $this->assertEquals(
+ [
+ 'app' => 'typed',
+ 'key' => 'array',
+ 'value' => '{"test": 1}',
+ 'type' => 64,
+ 'lazy' => false,
+ 'typeString' => 'array',
+ 'sensitive' => false
+ ],
+ $config->getDetails('typed', 'array')
+ );
+ }
+
+ public function testDeleteKey(): void {
+ $config = $this->generateAppConfig();
+ $config->deleteKey('anotherapp', 'key');
+ $this->assertSame('default', $config->getValueString('anotherapp', 'key', 'default'));
+ }
+
+ public function testDeleteKeyCache(): void {
+ $config = $this->generateAppConfig();
+ $config->deleteKey('anotherapp', 'key');
+ $status = $config->statusCache();
+ $this->assertEqualsCanonicalizing(['enabled' => 'false'], $status['fastCache']['anotherapp']);
+ }
+
+ public function testDeleteKeyDatabase(): void {
+ $config = $this->generateAppConfig();
+ $config->deleteKey('anotherapp', 'key');
+ $config->clearCache();
+ $this->assertSame('default', $config->getValueString('anotherapp', 'key', 'default'));
+ }
+
+ public function testDeleteApp(): void {
+ $config = $this->generateAppConfig();
+ $config->deleteApp('anotherapp');
+ $this->assertSame('default', $config->getValueString('anotherapp', 'key', 'default'));
+ $this->assertSame('default', $config->getValueString('anotherapp', 'enabled', 'default'));
+ }
+
+ public function testDeleteAppCache(): void {
+ $config = $this->generateAppConfig();
+ $status = $config->statusCache();
+ $this->assertSame(true, isset($status['fastCache']['anotherapp']));
+ $config->deleteApp('anotherapp');
+ $status = $config->statusCache();
+ $this->assertSame(false, isset($status['fastCache']['anotherapp']));
+ }
+
+ public function testDeleteAppDatabase(): void {
+ $config = $this->generateAppConfig();
+ $config->deleteApp('anotherapp');
+ $config->clearCache();
+ $this->assertSame('default', $config->getValueString('anotherapp', 'key', 'default'));
+ $this->assertSame('default', $config->getValueString('anotherapp', 'enabled', 'default'));
+ }
+
+ public function testClearCache(): void {
+ $config = $this->generateAppConfig();
+ $config->setValueString('feed', 'string', '123454');
+ $config->clearCache();
+ $status = $config->statusCache();
+ $this->assertSame([], $status['fastCache']);
+ }
+
+ public function testSensitiveValuesAreEncrypted(): void {
+ $key = self::getUniqueID('secret');
+
+ $appConfig = $this->generateAppConfig();
+ $secret = md5((string) time());
+ $appConfig->setValueString('testapp', $key, $secret, sensitive: true);
+
+ $this->assertConfigValueNotEquals('testapp', $key, $secret);
+
+ // Can get in same run
+ $actualSecret = $appConfig->getValueString('testapp', $key);
+ $this->assertEquals($secret, $actualSecret);
+
+ // Can get freshly decrypted from DB
+ $newAppConfig = $this->generateAppConfig();
+ $actualSecret = $newAppConfig->getValueString('testapp', $key);
+ $this->assertEquals($secret, $actualSecret);
+ }
+
+ public function testMigratingNonSensitiveValueToSensitiveWithSetValue(): void {
+ $key = self::getUniqueID('secret');
+ $appConfig = $this->generateAppConfig();
+ $secret = sha1((string) time());
+
+ // Unencrypted
+ $appConfig->setValueString('testapp', $key, $secret);
+ $this->assertConfigKey('testapp', $key, $secret);
+
+ // Can get freshly decrypted from DB
+ $newAppConfig = $this->generateAppConfig();
+ $actualSecret = $newAppConfig->getValueString('testapp', $key);
+ $this->assertEquals($secret, $actualSecret);
+
+ // Encrypting on change
+ $appConfig->setValueString('testapp', $key, $secret, sensitive: true);
+ $this->assertConfigValueNotEquals('testapp', $key, $secret);
+
+ // Can get in same run
+ $actualSecret = $appConfig->getValueString('testapp', $key);
+ $this->assertEquals($secret, $actualSecret);
+
+ // Can get freshly decrypted from DB
+ $newAppConfig = $this->generateAppConfig();
+ $actualSecret = $newAppConfig->getValueString('testapp', $key);
+ $this->assertEquals($secret, $actualSecret);
+ }
+
+ public function testUpdateSensitiveValueToNonSensitiveWithUpdateSensitive(): void {
+ $key = self::getUniqueID('secret');
+ $appConfig = $this->generateAppConfig();
+ $secret = sha1((string) time());
+
+ // Encrypted
+ $appConfig->setValueString('testapp', $key, $secret, sensitive: true);
+ $this->assertConfigValueNotEquals('testapp', $key, $secret);
+
+ // Migrate to non-sensitive / non-encrypted
+ $appConfig->updateSensitive('testapp', $key, false);
+ $this->assertConfigKey('testapp', $key, $secret);
+ }
+
+ public function testUpdateNonSensitiveValueToSensitiveWithUpdateSensitive(): void {
+ $key = self::getUniqueID('secret');
+ $appConfig = $this->generateAppConfig();
+ $secret = sha1((string) time());
+
+ // Unencrypted
+ $appConfig->setValueString('testapp', $key, $secret);
+ $this->assertConfigKey('testapp', $key, $secret);
+
+ // Migrate to sensitive / encrypted
+ $appConfig->updateSensitive('testapp', $key, true);
+ $this->assertConfigValueNotEquals('testapp', $key, $secret);
+ }
+
+ protected function loadConfigValueFromDatabase(string $app, string $key): string|false {
+ $sql = $this->connection->getQueryBuilder();
$sql->select('configvalue')
->from('appconfig')
->where($sql->expr()->eq('appid', $sql->createParameter('appid')))
->andWhere($sql->expr()->eq('configkey', $sql->createParameter('configkey')))
->setParameter('appid', $app)
->setParameter('configkey', $key);
- $query = $sql->execute();
- $actual = $query->fetch();
+ $query = $sql->executeQuery();
+ $actual = $query->fetchOne();
$query->closeCursor();
- $this->assertEquals($expected, $actual['configvalue']);
+ return $actual;
+ }
+
+ protected function assertConfigKey(string $app, string $key, string|false $expected): void {
+ $this->assertEquals($expected, $this->loadConfigValueFromDatabase($app, $key));
+ }
+
+ protected function assertConfigValueNotEquals(string $app, string $key, string|false $expected): void {
+ $this->assertNotEquals($expected, $this->loadConfigValueFromDatabase($app, $key));
}
}