generated from Nodarx/template
feat: track cache changes with sequence numbers and tombstones
Signed-off-by: Sebastian Krupinski <krupinski01@gmail.com>
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace KTXT\ProviderImap\Tests\Unit;
|
||||
|
||||
use ArrayIterator;
|
||||
use KTXC\Db\Collection;
|
||||
use KTXC\Db\Cursor;
|
||||
use KTXC\Db\DataStore;
|
||||
use KTXM\ProviderImap\Stores\MailboxStore;
|
||||
use KTXM\ProviderImap\Stores\MessageStore;
|
||||
use MongoDB\Collection as MongoCollection;
|
||||
use MongoDB\Operation\FindOneAndUpdate;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
final class MessageStoreChangesTest extends TestCase
|
||||
{
|
||||
public function testChangesQueriesAdditionsModificationsAndDeletions(): void
|
||||
{
|
||||
$filters = [];
|
||||
$collection = $this->createStub(Collection::class);
|
||||
$collection->method('find')->willReturnCallback(function (array $filter) use (&$filters): Cursor {
|
||||
$filters[] = $filter;
|
||||
return new Cursor(new ArrayIterator([['uid' => count($filters)]]));
|
||||
});
|
||||
|
||||
$changes = (new MessageStore($this->dataStore($collection)))->changes('svc', 'INBOX', 7, 10);
|
||||
|
||||
$key = ['sid' => 'svc', 'mailbox' => 'INBOX', 'uidValidity' => 7];
|
||||
$this->assertSame([
|
||||
[...$key, 'removedSeq' => null, 'addedSeq' => ['$gt' => 10]],
|
||||
[...$key, 'removedSeq' => null, 'addedSeq' => ['$lte' => 10], 'modSeq' => ['$gt' => 10]],
|
||||
[...$key, 'addedSeq' => ['$lte' => 10], 'removedSeq' => ['$gt' => 10]],
|
||||
], $filters);
|
||||
$this->assertSame(['additions' => [1], 'modifications' => [2], 'deletions' => [3]], $changes);
|
||||
}
|
||||
|
||||
public function testTombstoneKeepsKeyAndSequencesOnly(): void
|
||||
{
|
||||
$collection = $this->createMock(Collection::class);
|
||||
$collection->expects($this->once())
|
||||
->method('updateMany')
|
||||
->with(
|
||||
['sid' => 'svc', 'mailbox' => 'INBOX', 'uidValidity' => 7, 'uid' => ['$in' => [3, 4]], 'removedSeq' => null],
|
||||
$this->callback(function (array $update): bool {
|
||||
$this->assertSame(['removedSeq' => 12, 'modSeq' => 12], $update['$set']);
|
||||
$this->assertArrayHasKey('subject', $update['$unset']);
|
||||
$this->assertArrayHasKey('flags', $update['$unset']);
|
||||
$this->assertArrayNotHasKey('addedSeq', $update['$unset']);
|
||||
return true;
|
||||
}),
|
||||
);
|
||||
|
||||
(new MessageStore($this->dataStore($collection)))->tombstone('svc', 'INBOX', 7, 12, 3, 4);
|
||||
}
|
||||
|
||||
public function testLiveReadsSkipTombstones(): void
|
||||
{
|
||||
$collection = $this->createMock(Collection::class);
|
||||
$collection->expects($this->once())
|
||||
->method('find')
|
||||
->with($this->callback(fn (array $filter): bool => array_key_exists('removedSeq', $filter) && $filter['removedSeq'] === null))
|
||||
->willReturn(new Cursor(new ArrayIterator([])));
|
||||
|
||||
(new MessageStore($this->dataStore($collection)))->flags('svc', 'INBOX', 7);
|
||||
}
|
||||
|
||||
public function testReserveSequenceReturnsTheFirstNumberOfTheRange(): void
|
||||
{
|
||||
$mongo = $this->createMock(MongoCollection::class);
|
||||
$mongo->expects($this->once())
|
||||
->method('findOneAndUpdate')
|
||||
->with(
|
||||
['sid' => 'svc', 'name' => 'INBOX'],
|
||||
['$inc' => ['changeSeq' => 3]],
|
||||
$this->callback(fn (array $options): bool => $options['returnDocument'] === FindOneAndUpdate::RETURN_DOCUMENT_AFTER),
|
||||
)
|
||||
->willReturn(['changeSeq' => 12]);
|
||||
$collection = $this->createStub(Collection::class);
|
||||
$collection->method('getMongoCollection')->willReturn($mongo);
|
||||
|
||||
$this->assertSame(10, (new MailboxStore($this->dataStore($collection)))->reserveSequence('svc', 'INBOX', 3));
|
||||
}
|
||||
|
||||
private function dataStore(Collection $collection): DataStore
|
||||
{
|
||||
$dataStore = $this->createStub(DataStore::class);
|
||||
$dataStore->method('selectCollection')->willReturn($collection);
|
||||
return $dataStore;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user