Added support for HRANDFIELD command (#870)

Co-authored-by: Vladyslav Vildanov <vladyslavvildanov@Vladyslav-Vildanov-MacBook-Pro.local>
This commit is contained in:
Vladyslav Vildanov
2022-12-23 21:18:33 +02:00
committed by GitHub
parent 83fb0020a1
commit 9c543ef5b1
8 changed files with 264 additions and 0 deletions
+1
View File
@@ -74,6 +74,7 @@ use Predis\Command\CommandInterface;
* @method $this hlen($key)
* @method $this hmget($key, array $fields)
* @method $this hmset($key, array $dictionary)
* @method $this hrandfield(string $key, int $count = 1, bool $withValues = false)
* @method $this hscan($key, $cursor, array $options = null)
* @method $this hset($key, $field, $value)
* @method $this hsetnx($key, $field, $value)
+1
View File
@@ -83,6 +83,7 @@ use Predis\Response\Status;
* @method int hlen(string $key)
* @method array hmget(string $key, array $fields)
* @method mixed hmset(string $key, array $dictionary)
* @method array hrandfield(string $key, int $count = 1, bool $withValues = false)
* @method array hscan(string $key, $cursor, array $options = null)
* @method int hset(string $key, string $field, string $value)
* @method int hsetnx(string $key, string $field, string $value)
+24
View File
@@ -0,0 +1,24 @@
<?php
namespace Predis\Command\Redis;
use Predis\Command\Command as RedisCommand;
use Predis\Command\Traits\With\WithValues;
/**
* @link https://redis.io/commands/hrandfield/
*
* When called with just the key argument, return a random field from the hash value stored at key.
*
* If the provided count argument is positive, return an array of distinct fields.
* The array's length is either count or the hash's number of fields (HLEN), whichever is lower.
*/
class HRANDFIELD extends RedisCommand
{
use WithValues;
public function getId()
{
return 'HRANDFIELD';
}
}
+24
View File
@@ -0,0 +1,24 @@
<?php
namespace Predis\Command\Traits\With;
use Predis\Command\Command;
/**
* @mixin Command
*/
trait WithValues
{
public function setArguments(array $arguments)
{
$withValues = array_pop($arguments);
if (is_bool($withValues) && $withValues) {
$arguments[] = 'WITHVALUES';
} else if (!is_bool($withValues)) {
$arguments[] = $withValues;
}
parent::setArguments($arguments);
}
}
+52
View File
@@ -0,0 +1,52 @@
<?php
namespace PHPUnit;
use PHPUnit\Framework\Constraint\Constraint;
class OneOfConstraint extends Constraint
{
/**
* @var array
*/
protected $array;
public function __construct(array $array)
{
$this->array = $array;
}
/**
* @param mixed $other
* @return bool
*/
protected function matches($other): bool
{
if (is_array($other)) {
return !empty(array_intersect($other, $this->array));
}
if (in_array($other, $this->array, true)) {
return true;
}
return false;
}
/**
* @param $other
* @return string
*/
protected function failureDescription($other): string
{
return $this->toString();
}
/**
* @inheritDoc
*/
public function toString(): string
{
return 'given value matches any values from array';
}
}
+14
View File
@@ -10,6 +10,7 @@
*/
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\OneOfConstraint;
use PHPUnit\Util\Test as TestUtil;
use Predis\Client;
use Predis\Command;
@@ -94,6 +95,19 @@ abstract class PredisTestCase extends \PHPUnit\Framework\TestCase
$this->assertThat($actual, new ArrayHasSameValuesConstraint($expected), $message);
}
/**
* Asserts that actual value is one of the values from expected array.
*
* @param mixed $expected Expected array.
* @param mixed $actual Actual value. If array given searching for any matching value between two arrays.
* @param string $message Optional assertion message
* @return void
*/
public function assertOneOf(array $expected, $actual, string $message = ''): void
{
$this->assertThat($actual, new OneOfConstraint($expected), $message);
}
/**
* Asserts that a string matches a given regular expression.
*
@@ -0,0 +1,147 @@
<?php
namespace Predis\Command\Redis;
use Predis\Response\ServerException;
class HRANDFIELD_Test extends PredisCommandTestCase
{
/**
* @inheritDoc
*/
protected function getExpectedCommand(): string
{
return HRANDFIELD::class;
}
/**
* @inheritDoc
*/
protected function getExpectedId(): string
{
return 'HRANDFIELD';
}
/**
* @group disconnected
* @dataProvider argumentsProvider
* @param array $actualArguments
* @param array $expectedArguments
* @return void
*/
public function testFilterArguments(array $actualArguments, array $expectedArguments): void
{
$command = $this->getCommand();
$command->setArguments($actualArguments);
$this->assertSame($expectedArguments, $command->getArguments());
}
/**
* @group disconnected
*/
public function testParseResponse(): void
{
$this->assertSame(1, $this->getCommand()->parseResponse(1));
}
/**
* @group connected
* @dataProvider hashesProvider
* @param array $hash
* @param string $key
* @param int $count
* @param bool $withValues
* @param array $expectedResponse
* @return void
* @requiresRedisVersion >= 6.2.0
*/
public function testReturnsRandomFieldsFromHash(
array $hash,
string $key,
int $count,
bool $withValues,
array $expectedResponse
): void {
$redis = $this->getClient();
$redis->hset($key, ...$hash);
$actualResponse = $redis->hrandfield($key, $count, $withValues);
$this->assertOneOf($expectedResponse, $actualResponse);
}
/**
* @group connected
* @requiresRedisVersion >= 6.2.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('foo', 'bar');
$redis->hrandfield('foo');
}
public function argumentsProvider(): array
{
return [
'with default arguments' => [
['key'],
['key']
],
'with count argument' => [
['key', 1],
['key', 1]
],
'with WITHVALUES argument' => [
['key', 1, true],
['key', 1, 'WITHVALUES']
]
];
}
public function hashesProvider(): array
{
return [
'one field - without values' => [
['key1', 'value1', 'key2', 'value2', 'key3', 'value3'],
'key',
1,
false,
['key1', 'key2', 'key3']
],
'one field - with values' => [
['key1', 'value1', 'key2', 'value2', 'key3', 'value3'],
'key',
1,
true,
['key1', 'value1', 'key2', 'value2', 'key3', 'value3']
],
'multiple fields - without values' => [
['key1', 'value1', 'key2', 'value2', 'key3', 'value3'],
'key',
2,
false,
['key1', 'key2', 'key3'],
],
'multiple fields - with values' => [
['key1', 'value1', 'key2', 'value2', 'key3', 'value3'],
'key',
2,
true,
['key1', 'value1', 'key2', 'value2', 'key3', 'value3'],
],
'multiple fields - allows same fields' => [
['key1', 'value1', 'key2', 'value2', 'key3', 'value3'],
'key',
-2,
false,
['key1', 'key2', 'key3'],
],
];
}
}
+1
View File
@@ -18,6 +18,7 @@ if (file_exists(__DIR__.'/../autoload.php')) {
}
require __DIR__.'/PHPUnit/ArrayHasSameValuesConstraint.php';
require __DIR__.'/PHPUnit/OneOfConstraint.php';
require __DIR__.'/PHPUnit/RedisCommandConstraint.php';
require __DIR__.'/PHPUnit/PredisTestCase.php';
require __DIR__.'/PHPUnit/PredisCommandTestCase.php';