index/tests/DbConfigTest.php

184 lines
7.8 KiB
PHP

<?php
// DbConfigTest.php
// Created: 2023-10-20
// Updated: 2024-12-02
declare(strict_types=1);
use PHPUnit\Framework\TestCase;
use PHPUnit\Framework\Attributes\CoversClass;
use Index\Config\{GetValueInfoTrait,GetValuesTrait,MutableConfigTrait,ScopedConfigValueInfo};
use Index\Config\Db\{DbConfig,DbConfigValueInfo};
use Index\Db\{DbBackends,DbConnection};
#[CoversClass(DbConfig::class)]
#[CoversClass(DbConfigValueInfo::class)]
#[CoversClass(MutableConfigTrait::class)]
#[CoversClass(GetValueInfoTrait::class)]
#[CoversClass(GetValuesTrait::class)]
final class DbConfigTest extends TestCase {
private DbConnection $dbConn; // @phpstan-ignore-line: defined by PHPunit in setUp()
private DbConfig $config; // @phpstan-ignore-line: defined by PHPunit in setUp()
private const VALUES = [
'private.allow_password_reset' => 'b:1;',
'private.enable' => 'b:0;',
'private.msg' => 's:71:"Things are happening. Check back later for something new... eventually.";',
'private.perm.cat' => 's:4:"user";',
'private.perm.val' => 'i:1;',
'site.desc' => 's:38:"The internet\'s last convenience store.";',
'site.ext_logo' => 's:51:"https://static.flash.moe/images/flashii-logo-v3.png";',
'site.name' => 's:5:"Edgii";',
'site.social.bsky' => 's:36:"https://bsky.app/profile/flashii.net";',
'site.url' => 's:18:"https://edgii.net/";',
'test.array' => 'a:5:{i:0;i:1234;i:1;d:56.789;i:2;s:6:"Mewow!";i:3;b:1;i:4;s:4:"jeff";}',
'test.bool' => 'b:1;',
'test.float' => 'd:9876.4321;',
'test.int' => 'i:243230;',
];
private const USER_VALUES = [
'mobile.left_handed' => ['b:0;', 'b:1;'],
'profile.allow_indexing' => ['b:1;', 'b:0;'],
];
protected function setUp(): void {
$this->dbConn = DbBackends::create('sqlite::memory:');
$this->dbConn->execute('CREATE TABLE skh_config (config_name TEXT NOT NULL COLLATE NOCASE, config_value BLOB NOT NULL, PRIMARY KEY (config_name))');
$this->dbConn->execute('CREATE TABLE skh_user_settings (user_id INTEGER NOT NULL, setting_name TEXT NOT NULL COLLATE NOCASE, setting_value BLOB NOT NULL, PRIMARY KEY (user_id, setting_name))');
$stmt = $this->dbConn->prepare('INSERT INTO skh_config (config_name, config_value) VALUES (?, ?)');
foreach(self::VALUES as $name => $value) {
$stmt->addParameter(1, $name);
$stmt->addParameter(2, $value);
$stmt->execute();
}
$stmt = $this->dbConn->prepare('INSERT INTO skh_user_settings (user_id, setting_name, setting_value) VALUES (?, ?, ?)');
for($i = 1; $i <= 10; ++$i)
foreach(self::USER_VALUES as $name => $value) {
$stmt->addParameter(1, $i);
$stmt->addParameter(2, $name);
$stmt->addParameter(3, $value[$i % 2]);
$stmt->execute();
}
$this->config = new DbConfig($this->dbConn, 'skh_config');
}
public function testScoping(): void {
$this->assertEquals('user', $this->config->getString('private.perm.cat'));
$this->assertEquals('Edgii', $this->config->getString('site.name'));
$scoped = $this->config->scopeTo('private', 'perm');
$this->assertEquals('user', $scoped->getString('cat'));
}
public function testHasValues(): void {
// hasValues should always return true when the list is empty
$this->assertTrue($this->config->hasValues([]));
$this->assertFalse($this->config->hasValues('meow'));
$this->assertTrue($this->config->hasValues('site.desc'));
$this->assertTrue($this->config->hasValues(['site.ext_logo', 'site.url']));
$this->assertFalse($this->config->hasValues(['site.ext_logo', 'site.url', 'site.gun']));
}
public function testGetAllValueInfos(): void {
$all = $this->config->getAllValueInfos();
$expected = array_keys(self::VALUES);
$values = [];
foreach($all as $info)
$values[] = $info->getName();
$this->assertEquals($expected, $values);
$subset = $this->config->getAllValueInfos(2, 3);
$expected = [
'private.perm.cat',
'private.perm.val',
];
$values = [];
foreach($subset as $info)
$values[] = $info->getName();
$this->assertEquals($expected, $values);
}
public function testGetValues(): void {
$this->assertNull($this->config->getValueInfo('doesnotexist'));
$scoped = $this->config->scopeTo('private', 'perm');
$expected = ['private.perm.cat' => 'user', 'private.perm.val' => 1];
$values = [];
$valueInfos = $scoped->getValueInfos(['cat', 'val', 'poop']);
foreach($valueInfos as $valueInfo) {
$this->assertInstanceOf(ScopedConfigValueInfo::class, $valueInfo);
$values[$valueInfo->getRealName()] = $valueInfo->getValue();
}
$this->assertEquals($expected, $values);
$scoped = $this->config->scopeTo('site')->scopeTo('social');
$expected = [
'bsky' => 'https://bsky.app/profile/flashii.net',
'bsky_show' => true,
'twitter' => '',
'twitterShow' => false,
];
$values = $scoped->getValues([
'bsky',
['bsky_show:b', true],
'twitter:s',
['twitter_show:b', false, 'twitterShow'],
]);
$this->assertEquals($expected, $values);
$this->assertEquals('', $this->config->getString('none.string'));
$this->assertEquals('test', $this->config->getString('none.string', 'test'));
$this->assertEquals('https://edgii.net/', $this->config->getString('site.url'));
$this->assertEquals(0, $this->config->getInteger('site.url'));
$this->assertEquals(0, $this->config->getInteger('none.int'));
$this->assertEquals(10, $this->config->getInteger('none.int', 10));
$this->assertEquals(243230, $this->config->getInteger('test.int'));
$this->assertEquals('', $this->config->getString('test.int'));
$this->assertEquals(0, $this->config->getFloat('none.float'));
$this->assertEquals(0.1, $this->config->getFloat('none.float', 0.1));
$this->assertEquals(9876.4321, $this->config->getFloat('test.float'));
$this->assertEmpty($this->config->getArray('test.float'));
$this->assertEquals(false, $this->config->getBoolean('none.bool'));
$this->assertEquals(true, $this->config->getBoolean('none.bool', true));
$this->assertEquals(true, $this->config->getBoolean('test.bool'));
$this->assertEquals(false, $this->config->getBoolean('private.msg'));
$this->assertEquals(0, $this->config->getFloat('test.bool'));
$this->assertEmpty($this->config->getArray('none.array'));
$this->assertEquals(['de', 'het', 'een'], $this->config->getArray('none.array', ['de', 'het', 'een']));
$this->assertEquals([1234, 56.789, 'Mewow!', true, 'jeff'], $this->config->getArray('test.array'));
$this->assertEquals(false, $this->config->getBoolean('test.array'));
}
public function testNameValidation(): void {
$this->assertTrue(DbConfig::validateName('th1s.iS.vAL1d'));
$this->assertFalse(DbConfig::validateName(''));
$this->assertFalse(DbConfig::validateName('this..is.not.valid'));
$this->assertFalse(DbConfig::validateName('this..is.not.valid'));
$this->assertFalse(DbConfig::validateName('First.may.Not.be.uppercase'));
}
public function testUserSettings(): void {
for($i = 1; $i <= 10; ++$i) {
$config = new DbConfig($this->dbConn, 'skh_user_settings', 'setting_name', 'setting_value', ['user_id' => $i]);
foreach(self::USER_VALUES as $name => $value)
$this->assertEquals(unserialize($value[$i % 2]), $config->getBoolean($name));
}
}
}