mirror of
https://github.com/predis/predis.git
synced 2026-08-20 22:11:49 +00:00
Compare commits
19 Commits
v3.0.0-alpha1
...
v2.2.1
| Author | SHA1 | Date | |
|---|---|---|---|
| 5f2b410a74 | |||
| f6cf2afe47 | |||
| 311cd2b79e | |||
| ffd31cfdef | |||
| 1b2fd527ed | |||
| 4172d2265f | |||
| a3311d6869 | |||
| df14e11c3a | |||
| 7c2e8e01d8 | |||
| 0b6ab4dea4 | |||
| dd64569e06 | |||
| 90da582efc | |||
| 732abc88a2 | |||
| 33b70b971a | |||
| e46d56c45c | |||
| c57a6744bb | |||
| df83c94bb3 | |||
| a711ef96e2 | |||
| 3c322fc4e3 |
+1
-1
@@ -3,4 +3,4 @@ skip=./.git
|
||||
check-hidden=
|
||||
check-filenames=
|
||||
builtin=clear,rare,informal,usage,code,names
|
||||
ignore-words-list=master,masters,slave,slaves,whitelist,cas,exat,smove,SUGGET,sugget
|
||||
ignore-words-list=master,masters,slave,slaves,whitelist,cas,exat,smove,SUGGET,sugget,ro
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@ block_comment_end = */
|
||||
[*.php]
|
||||
max_line_length = 150
|
||||
|
||||
[*.{md,yml,yaml,neon}]
|
||||
[*.{md,yml,yaml,neon,sh}]
|
||||
indent_size = 2
|
||||
|
||||
[tests/**.php]
|
||||
|
||||
@@ -136,7 +136,7 @@ jobs:
|
||||
EXPECTED="LICENSE,README.md,autoload.php,composer.json"
|
||||
CURRENT="$(
|
||||
git archive HEAD \
|
||||
| tar --list --exclude="src" --exclude="src/*" --exclude="bin" --exclude="bin/*" \
|
||||
| tar --list --exclude="src" --exclude="src/*" --exclude="bin" --exclude="bin/*" --exclude="docker" --exclude="docker/*" \
|
||||
| paste --serial --delimiters=","
|
||||
)"
|
||||
echo "CURRENT =${CURRENT}"
|
||||
|
||||
@@ -78,3 +78,46 @@ jobs:
|
||||
run: |
|
||||
wget "https://github.com/php-coveralls/php-coveralls/releases/download/v2.5.3/php-coveralls.phar"
|
||||
php ./php-coveralls.phar -v
|
||||
|
||||
predis-cluster:
|
||||
|
||||
name: PHP ${{ matrix.php }} (Redis Cluster latest)
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
php:
|
||||
- '7.2'
|
||||
- '7.3'
|
||||
- '7.4'
|
||||
- '8.0'
|
||||
- '8.1'
|
||||
- '8.2'
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Run redis cluster
|
||||
uses: isbang/compose-action@v1.4.1
|
||||
with:
|
||||
compose-file: "./docker/unstable_cluster/docker-compose.yml"
|
||||
|
||||
- name: Setup PHP with Composer and extensions
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
extensions: relay
|
||||
coverage: ${{ (matrix.php == '8.1') && 'xdebug' || 'none' }}
|
||||
|
||||
- name: Install Composer dependencies
|
||||
uses: ramsey/composer-install@v2
|
||||
with:
|
||||
dependency-versions: highest
|
||||
composer-options: ${{ matrix.php == '8.0' && '--ignore-platform-reqs' || '' }}
|
||||
|
||||
- name: Run tests against cluster
|
||||
run: |
|
||||
sleep 5 # Timeout to make sure that docker image is setup
|
||||
vendor/bin/phpunit --group cluster
|
||||
|
||||
+22
-4
@@ -1,6 +1,20 @@
|
||||
## Changelog
|
||||
|
||||
## v2.2.0-RC1 (2023-05-09)
|
||||
## v2.2.1 (2023-08-15)
|
||||
|
||||
### Added
|
||||
- Added support for `WAITAOF` command (#1357)
|
||||
- Added support for `SHUTDOWN` command (#1359)
|
||||
- Added support for `FUNCTION` command (#1332)
|
||||
- Added support for new optional `PEXPIRE`, `PEXPIREAT` and `COMMAND`
|
||||
- Added missing Redis Stack commands to `KeyPrefixProcessor` (#1358)
|
||||
|
||||
### Changed
|
||||
- Set client name and version when establishing a connection (#1347)
|
||||
|
||||
## v2.2.0 (2023-06-14)
|
||||
|
||||
Predis v2.2.0 introduces official support for [Redis Stack](https://redis.io/docs/stack/) as well as a [Relay](https://github.com/cachewerk/relay) integration for substantially [faster read performance](https://github.com/predis/predis/wiki/Using-Relay).
|
||||
|
||||
### Added
|
||||
- Added support for [Relay](https://github.com/predis/predis/wiki/Using-Relay) (#1263)
|
||||
@@ -8,11 +22,15 @@
|
||||
- Added support for Redis `JSON`, `Bloom`, `Search` and `TimeSeries` module (#1253)
|
||||
- Added support for `ACL SETUSER, GETUSER, DRYRUN` commands (#1193)
|
||||
|
||||
### Changed
|
||||
- Minor code style and type-hint changes (#1311)
|
||||
|
||||
### Fixed
|
||||
- Fixed prefixes for `XTRIM` and `XREVRANGE` commands (#1230)
|
||||
- Fix `fclose()` being called on invalid stream resource (#1199)
|
||||
- Fix `BitByte` and `ExpireOptions` traits skip processing on null values (#1169)
|
||||
- Fix missing `@return` annotations (#1265)
|
||||
- Fixed `fclose()` being called on invalid stream resource (#1199)
|
||||
- Fixed `BitByte` and `ExpireOptions` traits skip processing on null values (#1169)
|
||||
- Fixed missing `@return` annotations (#1265)
|
||||
- Fixed `GETDEL` prefixing (#1306)
|
||||
|
||||
## v2.1.2 (2023-03-02)
|
||||
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
FROM redis/redis-stack-server:latest as rss
|
||||
|
||||
COPY create_cluster.sh /create_cluster.sh
|
||||
RUN ls -R /opt/redis-stack
|
||||
RUN chmod a+x /create_cluster.sh
|
||||
|
||||
ENTRYPOINT [ "/create_cluster.sh"]
|
||||
@@ -0,0 +1,47 @@
|
||||
#! /bin/bash
|
||||
|
||||
mkdir -p /nodes
|
||||
touch /nodes/nodemap
|
||||
if [ -z ${START_PORT} ]; then
|
||||
START_PORT=6372
|
||||
fi
|
||||
if [ -z ${END_PORT} ]; then
|
||||
END_PORT=6377
|
||||
fi
|
||||
if [ ! -z "$3" ]; then
|
||||
START_PORT=$2
|
||||
START_PORT=$3
|
||||
fi
|
||||
echo "STARTING: ${START_PORT}"
|
||||
echo "ENDING: ${END_PORT}"
|
||||
|
||||
for PORT in `seq ${START_PORT} ${END_PORT}`; do
|
||||
mkdir -p /nodes/$PORT
|
||||
if [[ -e /redis.conf ]]; then
|
||||
cp /redis.conf /nodes/$PORT/redis.conf
|
||||
else
|
||||
touch /nodes/$PORT/redis.conf
|
||||
fi
|
||||
cat << EOF >> /nodes/$PORT/redis.conf
|
||||
port ${PORT}
|
||||
cluster-enabled yes
|
||||
daemonize yes
|
||||
logfile /redis.log
|
||||
dir /nodes/$PORT
|
||||
EOF
|
||||
|
||||
set -x
|
||||
/opt/redis-stack/bin/redis-server /nodes/$PORT/redis.conf
|
||||
sleep 1
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Redis failed to start, exiting."
|
||||
continue
|
||||
fi
|
||||
echo 127.0.0.1:$PORT >> /nodes/nodemap
|
||||
done
|
||||
if [ -z "${REDIS_PASSWORD}" ]; then
|
||||
echo yes | /opt/redis-stack/bin/redis-cli --cluster create `seq -f 127.0.0.1:%g ${START_PORT} ${END_PORT}` --cluster-replicas 1
|
||||
else
|
||||
echo yes | opt/redis-stack/bin/redis-cli -a ${REDIS_PASSWORD} --cluster create `seq -f 127.0.0.1:%g ${START_PORT} ${END_PORT}` --cluster-replicas 1
|
||||
fi
|
||||
tail -f /redis.log
|
||||
@@ -0,0 +1,17 @@
|
||||
version: "3.9"
|
||||
services:
|
||||
cluster:
|
||||
container_name: redis-cluster
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
ports:
|
||||
- "6372:6372"
|
||||
- "6373:6373"
|
||||
- "6374:6374"
|
||||
- "6375:6375"
|
||||
- "6376:6376"
|
||||
- "6377:6378"
|
||||
volumes:
|
||||
- "./redis.conf:/redis.conf:ro"
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
# Redis Cluster config file will be shared across all nodes.
|
||||
# Do not change the following configurations that are already set:
|
||||
# port, cluster-enabled, daemonize, logfile, dir
|
||||
protected-mode no
|
||||
loadmodule /opt/redis-stack/lib/redisearch.so
|
||||
loadmodule /opt/redis-stack/lib/redisgraph.so
|
||||
loadmodule /opt/redis-stack/lib/redistimeseries.so
|
||||
loadmodule /opt/redis-stack/lib/rejson.so
|
||||
loadmodule /opt/redis-stack/lib/redisbloom.so
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use Predis\Client;
|
||||
|
||||
require __DIR__ . '/../shared.php';
|
||||
|
||||
// Example of WAITAOF command usage:
|
||||
|
||||
// 1. Enable appendonly mode if it's not (command works only in appendonly mode)
|
||||
$client = new Client($single_server);
|
||||
$info = $client->info();
|
||||
$enabled = false;
|
||||
|
||||
if ($info['Persistence']['aof_enabled'] === '0') {
|
||||
$client->config('set', 'appendonly', 'yes');
|
||||
$enabled = true;
|
||||
}
|
||||
|
||||
// 2. Set key value pair
|
||||
$response = $client->set('foo', 'bar');
|
||||
echo "Key-value pair set status: {$response}\n";
|
||||
|
||||
// 3. Run WAITAOF command to make sure that all previous writes was fsynced
|
||||
$response = $client->waitaof(1, 0, 0);
|
||||
|
||||
echo "Quantity of local instances that was fsynced - {$response[0]}, quantity of replicas - {$response[1]}";
|
||||
|
||||
// 4. Disable appendonly mode if it was enabled during script execution
|
||||
if ($enabled) {
|
||||
$client->config('set', 'appendonly', 'no');
|
||||
}
|
||||
@@ -24,6 +24,7 @@
|
||||
<group>realm-stack</group>
|
||||
<group>ext-curl</group>
|
||||
<group>ext-phpiredis</group>
|
||||
<group>cluster</group>
|
||||
</exclude>
|
||||
</groups>
|
||||
|
||||
@@ -38,5 +39,9 @@
|
||||
<const name="REDIS_SERVER_PORT" value="6379" />
|
||||
<const name="REDIS_SERVER_DBNUM" value="0" />
|
||||
<env name="USE_RELAY" value="true" />
|
||||
|
||||
<!-- Redis Cluster -->
|
||||
<!-- Only master nodes endpoints included -->
|
||||
<const name="REDIS_CLUSTER_ENDPOINTS" value="127.0.0.1:6372,127.0.0.1:6373,127.0.0.1:6374" />
|
||||
</php>
|
||||
</phpunit>
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
<group>ext-relay</group>
|
||||
<group>ext-curl</group>
|
||||
<group>ext-phpiredis</group>
|
||||
<group>cluster</group>
|
||||
<!-- <group>connected</group> -->
|
||||
<!-- <group>disconnected</group> -->
|
||||
<!-- <group>commands</group> -->
|
||||
@@ -51,5 +52,9 @@
|
||||
<const name="REDIS_SERVER_PORT" value="6379" />
|
||||
<const name="REDIS_SERVER_DBNUM" value="0" />
|
||||
<env name="USE_RELAY" value="false" />
|
||||
|
||||
<!-- Redis Cluster -->
|
||||
<!-- Only master nodes endpoints included -->
|
||||
<const name="REDIS_CLUSTER_ENDPOINTS" value="127.0.0.1:6372,127.0.0.1:6373,127.0.0.1:6374" />
|
||||
</php>
|
||||
</phpunit>
|
||||
|
||||
+8
-8
@@ -53,7 +53,7 @@ use Traversable;
|
||||
*/
|
||||
class Client implements ClientInterface, IteratorAggregate
|
||||
{
|
||||
public const VERSION = '2.2.0-RC1';
|
||||
public const VERSION = '2.2.1';
|
||||
|
||||
/** @var OptionsInterface */
|
||||
private $options;
|
||||
@@ -346,29 +346,29 @@ class Client implements ClientInterface, IteratorAggregate
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param string $name
|
||||
* @return ContainerInterface
|
||||
*/
|
||||
public function __get($name)
|
||||
public function __get(string $name)
|
||||
{
|
||||
return ContainerFactory::create($this, $name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param $value
|
||||
* @param string $name
|
||||
* @param mixed $value
|
||||
* @return mixed
|
||||
*/
|
||||
public function __set($name, $value)
|
||||
public function __set(string $name, $value)
|
||||
{
|
||||
throw new RuntimeException('Not allowed');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param string $name
|
||||
* @return mixed
|
||||
*/
|
||||
public function __isset($name)
|
||||
public function __isset(string $name)
|
||||
{
|
||||
throw new RuntimeException('Not allowed');
|
||||
}
|
||||
|
||||
@@ -178,7 +178,9 @@ use Predis\Command\Redis\Container\Search\FTCURSOR;
|
||||
* @method $this jsonforget(string $key, string $path = '$')
|
||||
* @method $this jsonget(string $key, string $indent = '', string $newline = '', string $space = '', string ...$paths)
|
||||
* @method $this jsonnumincrby(string $key, string $path, int $value)
|
||||
* @method $this jsonmerge(string $key, string $path, string $value)
|
||||
* @method $this jsonmget(array $keys, string $path)
|
||||
* @method $this jsonmset(string ...$keyPathValue)
|
||||
* @method $this jsonobjkeys(string $key, string $path = '$')
|
||||
* @method $this jsonobjlen(string $key, string $path = '$')
|
||||
* @method $this jsonresp(string $key, string $path = '$')
|
||||
@@ -302,12 +304,14 @@ use Predis\Command\Redis\Container\Search\FTCURSOR;
|
||||
* @method $this exec()
|
||||
* @method $this multi()
|
||||
* @method $this unwatch()
|
||||
* @method $this waitaof(int $numLocal, int $numReplicas, int $timeout)
|
||||
* @method $this watch($key)
|
||||
* @method $this eval($script, $numkeys, $keyOrArg1 = null, $keyOrArgN = null)
|
||||
* @method $this eval_ro(string $script, array $keys, ...$argument)
|
||||
* @method $this evalsha($script, $numkeys, $keyOrArg1 = null, $keyOrArgN = null)
|
||||
* @method $this evalsha_ro(string $sha1, array $keys, ...$argument)
|
||||
* @method $this script($subcommand, $argument = null)
|
||||
* @method $this shutdown(bool $noSave = null, bool $now = false, bool $force = false, bool $abort = false)
|
||||
* @method $this auth($password)
|
||||
* @method $this echo($message)
|
||||
* @method $this ping($message = null)
|
||||
|
||||
@@ -187,7 +187,9 @@ use Predis\Response\Status;
|
||||
* @method int jsonforget(string $key, string $path = '$')
|
||||
* @method string jsonget(string $key, string $indent = '', string $newline = '', string $space = '', string ...$paths)
|
||||
* @method string jsonnumincrby(string $key, string $path, int $value)
|
||||
* @method Status jsonmerge(string $key, string $path, string $value)
|
||||
* @method array jsonmget(array $keys, string $path)
|
||||
* @method Status jsonmset(string ...$keyPathValue)
|
||||
* @method array jsonobjkeys(string $key, string $path = '$')
|
||||
* @method array jsonobjlen(string $key, string $path = '$')
|
||||
* @method array jsonresp(string $key, string $path = '$')
|
||||
@@ -320,12 +322,14 @@ use Predis\Response\Status;
|
||||
* @method array|null exec()
|
||||
* @method mixed multi()
|
||||
* @method mixed unwatch()
|
||||
* @method array waitaof(int $numLocal, int $numReplicas, int $timeout)
|
||||
* @method mixed watch(string $key)
|
||||
* @method mixed eval(string $script, int $numkeys, string ...$keyOrArg = null)
|
||||
* @method mixed eval_ro(string $script, array $keys, ...$argument)
|
||||
* @method mixed evalsha(string $script, int $numkeys, string ...$keyOrArg = null)
|
||||
* @method mixed evalsha_ro(string $sha1, array $keys, ...$argument)
|
||||
* @method mixed script($subcommand, $argument = null)
|
||||
* @method Status shutdown(bool $noSave = null, bool $now = false, bool $force = false, bool $abort = false)
|
||||
* @method mixed auth(string $password)
|
||||
* @method string echo(string $message)
|
||||
* @method mixed ping(string $message = null)
|
||||
|
||||
@@ -53,6 +53,7 @@ abstract class ClusterStrategy implements StrategyInterface
|
||||
'SORT' => [$this, 'getKeyFromSortCommand'],
|
||||
'DUMP' => $getKeyFromFirstArgument,
|
||||
'RESTORE' => $getKeyFromFirstArgument,
|
||||
'FLUSHDB' => [$this, 'getFakeKey'],
|
||||
|
||||
/* commands operating on string values */
|
||||
'APPEND' => $getKeyFromFirstArgument,
|
||||
@@ -163,6 +164,9 @@ abstract class ClusterStrategy implements StrategyInterface
|
||||
'EVAL' => [$this, 'getKeyFromScriptingCommands'],
|
||||
'EVALSHA' => [$this, 'getKeyFromScriptingCommands'],
|
||||
|
||||
/* server */
|
||||
'INFO' => [$this, 'getFakeKey'],
|
||||
|
||||
/* commands performing geospatial operations */
|
||||
'GEOADD' => $getKeyFromFirstArgument,
|
||||
'GEOHASH' => $getKeyFromFirstArgument,
|
||||
@@ -216,6 +220,16 @@ abstract class ClusterStrategy implements StrategyInterface
|
||||
$this->commands[$commandID] = $callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get fake key for commands with no key argument.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getFakeKey(): string
|
||||
{
|
||||
return 'key';
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the key from the first argument of a command instance.
|
||||
*
|
||||
|
||||
@@ -186,6 +186,111 @@ class KeyPrefixProcessor implements ProcessorInterface
|
||||
'XLEN' => $prefixFirst,
|
||||
'XACK' => $prefixFirst,
|
||||
'XTRIM' => $prefixFirst,
|
||||
|
||||
/* ---------------- Redis 6.2 ---------------- */
|
||||
'GETDEL' => $prefixFirst,
|
||||
|
||||
/* RedisJSON */
|
||||
'JSON.ARRAPPEND' => $prefixFirst,
|
||||
'JSON.ARRINDEX' => $prefixFirst,
|
||||
'JSON.ARRINSERT' => $prefixFirst,
|
||||
'JSON.ARRLEN' => $prefixFirst,
|
||||
'JSON.ARRPOP' => $prefixFirst,
|
||||
'JSON.ARRTRIM' => $prefixFirst,
|
||||
'JSON.CLEAR' => $prefixFirst,
|
||||
'JSON.DEBUG MEMORY' => $prefixFirst,
|
||||
'JSON.DEL' => $prefixFirst,
|
||||
'JSON.FORGET' => $prefixFirst,
|
||||
'JSON.GET' => $prefixFirst,
|
||||
'JSON.MGET' => $prefixAll,
|
||||
'JSON.NUMINCRBY' => $prefixFirst,
|
||||
'JSON.OBJKEYS' => $prefixFirst,
|
||||
'JSON.OBJLEN' => $prefixFirst,
|
||||
'JSON.RESP' => $prefixFirst,
|
||||
'JSON.SET' => $prefixFirst,
|
||||
'JSON.STRAPPEND' => $prefixFirst,
|
||||
'JSON.STRLEN' => $prefixFirst,
|
||||
'JSON.TOGGLE' => $prefixFirst,
|
||||
'JSON.TYPE' => $prefixFirst,
|
||||
|
||||
/* RedisBloom */
|
||||
'BF.ADD' => $prefixFirst,
|
||||
'BF.EXISTS' => $prefixFirst,
|
||||
'BF.INFO' => $prefixFirst,
|
||||
'BF.INSERT' => $prefixFirst,
|
||||
'BF.LOADCHUNK' => $prefixFirst,
|
||||
'BF.MADD' => $prefixFirst,
|
||||
'BF.MEXISTS' => $prefixFirst,
|
||||
'BF.RESERVE' => $prefixFirst,
|
||||
'BF.SCANDUMP' => $prefixFirst,
|
||||
'CF.ADD' => $prefixFirst,
|
||||
'CF.ADDNX' => $prefixFirst,
|
||||
'CF.COUNT' => $prefixFirst,
|
||||
'CF.DEL' => $prefixFirst,
|
||||
'CF.EXISTS' => $prefixFirst,
|
||||
'CF.INFO' => $prefixFirst,
|
||||
'CF.INSERT' => $prefixFirst,
|
||||
'CF.INSERTNX' => $prefixFirst,
|
||||
'CF.LOADCHUNK' => $prefixFirst,
|
||||
'CF.MEXISTS' => $prefixFirst,
|
||||
'CF.RESERVE' => $prefixFirst,
|
||||
'CF.SCANDUMP' => $prefixFirst,
|
||||
'CMS.INCRBY' => $prefixFirst,
|
||||
'CMS.INFO' => $prefixFirst,
|
||||
'CMS.INITBYDIM' => $prefixFirst,
|
||||
'CMS.INITBYPROB' => $prefixFirst,
|
||||
'CMS.QUERY' => $prefixFirst,
|
||||
'TDIGEST.ADD' => $prefixFirst,
|
||||
'TDIGEST.BYRANK' => $prefixFirst,
|
||||
'TDIGEST.BYREVRANK' => $prefixFirst,
|
||||
'TDIGEST.CDF' => $prefixFirst,
|
||||
'TDIGEST.CREATE' => $prefixFirst,
|
||||
'TDIGEST.INFO' => $prefixFirst,
|
||||
'TDIGEST.MAX' => $prefixFirst,
|
||||
'TDIGEST.MIN' => $prefixFirst,
|
||||
'TDIGEST.QUANTILE' => $prefixFirst,
|
||||
'TDIGEST.RANK' => $prefixFirst,
|
||||
'TDIGEST.RESET' => $prefixFirst,
|
||||
'TDIGEST.REVRANK' => $prefixFirst,
|
||||
'TDIGEST.TRIMMED_MEAN' => $prefixFirst,
|
||||
'TOPK.ADD' => $prefixFirst,
|
||||
'TOPK.INCRBY' => $prefixFirst,
|
||||
'TOPK.INFO' => $prefixFirst,
|
||||
'TOPK.LIST' => $prefixFirst,
|
||||
'TOPK.QUERY' => $prefixFirst,
|
||||
'TOPK.RESERVE' => $prefixFirst,
|
||||
|
||||
/* RediSearch */
|
||||
'FT.AGGREGATE' => $prefixFirst,
|
||||
'FT.ALTER' => $prefixFirst,
|
||||
'FT.CREATE' => $prefixFirst,
|
||||
'FT.CURSOR DEL' => $prefixFirst,
|
||||
'FT.CURSOR READ' => $prefixFirst,
|
||||
'FT.DROPINDEX' => $prefixFirst,
|
||||
'FT.EXPLAIN' => $prefixFirst,
|
||||
'FT.INFO' => $prefixFirst,
|
||||
'FT.PROFILE' => $prefixFirst,
|
||||
'FT.SEARCH' => $prefixFirst,
|
||||
'FT.SPELLCHECK' => $prefixFirst,
|
||||
'FT.SYNDUMP' => $prefixFirst,
|
||||
'FT.SYNUPDATE' => $prefixFirst,
|
||||
'FT.TAGVALS' => $prefixFirst,
|
||||
|
||||
/* Redis TimeSeries */
|
||||
'TS.ADD' => $prefixFirst,
|
||||
'TS.ALTER' => $prefixFirst,
|
||||
'TS.CREATE' => $prefixFirst,
|
||||
'TS.DECRBY' => $prefixFirst,
|
||||
'TS.DEL' => $prefixFirst,
|
||||
'TS.GET' => $prefixFirst,
|
||||
'TS.INCRBY' => $prefixFirst,
|
||||
'TS.INFO' => $prefixFirst,
|
||||
'TS.MGET' => $prefixFirst,
|
||||
'TS.MRANGE' => $prefixFirst,
|
||||
'TS.MREVRANGE' => $prefixFirst,
|
||||
'TS.QUERYINDEX' => $prefixFirst,
|
||||
'TS.RANGE' => $prefixFirst,
|
||||
'TS.REVRANGE' => $prefixFirst,
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ abstract class AbstractContainer implements ContainerInterface
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function __call($subcommandID, $arguments)
|
||||
public function __call(string $subcommandID, array $arguments)
|
||||
{
|
||||
array_unshift($arguments, strtoupper($subcommandID));
|
||||
|
||||
|
||||
@@ -18,11 +18,11 @@ interface ContainerInterface
|
||||
* Creates Redis container command with subcommand as virtual method name
|
||||
* and sends a request to the server.
|
||||
*
|
||||
* @param $subcommandID
|
||||
* @param $arguments
|
||||
* @param string $subcommandID
|
||||
* @param array $arguments
|
||||
* @return mixed
|
||||
*/
|
||||
public function __call($subcommandID, $arguments);
|
||||
public function __call(string $subcommandID, array $arguments);
|
||||
|
||||
/**
|
||||
* Returns containerCommandId of specific container command.
|
||||
|
||||
@@ -15,8 +15,14 @@ namespace Predis\Command\Redis\Container;
|
||||
use Predis\Response\Status;
|
||||
|
||||
/**
|
||||
* @method string load(string $functionCode, bool $replace = 'false')
|
||||
* @method Status delete(string $libraryName)
|
||||
* @method string dump()
|
||||
* @method Status flush(?string $mode = null)
|
||||
* @method Status kill()
|
||||
* @method array list(string $libraryNamePattern = null, bool $withCode = false)
|
||||
* @method string load(string $functionCode, bool $replace = 'false')
|
||||
* @method Status restore(string $value, string $policy = null)
|
||||
* @method array stats()
|
||||
*/
|
||||
class FunctionContainer extends AbstractContainer
|
||||
{
|
||||
|
||||
@@ -41,7 +41,7 @@ class FUNCTIONS extends RedisCommand
|
||||
|
||||
public function setArguments(array $arguments)
|
||||
{
|
||||
$strategy = $this->strategyResolver->resolve('functions', $arguments[0]);
|
||||
$strategy = $this->strategyResolver->resolve('functions', strtolower($arguments[0]));
|
||||
$arguments = $strategy->processArguments($arguments);
|
||||
|
||||
parent::setArguments($arguments);
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command\Redis\Json;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
|
||||
/**
|
||||
* @see https://redis.io/commands/json.merge/
|
||||
*
|
||||
* Merge a given JSON value into matching paths.
|
||||
* Consequently, JSON values at matching paths are updated, deleted, or expanded with new children.
|
||||
*/
|
||||
class JSONMERGE extends RedisCommand
|
||||
{
|
||||
public function getId()
|
||||
{
|
||||
return 'JSON.MERGE';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command\Redis\Json;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
|
||||
/**
|
||||
* @see https://redis.io/commands/json.mset/
|
||||
*
|
||||
* Set or update one or more JSON values according to the specified key-path-value triplets.
|
||||
*/
|
||||
class JSONMSET extends RedisCommand
|
||||
{
|
||||
public function getId()
|
||||
{
|
||||
return 'JSON.MSET';
|
||||
}
|
||||
}
|
||||
@@ -26,4 +26,36 @@ class SHUTDOWN extends RedisCommand
|
||||
{
|
||||
return 'SHUTDOWN';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setArguments(array $arguments)
|
||||
{
|
||||
if (empty($arguments)) {
|
||||
parent::setArguments($arguments);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$processedArguments = [];
|
||||
|
||||
if (array_key_exists(0, $arguments) && null !== $arguments[0]) {
|
||||
$processedArguments[] = ($arguments[0]) ? 'SAVE' : 'NOSAVE';
|
||||
}
|
||||
|
||||
if (array_key_exists(1, $arguments) && false !== $arguments[1]) {
|
||||
$processedArguments[] = 'NOW';
|
||||
}
|
||||
|
||||
if (array_key_exists(2, $arguments) && false !== $arguments[2]) {
|
||||
$processedArguments[] = 'FORCE';
|
||||
}
|
||||
|
||||
if (array_key_exists(3, $arguments) && false !== $arguments[3]) {
|
||||
$processedArguments[] = 'ABORT';
|
||||
}
|
||||
|
||||
parent::setArguments($processedArguments);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,9 +60,9 @@ class SORT extends RedisCommand
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($sortParams['LIMIT']) &&
|
||||
is_array($sortParams['LIMIT']) &&
|
||||
count($sortParams['LIMIT']) == 2) {
|
||||
if (isset($sortParams['LIMIT'])
|
||||
&& is_array($sortParams['LIMIT'])
|
||||
&& count($sortParams['LIMIT']) == 2) {
|
||||
$query[] = 'LIMIT';
|
||||
$query[] = $sortParams['LIMIT'][0];
|
||||
$query[] = $sortParams['LIMIT'][1];
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
|
||||
/**
|
||||
* @see https://redis.io/commands/waitaof/
|
||||
*
|
||||
* This command blocks the current client until all the previous write commands are acknowledged
|
||||
* as having been fsynced to the AOF of the local Redis and/or at least the specified number of replicas.
|
||||
*/
|
||||
class WAITAOF extends RedisCommand
|
||||
{
|
||||
public function getId()
|
||||
{
|
||||
return 'WAITAOF';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command\Strategy\ContainerCommands\Functions;
|
||||
|
||||
use Predis\Command\Strategy\SubcommandStrategyInterface;
|
||||
|
||||
class DumpStrategy implements SubcommandStrategyInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function processArguments(array $arguments): array
|
||||
{
|
||||
return $arguments;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command\Strategy\ContainerCommands\Functions;
|
||||
|
||||
use Predis\Command\Strategy\SubcommandStrategyInterface;
|
||||
|
||||
class FlushStrategy implements SubcommandStrategyInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function processArguments(array $arguments): array
|
||||
{
|
||||
$processedArguments = [$arguments[0]];
|
||||
|
||||
if (array_key_exists(1, $arguments) && null !== $arguments[1]) {
|
||||
$processedArguments[] = strtoupper($arguments[1]);
|
||||
}
|
||||
|
||||
return $processedArguments;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command\Strategy\ContainerCommands\Functions;
|
||||
|
||||
use Predis\Command\Strategy\SubcommandStrategyInterface;
|
||||
|
||||
class KillStrategy implements SubcommandStrategyInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function processArguments(array $arguments): array
|
||||
{
|
||||
return $arguments;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command\Strategy\ContainerCommands\Functions;
|
||||
|
||||
use Predis\Command\Strategy\SubcommandStrategyInterface;
|
||||
|
||||
class ListStrategy implements SubcommandStrategyInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function processArguments(array $arguments): array
|
||||
{
|
||||
$processedArguments = [$arguments[0]];
|
||||
|
||||
if (array_key_exists(1, $arguments) && null !== $arguments[1]) {
|
||||
array_push($processedArguments, 'LIBRARYNAME', $arguments[1]);
|
||||
}
|
||||
|
||||
if (array_key_exists(2, $arguments) && true === $arguments[2]) {
|
||||
$processedArguments[] = 'WITHCODE';
|
||||
}
|
||||
|
||||
return $processedArguments;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command\Strategy\ContainerCommands\Functions;
|
||||
|
||||
use Predis\Command\Strategy\SubcommandStrategyInterface;
|
||||
|
||||
class RestoreStrategy implements SubcommandStrategyInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function processArguments(array $arguments): array
|
||||
{
|
||||
$processedArguments = [$arguments[0], $arguments[1]];
|
||||
|
||||
if (array_key_exists(2, $arguments) && null !== $arguments[2]) {
|
||||
$processedArguments[] = strtoupper($arguments[2]);
|
||||
}
|
||||
|
||||
return $processedArguments;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command\Strategy\ContainerCommands\Functions;
|
||||
|
||||
use Predis\Command\Strategy\SubcommandStrategyInterface;
|
||||
|
||||
class StatsStrategy implements SubcommandStrategyInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function processArguments(array $arguments): array
|
||||
{
|
||||
return $arguments;
|
||||
}
|
||||
}
|
||||
@@ -18,13 +18,28 @@ class SubcommandStrategyResolver implements StrategyResolverInterface
|
||||
{
|
||||
private const CONTAINER_COMMANDS_NAMESPACE = 'Predis\Command\Strategy\ContainerCommands';
|
||||
|
||||
/**
|
||||
* @var ?string
|
||||
*/
|
||||
private $separator;
|
||||
|
||||
public function __construct(string $separator = null)
|
||||
{
|
||||
$this->separator = $separator;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function resolve(string $commandId, string $subcommandId): SubcommandStrategyInterface
|
||||
{
|
||||
$subcommandStrategyClass = ucfirst(strtolower($subcommandId)) . 'Strategy';
|
||||
$commandDirectoryName = ucfirst(strtolower($commandId));
|
||||
$subcommandStrategyClass = ucwords($subcommandId) . 'Strategy';
|
||||
$commandDirectoryName = ucwords($commandId);
|
||||
|
||||
if (!is_null($this->separator)) {
|
||||
$subcommandStrategyClass = str_replace($this->separator, '', $subcommandStrategyClass);
|
||||
$commandDirectoryName = str_replace($this->separator, '', $commandDirectoryName);
|
||||
}
|
||||
|
||||
if (class_exists(
|
||||
$containerCommandClass = self::CONTAINER_COMMANDS_NAMESPACE . '\\' . $commandDirectoryName . '\\' . $subcommandStrategyClass
|
||||
|
||||
@@ -25,8 +25,8 @@ trait Keys
|
||||
$argumentsLength = count($arguments);
|
||||
|
||||
if (
|
||||
static::$keysArgumentPositionOffset > $argumentsLength ||
|
||||
!is_array($arguments[static::$keysArgumentPositionOffset])
|
||||
static::$keysArgumentPositionOffset > $argumentsLength
|
||||
|| !is_array($arguments[static::$keysArgumentPositionOffset])
|
||||
) {
|
||||
throw new UnexpectedValueException('Wrong keys argument type or position offset');
|
||||
}
|
||||
|
||||
@@ -67,8 +67,8 @@ class Options implements OptionsInterface
|
||||
public function defined($option)
|
||||
{
|
||||
return
|
||||
array_key_exists($option, $this->options) ||
|
||||
array_key_exists($option, $this->input)
|
||||
array_key_exists($option, $this->options)
|
||||
|| array_key_exists($option, $this->input)
|
||||
;
|
||||
}
|
||||
|
||||
@@ -78,8 +78,8 @@ class Options implements OptionsInterface
|
||||
public function __isset($option)
|
||||
{
|
||||
return (
|
||||
array_key_exists($option, $this->options) ||
|
||||
array_key_exists($option, $this->input)
|
||||
array_key_exists($option, $this->options)
|
||||
|| array_key_exists($option, $this->input)
|
||||
) && $this->__get($option) !== null;
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace Predis\Connection;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use Predis\Command\CommandInterface;
|
||||
use Predis\Command\RawCommand;
|
||||
use Predis\CommunicationException;
|
||||
use Predis\Protocol\ProtocolException;
|
||||
|
||||
@@ -27,6 +28,10 @@ abstract class AbstractConnection implements NodeConnectionInterface
|
||||
private $cachedId;
|
||||
|
||||
protected $parameters;
|
||||
|
||||
/**
|
||||
* @var RawCommand[]
|
||||
*/
|
||||
protected $initCommands = [];
|
||||
|
||||
/**
|
||||
@@ -101,6 +106,14 @@ abstract class AbstractConnection implements NodeConnectionInterface
|
||||
$this->initCommands[] = $command;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getInitCommands(): array
|
||||
{
|
||||
return $this->initCommands;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
namespace Predis\Connection;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use Predis\Client;
|
||||
use Predis\Command\RawCommand;
|
||||
use ReflectionClass;
|
||||
use UnexpectedValueException;
|
||||
@@ -174,6 +175,16 @@ class Factory implements FactoryInterface
|
||||
);
|
||||
}
|
||||
|
||||
if (!$connection instanceof RelayConnection) {
|
||||
$connection->addConnectCommand(
|
||||
new RawCommand('CLIENT', ['SETINFO', 'LIB-NAME', 'predis'])
|
||||
);
|
||||
|
||||
$connection->addConnectCommand(
|
||||
new RawCommand('CLIENT', ['SETINFO', 'LIB-VER', Client::VERSION])
|
||||
);
|
||||
}
|
||||
|
||||
if (isset($parameters->database) && strlen($parameters->database)) {
|
||||
$connection->addConnectCommand(
|
||||
new RawCommand('SELECT', [$parameters->database])
|
||||
|
||||
@@ -32,7 +32,7 @@ trait RelayMethods
|
||||
* @param string $pattern
|
||||
* @return bool
|
||||
*/
|
||||
public function onInvalidated(?callable $callback, ?string $pattern = null)
|
||||
public function onInvalidated(?callable $callback, string $pattern = null)
|
||||
{
|
||||
return $this->client->onInvalidated($callback, $pattern);
|
||||
}
|
||||
@@ -129,7 +129,7 @@ trait RelayMethods
|
||||
* @param ?int $db
|
||||
* @return bool
|
||||
*/
|
||||
public function flushMemory(?string $endpointId = null, int $db = null)
|
||||
public function flushMemory(string $endpointId = null, int $db = null)
|
||||
{
|
||||
return $this->client->flushMemory($endpointId, $db);
|
||||
}
|
||||
|
||||
@@ -211,6 +211,7 @@ class SentinelReplication implements ReplicationInterface
|
||||
$this->master = $connection;
|
||||
} elseif ('sentinel' === $role) {
|
||||
$this->sentinels[] = $connection;
|
||||
|
||||
// sentinels are not considered part of the pool.
|
||||
return;
|
||||
} else {
|
||||
|
||||
@@ -231,7 +231,9 @@ class StreamConnection extends AbstractConnection
|
||||
foreach ($this->initCommands as $command) {
|
||||
$response = $this->executeCommand($command);
|
||||
|
||||
if ($response instanceof ErrorResponseInterface) {
|
||||
if ($response instanceof ErrorResponseInterface && $command->getId() === 'CLIENT') {
|
||||
// Do nothing on CLIENT SETINFO command failure
|
||||
} elseif ($response instanceof ErrorResponseInterface) {
|
||||
$this->onConnectionError("`{$command->getId()}` failed: {$response->getMessage()}", 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ abstract class AbstractConsumer implements Iterator
|
||||
public const STATUS_SUBSCRIBED = 2; // 0b0010
|
||||
public const STATUS_PSUBSCRIBED = 4; // 0b0100
|
||||
|
||||
protected $position = null;
|
||||
protected $position;
|
||||
protected $statusFlags = self::STATUS_VALID;
|
||||
|
||||
/**
|
||||
|
||||
@@ -44,7 +44,7 @@ class OneOfConstraint extends Constraint
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $other
|
||||
* @param mixed $other
|
||||
* @return string
|
||||
*/
|
||||
protected function failureDescription($other): string
|
||||
|
||||
@@ -61,7 +61,11 @@ abstract class PredisCommandTestCase extends PredisTestCase
|
||||
);
|
||||
}
|
||||
|
||||
$client = $this->createClient(null, null, $flushdb);
|
||||
if ($this->isClusterTest()) {
|
||||
$client = $this->createClient(null, ['cluster' => 'redis'], $flushdb);
|
||||
} else {
|
||||
$client = $this->createClient(null, null, $flushdb);
|
||||
}
|
||||
|
||||
return $client;
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ use Predis\Connection;
|
||||
*/
|
||||
abstract class PredisTestCase extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
protected $redisServerVersion = null;
|
||||
protected $redisServerVersion;
|
||||
protected $redisJsonVersion;
|
||||
|
||||
/**
|
||||
@@ -73,7 +73,7 @@ abstract class PredisTestCase extends \PHPUnit\Framework\TestCase
|
||||
*
|
||||
* @return RedisCommandConstraint
|
||||
*/
|
||||
public function isRedisCommand($command = null, ?array $arguments = null): RedisCommandConstraint
|
||||
public function isRedisCommand($command = null, array $arguments = null): RedisCommandConstraint
|
||||
{
|
||||
return new RedisCommandConstraint($command, $arguments);
|
||||
}
|
||||
@@ -153,6 +153,10 @@ abstract class PredisTestCase extends \PHPUnit\Framework\TestCase
|
||||
*/
|
||||
protected function getDefaultParametersArray(): array
|
||||
{
|
||||
if ($this->isClusterTest()) {
|
||||
return $this->prepareClusterEndpoints();
|
||||
}
|
||||
|
||||
return [
|
||||
'scheme' => 'tcp',
|
||||
'host' => constant('REDIS_SERVER_HOST'),
|
||||
@@ -224,7 +228,7 @@ abstract class PredisTestCase extends \PHPUnit\Framework\TestCase
|
||||
*
|
||||
* @return Client
|
||||
*/
|
||||
protected function createClient(?array $parameters = null, ?array $options = null, ?bool $flushdb = true): Client
|
||||
protected function createClient(array $parameters = null, array $options = null, ?bool $flushdb = true): Client
|
||||
{
|
||||
$parameters = array_merge(
|
||||
$this->getDefaultParametersArray(),
|
||||
@@ -237,6 +241,15 @@ abstract class PredisTestCase extends \PHPUnit\Framework\TestCase
|
||||
getenv('USE_RELAY') ? ['connections' => 'relay'] : []
|
||||
);
|
||||
|
||||
if ($this->isClusterTest()) {
|
||||
$options = array_merge(
|
||||
[
|
||||
'cluster' => 'redis',
|
||||
],
|
||||
$options
|
||||
);
|
||||
}
|
||||
|
||||
$client = new Client($parameters, $options);
|
||||
$client->connect();
|
||||
|
||||
@@ -300,7 +313,6 @@ abstract class PredisTestCase extends \PHPUnit\Framework\TestCase
|
||||
* the default connection parameters used by Predis or a set of connection
|
||||
* parameters specified in the optional second argument.
|
||||
*
|
||||
|
||||
* @param array|string|null $parameters Optional connection parameters
|
||||
*
|
||||
* @return MockObject|Connection\NodeConnectionInterface
|
||||
@@ -362,9 +374,9 @@ abstract class PredisTestCase extends \PHPUnit\Framework\TestCase
|
||||
$this->getName(false)
|
||||
);
|
||||
|
||||
if (isset($annotations['method']['requiresRedisVersion'], $annotations['method']['group']) &&
|
||||
!empty($annotations['method']['requiresRedisVersion']) &&
|
||||
in_array('connected', $annotations['method']['group'])
|
||||
if (isset($annotations['method']['requiresRedisVersion'], $annotations['method']['group'])
|
||||
&& !empty($annotations['method']['requiresRedisVersion'])
|
||||
&& in_array('connected', $annotations['method']['group'])
|
||||
) {
|
||||
return $annotations['method']['requiresRedisVersion'][0];
|
||||
}
|
||||
@@ -517,9 +529,9 @@ abstract class PredisTestCase extends \PHPUnit\Framework\TestCase
|
||||
$this->getName(false)
|
||||
);
|
||||
|
||||
if (isset($annotations['method'][$moduleAnnotation], $annotations['method']['group']) &&
|
||||
!empty($annotations['method'][$moduleAnnotation]) &&
|
||||
in_array('connected', $annotations['method']['group'], true)
|
||||
if (isset($annotations['method'][$moduleAnnotation], $annotations['method']['group'])
|
||||
&& !empty($annotations['method'][$moduleAnnotation])
|
||||
&& in_array('connected', $annotations['method']['group'], true)
|
||||
) {
|
||||
return $annotations['method'][$moduleAnnotation][0];
|
||||
}
|
||||
@@ -538,4 +550,36 @@ abstract class PredisTestCase extends \PHPUnit\Framework\TestCase
|
||||
$this->markTestSkipped($message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check annotations if it's matches to cluster test scenario.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function isClusterTest(): bool
|
||||
{
|
||||
$annotations = TestUtil::parseTestMethodAnnotations(
|
||||
get_class($this),
|
||||
$this->getName(false)
|
||||
);
|
||||
|
||||
return isset($annotations['method']['requiresRedisVersion'], $annotations['method']['group'])
|
||||
&& !empty($annotations['method']['requiresRedisVersion'])
|
||||
&& in_array('connected', $annotations['method']['group'], true)
|
||||
&& in_array('cluster', $annotations['method']['group'], true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse comma-separated cluster endpoints and convert them into tcp strings.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function prepareClusterEndpoints(): array
|
||||
{
|
||||
$endpoints = explode(',', constant('REDIS_CLUSTER_ENDPOINTS'));
|
||||
|
||||
return array_map(static function (string $elem) {
|
||||
return 'tcp://' . $elem;
|
||||
}, $endpoints);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ class RedisCommandConstraint extends \PHPUnit\Framework\Constraint\Constraint
|
||||
* @param string|CommandInterface $command Expected command instance or command ID
|
||||
* @param ?array $arguments Expected command arguments
|
||||
*/
|
||||
public function __construct($command, ?array $arguments = null)
|
||||
public function __construct($command, array $arguments = null)
|
||||
{
|
||||
if ($command instanceof CommandInterface) {
|
||||
$this->commandID = strtoupper($command->getId());
|
||||
|
||||
@@ -1253,6 +1253,20 @@ class ClientTest extends PredisTestCase
|
||||
$this->assertSame('127.0.0.1:6381', $iterator->key());
|
||||
}
|
||||
|
||||
/**
|
||||
* @group connected
|
||||
* @requiresRedisVersion >= 7.2.0
|
||||
*/
|
||||
public function testSetClientInfoOnConnection(): void
|
||||
{
|
||||
$client = new Client($this->getParameters());
|
||||
$libName = $client->client('LIST')[0]['lib-name'];
|
||||
$libVer = $client->client('LIST')[0]['lib-ver'];
|
||||
|
||||
$this->assertSame('predis', $libName);
|
||||
$this->assertSame(Client::VERSION, $libVer);
|
||||
}
|
||||
|
||||
// ******************************************************************** //
|
||||
// ---- HELPER METHODS ------------------------------------------------ //
|
||||
// ******************************************************************** //
|
||||
|
||||
@@ -106,6 +106,21 @@ class PredisStrategyTest extends PredisTestCase
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
public function testFakeKeyCommandsWithOneKey(): void
|
||||
{
|
||||
$strategy = $this->getClusterStrategy();
|
||||
$commands = $this->getCommandFactory();
|
||||
$arguments = [];
|
||||
|
||||
foreach ($this->getExpectedCommands('keys-fake') as $commandID) {
|
||||
$command = $commands->create($commandID, $arguments);
|
||||
$this->assertNotNull($strategy->getSlot($command), $commandID);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
@@ -310,7 +325,7 @@ class PredisStrategyTest extends PredisTestCase
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getExpectedCommands(?string $type = null): array
|
||||
protected function getExpectedCommands(string $type = null): array
|
||||
{
|
||||
$commands = [
|
||||
/* commands operating on the key space */
|
||||
@@ -327,6 +342,7 @@ class PredisStrategyTest extends PredisTestCase
|
||||
'SORT' => 'variable',
|
||||
'DUMP' => 'keys-first',
|
||||
'RESTORE' => 'keys-first',
|
||||
'FLUSHDB' => 'keys-fake',
|
||||
|
||||
/* commands operating on string values */
|
||||
'APPEND' => 'keys-first',
|
||||
@@ -437,6 +453,9 @@ class PredisStrategyTest extends PredisTestCase
|
||||
'EVAL' => 'keys-script',
|
||||
'EVALSHA' => 'keys-script',
|
||||
|
||||
/* server */
|
||||
'INFO' => 'keys-fake',
|
||||
|
||||
/* commands performing geospatial operations */
|
||||
'GEOADD' => 'keys-first',
|
||||
'GEOHASH' => 'keys-first',
|
||||
|
||||
@@ -134,6 +134,21 @@ class RedisStrategyTest extends PredisTestCase
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
public function testFakeKeyCommandsWithOneKey(): void
|
||||
{
|
||||
$strategy = $this->getClusterStrategy();
|
||||
$commands = $this->getCommandFactory();
|
||||
$arguments = [];
|
||||
|
||||
foreach ($this->getExpectedCommands('keys-fake') as $commandID) {
|
||||
$command = $commands->create($commandID, $arguments);
|
||||
$this->assertNotNull($strategy->getSlot($command), $commandID);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
@@ -333,7 +348,7 @@ class RedisStrategyTest extends PredisTestCase
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getExpectedCommands(?string $type = null): array
|
||||
protected function getExpectedCommands(string $type = null): array
|
||||
{
|
||||
$commands = [
|
||||
/* commands operating on the key space */
|
||||
@@ -350,6 +365,7 @@ class RedisStrategyTest extends PredisTestCase
|
||||
'SORT' => 'keys-first', // TODO
|
||||
'DUMP' => 'keys-first',
|
||||
'RESTORE' => 'keys-first',
|
||||
'FLUSHDB' => 'keys-fake',
|
||||
|
||||
/* commands operating on string values */
|
||||
'APPEND' => 'keys-first',
|
||||
@@ -460,6 +476,9 @@ class RedisStrategyTest extends PredisTestCase
|
||||
'EVAL' => 'keys-script',
|
||||
'EVALSHA' => 'keys-script',
|
||||
|
||||
/* server */
|
||||
'INFO' => 'keys-fake',
|
||||
|
||||
/* commands performing geospatial operations */
|
||||
'GEOADD' => 'keys-first',
|
||||
'GEOHASH' => 'keys-first',
|
||||
|
||||
@@ -973,6 +973,11 @@ class KeyPrefixProcessorTest extends PredisTestCase
|
||||
['key', 'MAXLEN', 100],
|
||||
['prefix:key', 'MAXLEN', 100],
|
||||
],
|
||||
/* ---------------- Redis 6.2 ---------------- */
|
||||
['GETDEL',
|
||||
['key'],
|
||||
['prefix:key'],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -172,6 +172,18 @@ BUFFER;
|
||||
$this->assertEquals($expectedConnectionName, $redis->client('GETNAME'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @group connected
|
||||
* @requiresRedisVersion >= 7.0.0
|
||||
*/
|
||||
public function testSetNoEvictModeForCurrentConnection(): void
|
||||
{
|
||||
$redis = $this->getClient();
|
||||
|
||||
$this->assertEquals('OK', $redis->client('NO-EVICT', 'ON'));
|
||||
$this->assertEquals('OK', $redis->client('NO-EVICT', 'OFF'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
|
||||
@@ -61,10 +61,10 @@ class EVALSHA_RO_Test extends PredisCommandTestCase
|
||||
/**
|
||||
* @group connected
|
||||
* @dataProvider scriptsProvider
|
||||
* @param string $script
|
||||
* @param array $keys
|
||||
* @param array $arguments
|
||||
* @param $expectedResponse
|
||||
* @param string $script
|
||||
* @param array $keys
|
||||
* @param array $arguments
|
||||
* @param $expectedResponse
|
||||
* @return void
|
||||
* @requiresRedisVersion >= 7.0.0
|
||||
*/
|
||||
|
||||
@@ -61,11 +61,11 @@ class EVAL_RO_Test extends PredisCommandTestCase
|
||||
/**
|
||||
* @group connected
|
||||
* @dataProvider scriptsProvider
|
||||
* @param array $dictionary
|
||||
* @param string $script
|
||||
* @param array $keys
|
||||
* @param array $arguments
|
||||
* @param $expectedResponse
|
||||
* @param array $dictionary
|
||||
* @param string $script
|
||||
* @param array $keys
|
||||
* @param array $arguments
|
||||
* @param $expectedResponse
|
||||
* @return void
|
||||
* @requiresRedisVersion >= 7.0.0
|
||||
*/
|
||||
|
||||
@@ -147,14 +147,14 @@ class EXPIREAT_Test extends PredisCommandTestCase
|
||||
['noExpiry', time() + 10, 'XX'],
|
||||
],
|
||||
'only if new expiry is greater then current one' => [
|
||||
['newExpiryLower', 'value', 'EXAT', time() + 1000],
|
||||
['newExpiryGreater', 'value', 'EXAT', time() + 10],
|
||||
['newExpiryLower', 'value', 'EX', 1000],
|
||||
['newExpiryGreater', 'value', 'EX', 10],
|
||||
['newExpiryGreater', time() + 20, 'GT'],
|
||||
['newExpiryLower', time() + 20, 'GT'],
|
||||
],
|
||||
'only if new expiry is lower then current one' => [
|
||||
['newExpiryLower', 'value', 'EXAT', time() + 1000],
|
||||
['newExpiryGreater', 'value', 'EXAT', time() + 10],
|
||||
['newExpiryLower', 'value', 'EX', 1000],
|
||||
['newExpiryGreater', 'value', 'EX', 10],
|
||||
['newExpiryLower', time() + 20, 'LT'],
|
||||
['newExpiryGreater', time() + 20, 'LT'],
|
||||
],
|
||||
|
||||
@@ -113,8 +113,8 @@ class FCALL_RO_Test extends PredisCommandTestCase
|
||||
);
|
||||
|
||||
if (
|
||||
isset($annotations['method']['group']) &&
|
||||
in_array('connected', $annotations['method']['group'], true)
|
||||
isset($annotations['method']['group'])
|
||||
&& in_array('connected', $annotations['method']['group'], true)
|
||||
) {
|
||||
$redis = $this->getClient();
|
||||
$redis->function->delete(self::LIB_NAME);
|
||||
|
||||
@@ -60,9 +60,9 @@ class FCALL_Test extends PredisCommandTestCase
|
||||
/**
|
||||
* @group connected
|
||||
* @dataProvider functionsProvider
|
||||
* @param string $function
|
||||
* @param array $functionArguments
|
||||
* @param $expectedResponse
|
||||
* @param string $function
|
||||
* @param array $functionArguments
|
||||
* @param $expectedResponse
|
||||
* @return void
|
||||
* @requiresRedisVersion >= 7.0.0
|
||||
*/
|
||||
|
||||
@@ -70,6 +70,84 @@ class FUNCTIONS_Test extends PredisCommandTestCase
|
||||
$this->assertSameValues($expected, $command->getArguments());
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
public function testDumpFilterArguments(): void
|
||||
{
|
||||
$arguments = ['DUMP'];
|
||||
$expected = ['DUMP'];
|
||||
|
||||
$command = $this->getCommand();
|
||||
$command->setArguments($arguments);
|
||||
|
||||
$this->assertSameValues($expected, $command->getArguments());
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
public function testKillFilterArguments(): void
|
||||
{
|
||||
$arguments = ['KILL'];
|
||||
$expected = ['KILL'];
|
||||
|
||||
$command = $this->getCommand();
|
||||
$command->setArguments($arguments);
|
||||
|
||||
$this->assertSameValues($expected, $command->getArguments());
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
public function testStatsFilterArguments(): void
|
||||
{
|
||||
$arguments = ['STATS'];
|
||||
$expected = ['STATS'];
|
||||
|
||||
$command = $this->getCommand();
|
||||
$command->setArguments($arguments);
|
||||
|
||||
$this->assertSameValues($expected, $command->getArguments());
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider flushArgumentsProvider
|
||||
* @group disconnected
|
||||
*/
|
||||
public function testFlushFilterArguments(array $actualArguments, array $expectedResponse): void
|
||||
{
|
||||
$command = $this->getCommand();
|
||||
$command->setArguments($actualArguments);
|
||||
|
||||
$this->assertSameValues($expectedResponse, $command->getArguments());
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider restoreArgumentsProvider
|
||||
* @group disconnected
|
||||
*/
|
||||
public function testRestoreFilterArguments(array $actualArguments, array $expectedResponse): void
|
||||
{
|
||||
$command = $this->getCommand();
|
||||
$command->setArguments($actualArguments);
|
||||
|
||||
$this->assertSameValues($expectedResponse, $command->getArguments());
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider listArgumentsProvider
|
||||
* @group disconnected
|
||||
*/
|
||||
public function testListFilterArguments(array $actualArguments, array $expectedResponse): void
|
||||
{
|
||||
$command = $this->getCommand();
|
||||
$command->setArguments($actualArguments);
|
||||
|
||||
$this->assertSameValues($expectedResponse, $command->getArguments());
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
@@ -86,7 +164,7 @@ class FUNCTIONS_Test extends PredisCommandTestCase
|
||||
public function testLoadFunctionAddFunctionIntoGivenLibrary(): void
|
||||
{
|
||||
$redis = $this->getClient();
|
||||
$redis->executeRaw(['FUNCTION', 'FLUSH']);
|
||||
$redis->function->flush();
|
||||
|
||||
$actualResponse = $redis->function->load(
|
||||
"#!lua name={$this->libName} \n redis.register_function('myfunc', function(keys, args) return args[1] end)"
|
||||
@@ -105,7 +183,7 @@ class FUNCTIONS_Test extends PredisCommandTestCase
|
||||
public function testLoadFunctionOverridesExistingFunctionWithReplaceArgumentGiven(): void
|
||||
{
|
||||
$redis = $this->getClient();
|
||||
$redis->executeRaw(['FUNCTION', 'FLUSH']);
|
||||
$redis->function->flush();
|
||||
|
||||
$actualResponse = $redis->function->load(
|
||||
"#!lua name={$this->libName} \n redis.register_function('myfunc', function(keys, args) return args[1] end)"
|
||||
@@ -132,7 +210,7 @@ class FUNCTIONS_Test extends PredisCommandTestCase
|
||||
public function testLoadFunctionThrowsErrorOnAlreadyExistingLibraryGiven(): void
|
||||
{
|
||||
$redis = $this->getClient();
|
||||
$redis->executeRaw(['FUNCTION', 'FLUSH']);
|
||||
$redis->function->flush();
|
||||
|
||||
$actualResponse = $redis->function->load(
|
||||
"#!lua name={$this->libName} \n redis.register_function('myfunc', function(keys, args) return args[1] end)"
|
||||
@@ -160,7 +238,7 @@ class FUNCTIONS_Test extends PredisCommandTestCase
|
||||
public function testDeleteFunctionRemovesAlreadyExistingLibrary(): void
|
||||
{
|
||||
$redis = $this->getClient();
|
||||
$redis->executeRaw(['FUNCTION', 'FLUSH']);
|
||||
$redis->function->flush();
|
||||
|
||||
$actualResponse = $redis->function->load(
|
||||
"#!lua name={$this->libName} \n redis.register_function('myfunc', function(keys, args) return args[1] end)"
|
||||
@@ -170,6 +248,112 @@ class FUNCTIONS_Test extends PredisCommandTestCase
|
||||
$this->assertEquals('OK', $redis->function->delete($this->libName));
|
||||
}
|
||||
|
||||
/**
|
||||
* @group connected
|
||||
* @return void
|
||||
* @requiresRedisVersion >= 7.0.0
|
||||
*/
|
||||
public function testDumpReturnsSerializedPayloadOfLibrary(): void
|
||||
{
|
||||
$redis = $this->getClient();
|
||||
$redis->function->flush();
|
||||
|
||||
$libName = $redis->function->load(
|
||||
"#!lua name={$this->libName} \n redis.register_function('myfunc', function(keys, args) return args[1] end)"
|
||||
);
|
||||
|
||||
$this->assertSame($this->libName, $libName);
|
||||
$this->assertStringContainsString($libName, $redis->function->dump());
|
||||
}
|
||||
|
||||
/**
|
||||
* @group connected
|
||||
* @return void
|
||||
* @requiresRedisVersion >= 7.0.0
|
||||
*/
|
||||
public function testFlushRemovesAllLibraries(): void
|
||||
{
|
||||
$redis = $this->getClient();
|
||||
$redis->function->flush();
|
||||
|
||||
$libName = $redis->function->load(
|
||||
"#!lua name={$this->libName} \n redis.register_function('myfunc', function(keys, args) return args[1] end)"
|
||||
);
|
||||
|
||||
$this->assertEquals($this->libName, $libName);
|
||||
$this->assertEquals('OK', $redis->function->flush());
|
||||
}
|
||||
|
||||
/**
|
||||
* @group connected
|
||||
* @return void
|
||||
* @requiresRedisVersion >= 7.0.0
|
||||
*/
|
||||
public function testRestoresLibraryFromSerializedPayload(): void
|
||||
{
|
||||
$redis = $this->getClient();
|
||||
$redis->function->flush();
|
||||
|
||||
$libName = $redis->function->load(
|
||||
"#!lua name={$this->libName} \n redis.register_function('myfunc', function(keys, args) return args[1] end)"
|
||||
);
|
||||
$this->assertEquals($this->libName, $libName);
|
||||
|
||||
$serializedPayload = $redis->function->dump();
|
||||
$this->assertStringContainsString($libName, $serializedPayload);
|
||||
|
||||
$redis->function->flush();
|
||||
|
||||
$this->assertEquals('OK', $redis->function->restore($serializedPayload));
|
||||
}
|
||||
|
||||
/**
|
||||
* @group connected
|
||||
* @group relay-incompatible
|
||||
* @return void
|
||||
* @requiresRedisVersion >= 7.0.0
|
||||
*/
|
||||
public function testListReturnsListOfAvailableFunctions(): void
|
||||
{
|
||||
$redis = $this->getClient();
|
||||
$redis->function->flush();
|
||||
$expectedResponse = [
|
||||
[
|
||||
'library_name', 'mylib', 'engine', 'LUA', 'functions',
|
||||
[
|
||||
['name', 'myfunc', 'description', null, 'flags', []],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
$libName = $redis->function->load(
|
||||
"#!lua name={$this->libName} \n redis.register_function('myfunc', function(keys, args) return args[1] end)"
|
||||
);
|
||||
|
||||
$this->assertEquals($this->libName, $libName);
|
||||
$this->assertSame($expectedResponse, $redis->function->list());
|
||||
}
|
||||
|
||||
/**
|
||||
* @group connected
|
||||
* @group relay-incompatible
|
||||
* @return void
|
||||
* @requiresRedisVersion >= 7.0.0
|
||||
*/
|
||||
public function testStatsReturnsInformationAboutRunningScript(): void
|
||||
{
|
||||
$redis = $this->getClient();
|
||||
$redis->function->flush();
|
||||
$expectedResponse = ['running_script', null, 'engines', ['LUA', ['libraries_count', 1, 'functions_count', 1]]];
|
||||
|
||||
$libName = $redis->function->load(
|
||||
"#!lua name={$this->libName} \n redis.register_function('myfunc', function(keys, args) return args[1] end)"
|
||||
);
|
||||
|
||||
$this->assertEquals($this->libName, $libName);
|
||||
$this->assertSame($expectedResponse, $redis->function->stats());
|
||||
}
|
||||
|
||||
/**
|
||||
* @group connected
|
||||
* @return void
|
||||
@@ -178,11 +362,77 @@ class FUNCTIONS_Test extends PredisCommandTestCase
|
||||
public function testDeleteFunctionThrowsErrorOnNonExistingLibrary(): void
|
||||
{
|
||||
$redis = $this->getClient();
|
||||
$redis->executeRaw(['FUNCTION', 'FLUSH']);
|
||||
$redis->function->flush();
|
||||
|
||||
$this->expectException(ServerException::class);
|
||||
$this->expectExceptionMessage('ERR Library not found');
|
||||
|
||||
$redis->function->delete($this->libName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group connected
|
||||
* @return void
|
||||
* @requiresRedisVersion >= 7.0.0
|
||||
*/
|
||||
public function testKillThrowsExceptionOnNonExistingRunningScript(): void
|
||||
{
|
||||
$redis = $this->getClient();
|
||||
$redis->function->flush();
|
||||
|
||||
$this->expectException(ServerException::class);
|
||||
$this->expectExceptionMessage('NOTBUSY No scripts in execution right now.');
|
||||
|
||||
$redis->function->kill();
|
||||
}
|
||||
|
||||
public function flushArgumentsProvider(): array
|
||||
{
|
||||
return [
|
||||
'with default arguments' => [
|
||||
['FLUSH', null],
|
||||
['FLUSH'],
|
||||
],
|
||||
'with mode argument' => [
|
||||
['FLUSH', 'sync'],
|
||||
['FLUSH', 'SYNC'],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
public function restoreArgumentsProvider(): array
|
||||
{
|
||||
return [
|
||||
'with default arguments' => [
|
||||
['RESTORE', 'value', null],
|
||||
['RESTORE', 'value'],
|
||||
],
|
||||
'with mode argument' => [
|
||||
['RESTORE', 'value', 'append'],
|
||||
['RESTORE', 'value', 'APPEND'],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
public function listArgumentsProvider(): array
|
||||
{
|
||||
return [
|
||||
'with default arguments' => [
|
||||
['LIST', null, false],
|
||||
['LIST'],
|
||||
],
|
||||
'with LIBRARYNAME modifier' => [
|
||||
['LIST', 'libraryname', false],
|
||||
['LIST', 'LIBRARYNAME', 'libraryname'],
|
||||
],
|
||||
'with WITHCODE modifier' => [
|
||||
['LIST', null, true],
|
||||
['LIST', 'WITHCODE'],
|
||||
],
|
||||
'with all arguments' => [
|
||||
['LIST', 'libraryname', true],
|
||||
['LIST', 'LIBRARYNAME', 'libraryname', 'WITHCODE'],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command\Redis\Json;
|
||||
|
||||
use Predis\Command\Redis\PredisCommandTestCase;
|
||||
|
||||
class JSONMERGE_Test extends PredisCommandTestCase
|
||||
{
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function getExpectedCommand(): string
|
||||
{
|
||||
return JSONMERGE::class;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function getExpectedId(): string
|
||||
{
|
||||
return 'JSONMERGE';
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
public function testFilterArguments(): void
|
||||
{
|
||||
$arguments = ['key', '$..', '{"a":2}'];
|
||||
$expected = ['key', '$..', '{"a":2}'];
|
||||
|
||||
$command = $this->getCommand();
|
||||
$command->setArguments($arguments);
|
||||
|
||||
$this->assertSame($expected, $command->getArguments());
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
public function testParseResponse(): void
|
||||
{
|
||||
$this->assertSame(1, $this->getCommand()->parseResponse(1));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider jsonProvider
|
||||
* @group connected
|
||||
* @param array $setArguments
|
||||
* @param array $mergeArguments
|
||||
* @param string $expectedResponse
|
||||
* @return void
|
||||
* @requiresRedisJsonVersion >= 2.6.0
|
||||
*/
|
||||
public function testMergeCorrectlyMergeJsonValues(
|
||||
array $setArguments,
|
||||
array $mergeArguments,
|
||||
string $expectedResponse
|
||||
): void {
|
||||
$redis = $this->getClient();
|
||||
|
||||
$this->assertEquals('OK', $redis->jsonset(...$setArguments));
|
||||
$this->assertEquals('OK', $redis->jsonmerge(...$mergeArguments));
|
||||
$this->assertEquals($expectedResponse, $redis->jsonget('key'));
|
||||
}
|
||||
|
||||
public function jsonProvider(): array
|
||||
{
|
||||
return [
|
||||
'create non-existing value' => [
|
||||
['key', '$', '{"a":2}'],
|
||||
['key', '$.b', '8'],
|
||||
'{"a":2,"b":8}',
|
||||
],
|
||||
'replace existing value' => [
|
||||
['key', '$', '{"a":2}'],
|
||||
['key', '$.a', '3'],
|
||||
'{"a":3}',
|
||||
],
|
||||
'replace an array' => [
|
||||
['key', '$', '{"a":[2,4,6,8]}'],
|
||||
['key', '$.a', '[10,12]'],
|
||||
'{"a":[10,12]}',
|
||||
],
|
||||
'merge in multiple-paths' => [
|
||||
['key', '$', '{"f1": {"a":1}, "f2":{"a":2}}'],
|
||||
['key', '$', '{"f2":{"a":3, "b":4}, "f3":[2,4,6]}'],
|
||||
'{"f1":{"a":1},"f2":{"a":3,"b":4},"f3":[2,4,6]}',
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command\Redis\Json;
|
||||
|
||||
use Predis\Command\Redis\PredisCommandTestCase;
|
||||
use Predis\Response\ServerException;
|
||||
|
||||
class JSONMSET_Test extends PredisCommandTestCase
|
||||
{
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function getExpectedCommand(): string
|
||||
{
|
||||
return JSONMSET::class;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function getExpectedId(): string
|
||||
{
|
||||
return 'JSONMSET';
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
public function testFilterArguments(): void
|
||||
{
|
||||
$arguments = ['key', '$..', 'value', 'key1', '$', 'value1'];
|
||||
$expected = ['key', '$..', 'value', 'key1', '$', 'value1'];
|
||||
|
||||
$command = $this->getCommand();
|
||||
$command->setArguments($arguments);
|
||||
|
||||
$this->assertSame($expected, $command->getArguments());
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
public function testParseResponse(): void
|
||||
{
|
||||
$this->assertSame(1, $this->getCommand()->parseResponse(1));
|
||||
}
|
||||
|
||||
/**
|
||||
* @group connected
|
||||
* @return void
|
||||
* @requiresRedisJsonVersion >= 2.6.0
|
||||
*/
|
||||
public function testSetMultipleJsonDocuments(): void
|
||||
{
|
||||
$redis = $this->getClient();
|
||||
|
||||
$this->assertEquals('OK', $redis->jsonmset('doc1', '$', '{"a":2}', 'doc2', '$', '{"b":3}'));
|
||||
$this->assertEquals(['[{"a":2}]', '[{"b":3}]'], $redis->jsonmget(['doc1', 'doc2'], '$'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @group connected
|
||||
* @return void
|
||||
* @requiresRedisJsonVersion >= 2.6.0
|
||||
*/
|
||||
public function testThrowsExceptionOnNewValuesNotInTheRootPath(): void
|
||||
{
|
||||
$redis = $this->getClient();
|
||||
|
||||
$this->expectException(ServerException::class);
|
||||
$this->expectExceptionMessage('ERR new objects must be created at the root');
|
||||
|
||||
$redis->jsonmset('doc1', '$', '{"a":2}', 'doc2', '$.f', '{"b":3}');
|
||||
}
|
||||
}
|
||||
@@ -58,9 +58,9 @@ class LCS_Test extends PredisCommandTestCase
|
||||
/**
|
||||
* @group connected
|
||||
* @dataProvider stringsProvider
|
||||
* @param array $stringsArguments
|
||||
* @param array $functionArguments
|
||||
* @param $expectedResponse
|
||||
* @param array $stringsArguments
|
||||
* @param array $functionArguments
|
||||
* @param $expectedResponse
|
||||
* @return void
|
||||
* @requiresRedisVersion >= 7.0.0
|
||||
*/
|
||||
|
||||
@@ -134,4 +134,17 @@ class SET_Test extends PredisCommandTestCase
|
||||
$this->assertEquals('OK', $redis->set('foo', 'barbar', 'XX'));
|
||||
$this->assertNull($redis->set('foofoo', 'barbar', 'XX'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @group connected
|
||||
* @group cluster
|
||||
* @requiresRedisVersion >= 3.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function testSetStringValueInClusterMode(): void
|
||||
{
|
||||
$redis = $this->getClient();
|
||||
|
||||
$this->assertEquals('OK', $redis->set('foo', 'bar'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,13 +35,48 @@ class SHUTDOWN_Test extends PredisCommandTestCase
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider argumentsProvider
|
||||
* @group disconnected
|
||||
*/
|
||||
public function testFilterArguments(): void
|
||||
public function testFilterArguments(array $actualArguments, array $expectedResponse): void
|
||||
{
|
||||
$command = $this->getCommand();
|
||||
$command->setArguments([]);
|
||||
$command->setArguments($actualArguments);
|
||||
|
||||
$this->assertSame([], $command->getArguments());
|
||||
$this->assertSame($expectedResponse, $command->getArguments());
|
||||
}
|
||||
|
||||
public function argumentsProvider(): array
|
||||
{
|
||||
return [
|
||||
'with no arguments' => [
|
||||
[],
|
||||
[],
|
||||
],
|
||||
'with SAVE argument' => [
|
||||
[true],
|
||||
['SAVE'],
|
||||
],
|
||||
'with NOSAVE argument' => [
|
||||
[false],
|
||||
['NOSAVE'],
|
||||
],
|
||||
'with NOW argument' => [
|
||||
[null, true],
|
||||
['NOW'],
|
||||
],
|
||||
'with FORCE argument' => [
|
||||
[null, false, true],
|
||||
['FORCE'],
|
||||
],
|
||||
'with ABORT argument' => [
|
||||
[null, false, false, true],
|
||||
['ABORT'],
|
||||
],
|
||||
'with all arguments' => [
|
||||
[true, true, true, true],
|
||||
['SAVE', 'NOW', 'FORCE', 'ABORT'],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,6 +113,9 @@ class FTSEARCH_Test extends PredisCommandTestCase
|
||||
$ftCreateResponse = $redis->ftcreate('idx_hash', $schema, $ftCreateArguments);
|
||||
$this->assertEquals('OK', $ftCreateResponse);
|
||||
|
||||
// Timeout to make sure that index created before search performed.
|
||||
usleep(2000);
|
||||
|
||||
$ftSearchArguments = new SearchArguments();
|
||||
$ftSearchArguments->addReturn(1, 'should_return');
|
||||
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
class WAITAOF_Test extends PredisCommandTestCase
|
||||
{
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$redis = $this->getClient();
|
||||
$this->assertEquals('OK', $redis->config('set', 'appendonly', 'yes'));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function getExpectedCommand(): string
|
||||
{
|
||||
return WAITAOF::class;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function getExpectedId(): string
|
||||
{
|
||||
return 'WAITAOF';
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
public function testFilterArguments(): void
|
||||
{
|
||||
$actualArguments = $expectedArguments = [1, 2, 3];
|
||||
|
||||
$command = $this->getCommand();
|
||||
$command->setArguments($actualArguments);
|
||||
|
||||
$this->assertSameValues($expectedArguments, $command->getArguments());
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
public function testParseResponse(): void
|
||||
{
|
||||
$this->assertSame(1, $this->getCommand()->parseResponse(1));
|
||||
}
|
||||
|
||||
/**
|
||||
* @group connected
|
||||
* @return void
|
||||
* @requiresRedisVersion >= 7.2.0
|
||||
*/
|
||||
public function testReturnQuantityOfSyncedAOFInstances(): void
|
||||
{
|
||||
$redis = $this->getClient();
|
||||
|
||||
$this->assertEquals('OK', $redis->set('foo', 'bar'));
|
||||
$this->assertSame([1, 0], $redis->waitaof(1, 0, 0));
|
||||
}
|
||||
|
||||
protected function tearDown(): void
|
||||
{
|
||||
$redis = $this->getClient();
|
||||
$this->assertEquals('OK', $redis->config('set', 'appendonly', 'no'));
|
||||
}
|
||||
}
|
||||
@@ -110,8 +110,8 @@ class ZINTERCARD_Test extends PredisCommandTestCase
|
||||
/**
|
||||
* @group connected
|
||||
* @dataProvider unexpectedValuesProvider
|
||||
* @param $keys
|
||||
* @param $limit
|
||||
* @param $keys
|
||||
* @param $limit
|
||||
* @param string $expectedExceptionMessage
|
||||
* @return void
|
||||
* @requiresRedisVersion >= 7.0.0
|
||||
|
||||
@@ -115,9 +115,9 @@ class ZINTERSTORE_Test extends PredisCommandTestCase
|
||||
|
||||
/**
|
||||
* @dataProvider unexpectedValueProvider
|
||||
* @param string $destination
|
||||
* @param $keys
|
||||
* @param $weights
|
||||
* @param string $destination
|
||||
* @param $keys
|
||||
* @param $weights
|
||||
* @param string $aggregate
|
||||
* @param string $expectedExceptionMessage
|
||||
* @return void
|
||||
|
||||
@@ -127,8 +127,8 @@ class ZINTER_Test extends PredisCommandTestCase
|
||||
|
||||
/**
|
||||
* @dataProvider unexpectedValueProvider
|
||||
* @param $keys
|
||||
* @param $weights
|
||||
* @param $keys
|
||||
* @param $weights
|
||||
* @param string $aggregate
|
||||
* @param bool $withScores
|
||||
* @param string $expectedExceptionMessage
|
||||
|
||||
@@ -102,14 +102,14 @@ class ZRANGESTORE_Test extends PredisCommandTestCase
|
||||
/**
|
||||
* @group connected
|
||||
* @dataProvider unexpectedValuesProvider
|
||||
* @param int|string $min
|
||||
* @param int|string $max
|
||||
* @param string|bool $by
|
||||
* @param $rev
|
||||
* @param $limit
|
||||
* @param int $offset
|
||||
* @param int $count
|
||||
* @param string $expectedExceptionMessage
|
||||
* @param int|string $min
|
||||
* @param int|string $max
|
||||
* @param string|bool $by
|
||||
* @param $rev
|
||||
* @param $limit
|
||||
* @param int $offset
|
||||
* @param int $count
|
||||
* @param string $expectedExceptionMessage
|
||||
* @return void
|
||||
* @requiresRedisVersion >= 6.2.0
|
||||
*/
|
||||
|
||||
@@ -115,9 +115,9 @@ class ZUNIONSTORE_Test extends PredisCommandTestCase
|
||||
|
||||
/**
|
||||
* @dataProvider unexpectedValueProvider
|
||||
* @param string $destination
|
||||
* @param $keys
|
||||
* @param $weights
|
||||
* @param string $destination
|
||||
* @param $keys
|
||||
* @param $weights
|
||||
* @param string $aggregate
|
||||
* @param string $expectedExceptionMessage
|
||||
* @return void
|
||||
|
||||
@@ -101,8 +101,8 @@ class ZUNION_Test extends PredisCommandTestCase
|
||||
|
||||
/**
|
||||
* @dataProvider unexpectedValueProvider
|
||||
* @param $keys
|
||||
* @param $weights
|
||||
* @param $keys
|
||||
* @param $weights
|
||||
* @param string $aggregate
|
||||
* @param bool $withScores
|
||||
* @param string $expectedExceptionMessage
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command\Strategy\ContainerCommands\Functions;
|
||||
|
||||
use PredisTestCase;
|
||||
|
||||
class DumpStrategyTest extends PredisTestCase
|
||||
{
|
||||
/**
|
||||
* @var DumpStrategy
|
||||
*/
|
||||
private $strategy;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->strategy = new DumpStrategy();
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
* @return void
|
||||
*/
|
||||
public function testProcessArguments(): void
|
||||
{
|
||||
$this->assertSame(['arg1', 'arg2'], $this->strategy->processArguments(['arg1', 'arg2']));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command\Strategy\ContainerCommands\Functions;
|
||||
|
||||
use PredisTestCase;
|
||||
|
||||
class FlushStrategyTest extends PredisTestCase
|
||||
{
|
||||
/**
|
||||
* @var FlushStrategy
|
||||
*/
|
||||
private $strategy;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->strategy = new FlushStrategy();
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider argumentsProvider
|
||||
* @group disconnected
|
||||
* @param array $actualArguments
|
||||
* @param array $expectedResponse
|
||||
* @return void
|
||||
*/
|
||||
public function testProcessArguments(array $actualArguments, array $expectedResponse): void
|
||||
{
|
||||
$this->assertSame($expectedResponse, $this->strategy->processArguments($actualArguments));
|
||||
}
|
||||
|
||||
public function argumentsProvider(): array
|
||||
{
|
||||
return [
|
||||
'with default arguments' => [
|
||||
['FLUSH', null],
|
||||
['FLUSH'],
|
||||
],
|
||||
'with mode argument' => [
|
||||
['FLUSH', 'sync'],
|
||||
['FLUSH', 'SYNC'],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command\Strategy\ContainerCommands\Functions;
|
||||
|
||||
use PredisTestCase;
|
||||
|
||||
class KillStrategyTest extends PredisTestCase
|
||||
{
|
||||
/**
|
||||
* @var KillStrategy
|
||||
*/
|
||||
private $strategy;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->strategy = new KillStrategy();
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
* @return void
|
||||
*/
|
||||
public function testProcessArguments(): void
|
||||
{
|
||||
$this->assertSame(['arg1', 'arg2'], $this->strategy->processArguments(['arg1', 'arg2']));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command\Strategy\ContainerCommands\Functions;
|
||||
|
||||
use PredisTestCase;
|
||||
|
||||
class ListStrategyTest extends PredisTestCase
|
||||
{
|
||||
/**
|
||||
* @var ListStrategy
|
||||
*/
|
||||
private $strategy;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->strategy = new ListStrategy();
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider argumentsProvider
|
||||
* @group disconnected
|
||||
* @param array $actualArguments
|
||||
* @param array $expectedResponse
|
||||
* @return void
|
||||
*/
|
||||
public function testProcessArguments(array $actualArguments, array $expectedResponse): void
|
||||
{
|
||||
$this->assertSame($expectedResponse, $this->strategy->processArguments($actualArguments));
|
||||
}
|
||||
|
||||
public function argumentsProvider(): array
|
||||
{
|
||||
return [
|
||||
'with default arguments' => [
|
||||
['LIST', null, false],
|
||||
['LIST'],
|
||||
],
|
||||
'with LIBRARYNAME modifier' => [
|
||||
['LIST', 'libraryname', false],
|
||||
['LIST', 'LIBRARYNAME', 'libraryname'],
|
||||
],
|
||||
'with WITHCODE modifier' => [
|
||||
['LIST', null, true],
|
||||
['LIST', 'WITHCODE'],
|
||||
],
|
||||
'with all arguments' => [
|
||||
['LIST', 'libraryname', true],
|
||||
['LIST', 'LIBRARYNAME', 'libraryname', 'WITHCODE'],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command\Strategy\ContainerCommands\Functions;
|
||||
|
||||
use PredisTestCase;
|
||||
|
||||
class RestoreStrategyTest extends PredisTestCase
|
||||
{
|
||||
/**
|
||||
* @var RestoreStrategy
|
||||
*/
|
||||
private $strategy;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->strategy = new RestoreStrategy();
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider argumentsProvider
|
||||
* @group disconnected
|
||||
* @param array $actualArguments
|
||||
* @param array $expectedResponse
|
||||
* @return void
|
||||
*/
|
||||
public function testProcessArguments(array $actualArguments, array $expectedResponse): void
|
||||
{
|
||||
$this->assertSame($expectedResponse, $this->strategy->processArguments($actualArguments));
|
||||
}
|
||||
|
||||
public function argumentsProvider(): array
|
||||
{
|
||||
return [
|
||||
'with default arguments' => [
|
||||
['RESTORE', 'value', null],
|
||||
['RESTORE', 'value'],
|
||||
],
|
||||
'with mode argument' => [
|
||||
['RESTORE', 'value', 'append'],
|
||||
['RESTORE', 'value', 'APPEND'],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Command\Strategy\ContainerCommands\Functions;
|
||||
|
||||
use PredisTestCase;
|
||||
|
||||
class StatsStrategyTest extends PredisTestCase
|
||||
{
|
||||
/**
|
||||
* @var StatsStrategy
|
||||
*/
|
||||
private $strategy;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->strategy = new StatsStrategy();
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
* @return void
|
||||
*/
|
||||
public function testProcessArguments(): void
|
||||
{
|
||||
$this->assertSame(['arg1', 'arg2'], $this->strategy->processArguments(['arg1', 'arg2']));
|
||||
}
|
||||
}
|
||||
@@ -19,23 +19,27 @@ use Predis\Command\Strategy\ContainerCommands\Functions\LoadStrategy;
|
||||
class SubcommandStrategyResolverTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @var StrategyResolverInterface
|
||||
*/
|
||||
private $resolver;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->resolver = new SubcommandStrategyResolver();
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
* @return void
|
||||
*/
|
||||
public function testResolveCorrectStrategy(): void
|
||||
{
|
||||
$resolver = new SubcommandStrategyResolver();
|
||||
$expectedStrategy = new LoadStrategy();
|
||||
|
||||
$this->assertEquals($expectedStrategy, $this->resolver->resolve('functions', 'load'));
|
||||
$this->assertEquals($expectedStrategy, $resolver->resolve('functions', 'load'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
* @return void
|
||||
*/
|
||||
public function testResolveCorrectlyResolvesStrategyWithGivenWordSeparator(): void
|
||||
{
|
||||
$resolver = new SubcommandStrategyResolver('_');
|
||||
$expectedStrategy = new LoadStrategy();
|
||||
|
||||
$this->assertEquals($expectedStrategy, $resolver->resolve('functions_', 'load_'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -43,9 +47,11 @@ class SubcommandStrategyResolverTest extends TestCase
|
||||
*/
|
||||
public function testResolveThrowsExceptionOnNonExistingStrategy(): void
|
||||
{
|
||||
$resolver = new SubcommandStrategyResolver();
|
||||
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
$this->expectExceptionMessage('Non-existing container command given');
|
||||
|
||||
$this->resolver->resolve('foo', 'bar');
|
||||
$resolver->resolve('foo', 'bar');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
|
||||
namespace Predis\Connection;
|
||||
|
||||
use Predis\Client;
|
||||
use Predis\Command\RawCommand;
|
||||
use PredisTestCase;
|
||||
use ReflectionObject;
|
||||
use stdClass;
|
||||
@@ -302,10 +304,12 @@ class FactoryTest extends PredisTestCase
|
||||
->method('getParameters')
|
||||
->willReturn($parameters);
|
||||
$connection
|
||||
->expects($this->exactly(2))
|
||||
->expects($this->exactly(4))
|
||||
->method('addConnectCommand')
|
||||
->withConsecutive(
|
||||
[$this->isRedisCommand('AUTH', ['foobar'])],
|
||||
[$this->isRedisCommand('CLIENT', ['SETINFO', 'LIB-NAME', 'predis'])],
|
||||
[$this->isRedisCommand('CLIENT', ['SETINFO', 'LIB-VER', Client::VERSION])],
|
||||
[$this->isRedisCommand('SELECT', ['0'])]
|
||||
);
|
||||
|
||||
@@ -331,9 +335,13 @@ class FactoryTest extends PredisTestCase
|
||||
$connection->expects($this->once())
|
||||
->method('getParameters')
|
||||
->will($this->returnValue($parameters));
|
||||
$connection->expects($this->once())
|
||||
$connection->expects($this->exactly(3))
|
||||
->method('addConnectCommand')
|
||||
->with($this->isRedisCommand('AUTH', ['foobar']));
|
||||
->withConsecutive(
|
||||
[$this->isRedisCommand('AUTH', ['foobar'])],
|
||||
[$this->isRedisCommand('CLIENT', ['SETINFO', 'LIB-NAME', 'predis'])],
|
||||
[$this->isRedisCommand('CLIENT', ['SETINFO', 'LIB-VER', Client::VERSION])]
|
||||
);
|
||||
|
||||
$factory = new Factory();
|
||||
|
||||
@@ -358,9 +366,13 @@ class FactoryTest extends PredisTestCase
|
||||
$connection->expects($this->once())
|
||||
->method('getParameters')
|
||||
->will($this->returnValue($parameters));
|
||||
$connection->expects($this->once())
|
||||
$connection->expects($this->exactly(3))
|
||||
->method('addConnectCommand')
|
||||
->with($this->isRedisCommand('AUTH', ['myusername', 'foobar']));
|
||||
->withConsecutive(
|
||||
[$this->isRedisCommand('AUTH', ['myusername', 'foobar'])],
|
||||
[$this->isRedisCommand('CLIENT', ['SETINFO', 'LIB-NAME', 'predis'])],
|
||||
[$this->isRedisCommand('CLIENT', ['SETINFO', 'LIB-VER', Client::VERSION])]
|
||||
);
|
||||
|
||||
$factory = new Factory();
|
||||
|
||||
@@ -384,8 +396,12 @@ class FactoryTest extends PredisTestCase
|
||||
$connection->expects($this->once())
|
||||
->method('getParameters')
|
||||
->will($this->returnValue($parameters));
|
||||
$connection->expects($this->never())
|
||||
->method('addConnectCommand');
|
||||
$connection->expects($this->exactly(2))
|
||||
->method('addConnectCommand')
|
||||
->withConsecutive(
|
||||
[$this->isRedisCommand('CLIENT', ['SETINFO', 'LIB-NAME', 'predis'])],
|
||||
[$this->isRedisCommand('CLIENT', ['SETINFO', 'LIB-VER', Client::VERSION])]
|
||||
);
|
||||
|
||||
$factory = new Factory();
|
||||
|
||||
@@ -410,8 +426,12 @@ class FactoryTest extends PredisTestCase
|
||||
$connection->expects($this->once())
|
||||
->method('getParameters')
|
||||
->will($this->returnValue($parameters));
|
||||
$connection->expects($this->never())
|
||||
->method('addConnectCommand');
|
||||
$connection->expects($this->exactly(2))
|
||||
->method('addConnectCommand')
|
||||
->withConsecutive(
|
||||
[$this->isRedisCommand('CLIENT', ['SETINFO', 'LIB-NAME', 'predis'])],
|
||||
[$this->isRedisCommand('CLIENT', ['SETINFO', 'LIB-VER', Client::VERSION])]
|
||||
);
|
||||
|
||||
$factory = new Factory();
|
||||
|
||||
@@ -538,6 +558,27 @@ class FactoryTest extends PredisTestCase
|
||||
$factory->create('test://127.0.0.1');
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
* @return void
|
||||
*/
|
||||
public function testSetClientNameAndVersionOnConnection(): void
|
||||
{
|
||||
$parameters = [];
|
||||
|
||||
$factory = new Factory();
|
||||
$connection = $factory->create($parameters);
|
||||
$initCommands = $connection->getInitCommands();
|
||||
|
||||
$this->assertInstanceOf(RawCommand::class, $initCommands[0]);
|
||||
$this->assertSame('CLIENT', $initCommands[0]->getId());
|
||||
$this->assertSame(['SETINFO', 'LIB-NAME', 'predis'], $initCommands[0]->getArguments());
|
||||
|
||||
$this->assertInstanceOf(RawCommand::class, $initCommands[1]);
|
||||
$this->assertSame('CLIENT', $initCommands[1]->getId());
|
||||
$this->assertSame(['SETINFO', 'LIB-VER', Client::VERSION], $initCommands[1]->getArguments());
|
||||
}
|
||||
|
||||
// ******************************************************************** //
|
||||
// ---- HELPER METHODS ------------------------------------------------ //
|
||||
// ******************************************************************** //
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
namespace Predis\Connection;
|
||||
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use Predis\Client;
|
||||
use Predis\Command\RawCommand;
|
||||
use Predis\Response\Error as ErrorResponse;
|
||||
|
||||
@@ -195,4 +196,22 @@ class StreamConnectionTest extends PredisConnectionTestCase
|
||||
$this->assertArrayHasKey('tcp_nodelay', $options['socket']);
|
||||
$this->assertFalse($options['socket']['tcp_nodelay']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group connected
|
||||
* @requiresRedisVersion < 7.0.0
|
||||
*/
|
||||
public function testConnectDoNotThrowsExceptionOnClientCommandError(): void
|
||||
{
|
||||
$connection = $this->createConnectionWithParams([]);
|
||||
$connection->addConnectCommand(
|
||||
new RawCommand('CLIENT', ['SETINFO', 'LIB-NAME', 'predis'])
|
||||
);
|
||||
$connection->addConnectCommand(
|
||||
new RawCommand('CLIENT', ['SETINFO', 'LIB-VER', Client::VERSION])
|
||||
);
|
||||
|
||||
$connection->connect();
|
||||
$this->assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -390,7 +390,7 @@ class ReplicationStrategyTest extends PredisTestCase
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getExpectedCommands(?string $type = null): array
|
||||
protected function getExpectedCommands(string $type = null): array
|
||||
{
|
||||
$commands = [
|
||||
/* commands operating on the connection */
|
||||
|
||||
Reference in New Issue
Block a user