diff --git a/src/ClientContextInterface.php b/src/ClientContextInterface.php index 188814cb..bc588913 100644 --- a/src/ClientContextInterface.php +++ b/src/ClientContextInterface.php @@ -44,6 +44,7 @@ use Predis\Command\CommandInterface; * @method $this append($key, $value) * @method $this bfadd(string $key, $item) * @method $this bfexists(string $key, $item) + * @method $this bfinfo(string $key, string $modifier = '') * @method $this bitcount($key, $start = null, $end = null) * @method $this bitop($operation, $destkey, $key) * @method $this bitfield($key, $subcommand, ...$subcommandArg) diff --git a/src/ClientInterface.php b/src/ClientInterface.php index 53e5425c..9d013c6b 100644 --- a/src/ClientInterface.php +++ b/src/ClientInterface.php @@ -53,6 +53,7 @@ use Predis\Response\Status; * @method int append(string $key, $value) * @method int bfadd(string $key, $item) * @method int bfexists(string $key, $item) + * @method array bfinfo(string $key, string $modifier = '') * @method int bitcount(string $key, $start = null, $end = null) * @method int bitop($operation, $destkey, $key) * @method array|null bitfield(string $key, $subcommand, ...$subcommandArg) diff --git a/src/Command/Redis/BloomFilter/BFINFO.php b/src/Command/Redis/BloomFilter/BFINFO.php new file mode 100644 index 00000000..4f27eaab --- /dev/null +++ b/src/Command/Redis/BloomFilter/BFINFO.php @@ -0,0 +1,79 @@ + 'CAPACITY', + 'size' => 'SIZE', + 'filters' => 'FILTERS', + 'items' => 'ITEMS', + 'expansion' => 'EXPANSION', + ]; + + public function getId() + { + return 'BF.INFO'; + } + + public function setArguments(array $arguments) + { + if (isset($arguments[1])) { + $modifier = array_pop($arguments); + + if ($modifier === '') { + parent::setArguments($arguments); + + return; + } + + if (!in_array(strtoupper($modifier), $this->modifierEnum)) { + $enumValues = implode(', ', array_keys($this->modifierEnum)); + throw new UnexpectedValueException("Argument accepts only: {$enumValues} values"); + } + + $arguments[] = $this->modifierEnum[strtolower($modifier)]; + } + + parent::setArguments($arguments); + } + + public function parseResponse($data) + { + if (count($data) > 1) { + $result = []; + + for ($i = 0, $iMax = count($data); $i < $iMax; ++$i) { + if ($data[$i + 1] ?? false) { + $result[(string) $data[$i]] = $data[++$i]; + } + } + + return $result; + } + + return $data; + } +} diff --git a/tests/Predis/Command/Redis/BloomFilter/BFINFO_Test.php b/tests/Predis/Command/Redis/BloomFilter/BFINFO_Test.php new file mode 100644 index 00000000..cfe67083 --- /dev/null +++ b/tests/Predis/Command/Redis/BloomFilter/BFINFO_Test.php @@ -0,0 +1,226 @@ +getCommand(); + $command->setArguments($actualArguments); + + $this->assertSame($expectedArguments, $command->getArguments()); + } + + /** + * @group disconnected + * @dataProvider responsesProvider + */ + public function testParseResponse(array $actualResponse, array $expectedResponse): void + { + $this->assertSame($expectedResponse, $this->getCommand()->parseResponse($actualResponse)); + } + + /** + * @group connected + * @dataProvider filtersProvider + * @param array $filter + * @param string $key + * @param string $modifier + * @param array $expectedResponse + * @return void + * @requiresRedisBfVersion 1.0.0 + */ + public function testInfoReturnsCorrectInformationAboutBloomFilter( + array $filter, + string $key, + string $modifier, + array $expectedResponse + ): void { + $redis = $this->getClient(); + + $redis->bfadd(...$filter); + $this->assertSame($expectedResponse, $redis->bfinfo($key, $modifier)); + } + + /** + * @group connected + * @return void + * @requiresRedisBfVersion 1.0.0 + */ + public function testThrowsExceptionOnUnexpectedValueGiven(): void + { + $redis = $this->getClient(); + + $this->expectException(UnexpectedValueException::class); + $this->expectExceptionMessage('Argument accepts only: capacity, size, filters, items, expansion values'); + + $redis->bfinfo('key', 'wrong'); + } + + /** + * @group connected + * @requiresRedisBfVersion >= 1.0 + */ + public function testThrowsExceptionOnWrongType(): void + { + $this->expectException(ServerException::class); + $this->expectExceptionMessage('Operation against a key holding the wrong kind of value'); + + $redis = $this->getClient(); + + $redis->set('binfo_foo', 'bar'); + $redis->bfinfo('binfo_foo'); + } + + public function argumentsProvider(): array + { + return [ + 'without argument' => [ + [], + [], + ], + 'with default modifier value' => [ + ['key', ''], + ['key'], + ], + 'with CAPACITY modifier' => [ + ['key', 'capacity'], + ['key', 'CAPACITY'], + ], + 'with SIZE modifier' => [ + ['key', 'size'], + ['key', 'SIZE'], + ], + 'with FILTERS modifier' => [ + ['key', 'filters'], + ['key', 'FILTERS'], + ], + 'with ITEMS modifier' => [ + ['key', 'items'], + ['key', 'ITEMS'], + ], + 'with EXPANSION modifier' => [ + ['key', 'expansion'], + ['key', 'EXPANSION'], + ], + ]; + } + + public function responsesProvider(): array + { + return [ + 'with one modifier' => [ + [100], + [100], + ], + 'with all modifiers' => [ + [ + 'Capacity', + 100, + 'Size', + 296, + 'Number of filters', + 1, + 'Number of items inserted', + 1, + 'Expansion rate', + 2, + ], + [ + 'Capacity' => 100, + 'Size' => 296, + 'Number of filters' => 1, + 'Number of items inserted' => 1, + 'Expansion rate' => 2, + ], + ], + ]; + } + + public function filtersProvider(): array + { + return [ + 'without modifier' => [ + ['key', 'item'], + 'key', + '', + [ + 'Capacity' => 100, + 'Size' => 240, + 'Number of filters' => 1, + 'Number of items inserted' => 1, + 'Expansion rate' => 2, + ], + ], + 'with CAPACITY modifier' => [ + ['key', 'item'], + 'key', + 'capacity', + [100], + ], + 'with SIZE modifier' => [ + ['key', 'item'], + 'key', + 'size', + [240], + ], + 'with FILTERS modifier' => [ + ['key', 'item'], + 'key', + 'filters', + [1], + ], + 'with ITEMS modifier' => [ + ['key', 'item'], + 'key', + 'items', + [1], + ], + 'with EXPANSION modifier' => [ + ['key', 'item'], + 'key', + 'expansion', + [2], + ], + ]; + } +}