Files
preauth/tests/Unit/MonitorCacheKeysTest.php
T
lyra cb378e20bc
Sync GitHub / sync (push) Failing after 5s
Tests / test (pull_request) Successful in 49s
chore: add php-cs-fixer with PSR-12 config and CI check
- Add friendsofphp/php-cs-fixer to require-dev
- Create .php-cs-fixer.dist.php configured for @PSR12 ruleset
- Add php-cs-fixer dry-run step to CI pipeline
- Auto-fix existing PSR-12 violations
- Document code style tooling in readme.md
2026-08-11 08:30:05 -04:00

302 lines
8.7 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Tests\Unit;
use App\MonitorCacheKeys;
use OutOfBoundsException;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Cache\Adapter\ArrayAdapter;
final class MonitorCacheKeysTest extends TestCase
{
private function wrap(?ArrayAdapter $pool = null): MonitorCacheKeys
{
$pool ??= new ArrayAdapter();
return new MonitorCacheKeys($pool);
}
public function testConstructorInitializesEmptyPool(): void
{
$monitor = $this->wrap();
self::assertSame([], $monitor->getKeys());
self::assertSame([], $monitor->getChanges());
}
public function testSaveAddsKeyAndTracksChange(): void
{
$monitor = $this->wrap();
$item = $monitor->getItem('alpha');
$item->set('value');
$monitor->save($item);
self::assertSame(['alpha'], $monitor->getKeys());
self::assertSame(['alpha' => MonitorCacheKeys::UPDATED], $monitor->getChanges());
}
public function testSaveDeferredThenCommitAddsKey(): void
{
$monitor = $this->wrap();
$item = $monitor->getItem('beta');
$item->set('value');
$monitor->saveDeferred($item);
// saveDeferred calls update() which commits immediately
self::assertSame(['beta'], $monitor->getKeys());
self::assertSame(['beta' => MonitorCacheKeys::UPDATED], $monitor->getChanges());
}
public function testGetItemReturnsUnderlyingItem(): void
{
$monitor = $this->wrap();
$item = $monitor->getItem('mykey');
$item->set('data');
$monitor->save($item);
$fetched = $monitor->getItem('mykey');
self::assertTrue($fetched->isHit());
self::assertSame('data', $fetched->get());
}
public function testGetItemsReturnsMultipleItems(): void
{
$monitor = $this->wrap();
$a = $monitor->getItem('a');
$a->set(1);
$monitor->save($a);
$b = $monitor->getItem('b');
$b->set(2);
$monitor->save($b);
$items = $monitor->getItems(['a', 'b']);
$keys = [];
foreach ($items as $key => $item) {
$keys[$key] = $item->get();
}
self::assertSame(['a' => 1, 'b' => 2], $keys);
}
public function testHasItemReturnsTrueForExistingKey(): void
{
$monitor = $this->wrap();
$item = $monitor->getItem('exists');
$item->set('v');
$monitor->save($item);
self::assertTrue($monitor->hasItem('exists'));
self::assertFalse($monitor->hasItem('missing'));
}
public function testDeleteItemRemovesKeyAndTracksRemoval(): void
{
$monitor = $this->wrap();
$item = $monitor->getItem('doomed');
$item->set('v');
$monitor->save($item);
$monitor->deleteItem('doomed');
self::assertSame([], $monitor->getKeys());
self::assertSame(['doomed' => MonitorCacheKeys::REMOVED], $monitor->getChanges());
self::assertFalse($monitor->hasItem('doomed'));
}
public function testDeleteItemOnMissingKeyIsNoop(): void
{
$monitor = $this->wrap();
$result = $monitor->deleteItem('nonexistent');
self::assertTrue($result);
self::assertSame([], $monitor->getKeys());
}
public function testDeleteItemsRemovesMultipleKeys(): void
{
$monitor = $this->wrap();
foreach (['x', 'y', 'z'] as $key) {
$item = $monitor->getItem($key);
$item->set($key);
$monitor->save($item);
}
$monitor->deleteItems(['x', 'y']);
self::assertSame(['z'], $monitor->getKeys());
$changes = $monitor->getChanges();
self::assertSame(MonitorCacheKeys::REMOVED, $changes['x']);
self::assertSame(MonitorCacheKeys::REMOVED, $changes['y']);
}
public function testDeleteItemsWithMissingKeysStillReturnsTrue(): void
{
$monitor = $this->wrap();
$result = $monitor->deleteItems(['ghost1', 'ghost2']);
self::assertTrue($result);
}
public function testClearWipesPoolWhenNotEmpty(): void
{
$monitor = $this->wrap();
$item = $monitor->getItem('keep');
$item->set('v');
$monitor->save($item);
$result = $monitor->clear();
self::assertTrue($result);
self::assertSame([], $monitor->getKeys());
}
public function testClearIsNoopWhenEmpty(): void
{
$monitor = $this->wrap();
$result = $monitor->clear();
self::assertTrue($result);
}
public function testMarkCleanResetsChangeList(): void
{
$monitor = $this->wrap();
$item = $monitor->getItem('temp');
$item->set('v');
$monitor->save($item);
self::assertNotEmpty($monitor->getChanges());
$monitor->markClean();
self::assertSame([], $monitor->getChanges());
self::assertSame(['temp'], $monitor->getKeys());
}
public function testCommitPassesThrough(): void
{
$monitor = $this->wrap();
self::assertTrue($monitor->commit());
}
public function testSaveKeyListThrowsOutOfBoundsException(): void
{
$monitor = $this->wrap();
$item = $monitor->getItem('__key_list');
$this->expectException(OutOfBoundsException::class);
$monitor->save($item);
}
public function testSaveChangeListThrowsOutOfBoundsException(): void
{
$monitor = $this->wrap();
$item = $monitor->getItem('__chg_list');
$this->expectException(OutOfBoundsException::class);
$monitor->save($item);
}
public function testDeleteKeyListThrowsOutOfBoundsException(): void
{
$monitor = $this->wrap();
$this->expectException(OutOfBoundsException::class);
$monitor->deleteItem('__key_list');
}
public function testDeleteChangeListThrowsOutOfBoundsException(): void
{
$monitor = $this->wrap();
$this->expectException(OutOfBoundsException::class);
$monitor->deleteItem('__chg_list');
}
public function testDeleteItemsWithKeyListThrowsOutOfBoundsException(): void
{
$monitor = $this->wrap();
$this->expectException(OutOfBoundsException::class);
$monitor->deleteItems(['safe', '__key_list']);
}
public function testDeleteItemsWithChangeListThrowsOutOfBoundsException(): void
{
$monitor = $this->wrap();
$this->expectException(OutOfBoundsException::class);
$monitor->deleteItems(['__chg_list']);
}
public function testSaveDeferredOnKeyListThrowsOutOfBoundsException(): void
{
$monitor = $this->wrap();
$item = $monitor->getItem('safe');
$item->set('value');
// getItem returns the real item, but saveDeferred calls update() which
// validates the key — so we need to get the __key_list item and try to save it
$keyListItem = $monitor->getItem('__key_list');
$this->expectException(OutOfBoundsException::class);
$monitor->saveDeferred($keyListItem);
}
public function testSaveDeferredOnChangeListThrowsOutOfBoundsException(): void
{
$monitor = $this->wrap();
$changeListItem = $monitor->getItem('__chg_list');
$this->expectException(OutOfBoundsException::class);
$monitor->saveDeferred($changeListItem);
}
public function testGetKeysReturnsEmptyArrayWhenKeyListMissing(): void
{
// If the underlying pool loses its key list, getKeys should return []
$pool = new ArrayAdapter();
$monitor = new MonitorCacheKeys($pool);
$item = $monitor->getItem('alpha');
$item->set('value');
$monitor->save($item);
// delete the key list directly from the underlying pool
$pool->deleteItem('__key_list');
$monitor2 = new MonitorCacheKeys($pool);
// the constructor will re-initialize since __key_list is missing
// but getKeys on the new monitor should be empty
self::assertSame([], $monitor2->getKeys());
}
public function testDeleteItemReturnsTrueForExistingKey(): void
{
$monitor = $this->wrap();
$item = $monitor->getItem('to-delete');
$item->set('value');
$monitor->save($item);
self::assertTrue($monitor->deleteItem('to-delete'));
self::assertNotContains('to-delete', $monitor->getKeys());
}
public function testDeleteItemsReturnsTrue(): void
{
$monitor = $this->wrap();
foreach (['a', 'b', 'c'] as $key) {
$item = $monitor->getItem($key);
$item->set('value');
$monitor->save($item);
}
self::assertTrue($monitor->deleteItems(['a', 'b', 'c']));
self::assertSame([], $monitor->getKeys());
}
}