From b27163e6285dcbd99d0843f340e7fe1ce6bf39ec Mon Sep 17 00:00:00 2001 From: Petr Levtonov Date: Thu, 20 Jan 2022 22:29:39 +0100 Subject: [PATCH] Add full phpredis support to the cache component - Improved the RedisStore to support phpredis serialization and compression settings. - Improve test suite related to phpredis. --- src/Illuminate/Cache/LuaScripts.php | 16 + src/Illuminate/Cache/RedisStore.php | 82 +- .../Testing/Concerns/InteractsWithRedis.php | 350 ++++- .../Redis/Connections/PacksPhpRedisValues.php | 32 + .../Testing/Fakes/NotificationFake.php | 2 +- tests/Cache/RedisCacheIntegrationTest.php | 54 +- tests/Filesystem/FilesystemAdapterTest.php | 10 +- .../Cache/PhpRedisCacheLockTest.php | 281 +--- .../Integration/Cache/RedisCacheLockTest.php | 103 +- tests/Integration/Cache/RedisStoreTest.php | 189 ++- .../Http/ThrottleRequestsWithRedisTest.php | 71 +- .../Queue/RateLimitedWithRedisTest.php | 55 +- .../ThrottlesExceptionsWithRedisTest.php | 41 +- tests/Queue/DynamoDbFailedJobProviderTest.php | 3 +- tests/Queue/QueueBeanstalkdQueueTest.php | 5 +- tests/Queue/QueueDatabaseQueueUnitTest.php | 7 +- tests/Queue/QueueRedisQueueTest.php | 11 +- tests/Queue/RedisQueueIntegrationTest.php | 216 ++- tests/Redis/ConcurrentLimiterTest.php | 61 +- tests/Redis/DurationLimiterTest.php | 42 +- tests/Redis/RedisConnectionTest.php | 1265 +++++++---------- tests/Redis/RedisConnectorTest.php | 50 +- 22 files changed, 1548 insertions(+), 1398 deletions(-) diff --git a/src/Illuminate/Cache/LuaScripts.php b/src/Illuminate/Cache/LuaScripts.php index 6d22fcd4357b..2fa6c277c6dc 100644 --- a/src/Illuminate/Cache/LuaScripts.php +++ b/src/Illuminate/Cache/LuaScripts.php @@ -20,6 +20,22 @@ public static function releaseLock() else return 0 end +LUA; + } + + /** + * Get the Lua script that sets a key only when it does not yet exist. + * + * KEYS[1] - The name of the key + * ARGV[1] - Value of the key + * ARGV[2] - Time in seconds how long to keep the key + * + * @return string + */ + public static function add() + { + return <<<'LUA' +return redis.call('exists',KEYS[1])<1 and redis.call('setex',KEYS[1],ARGV[2],ARGV[1]) LUA; } } diff --git a/src/Illuminate/Cache/RedisStore.php b/src/Illuminate/Cache/RedisStore.php index 4896c9183d03..e7bf16b66b24 100755 --- a/src/Illuminate/Cache/RedisStore.php +++ b/src/Illuminate/Cache/RedisStore.php @@ -59,9 +59,11 @@ public function __construct(Redis $redis, $prefix = '', $connection = 'default') */ public function get($key) { - $value = $this->connection()->get($this->prefix.$key); + $connection = $this->connection(); - return ! is_null($value) ? $this->unserialize($value) : null; + $value = $connection->get($this->prefix.$key); + + return $value === null ? null : $this->connectionAwareUnserialize($value, $connection); } /** @@ -76,12 +78,14 @@ public function many(array $keys) { $results = []; - $values = $this->connection()->mget(array_map(function ($key) { + $connection = $this->connection(); + + $values = $connection->mget(array_map(function ($key) { return $this->prefix.$key; }, $keys)); foreach ($values as $index => $value) { - $results[$keys[$index]] = ! is_null($value) ? $this->unserialize($value) : null; + $results[$keys[$index]] = $value === null ? null : $this->connectionAwareUnserialize($value, $connection); } return $results; @@ -97,8 +101,10 @@ public function many(array $keys) */ public function put($key, $value, $seconds) { - return (bool) $this->connection()->setex( - $this->prefix.$key, (int) max(1, $seconds), $this->serialize($value) + $connection = $this->connection(); + + return (bool) $connection->setex( + $this->prefix.$key, (int) max(1, $seconds), $this->connectionAwareSerialize($value, $connection) ); } @@ -136,10 +142,10 @@ public function putMany(array $values, $seconds) */ public function add($key, $value, $seconds) { - $lua = "return redis.call('exists',KEYS[1])<1 and redis.call('setex',KEYS[1],ARGV[2],ARGV[1])"; + $connection = $this->connection(); - return (bool) $this->connection()->eval( - $lua, 1, $this->prefix.$key, $this->serialize($value), (int) max(1, $seconds) + return (bool) $connection->eval( + LuaScripts::add(), 1, $this->prefix.$key, $this->pack($value, $connection), (int) max(1, $seconds) ); } @@ -176,7 +182,9 @@ public function decrement($key, $value = 1) */ public function forever($key, $value) { - return (bool) $this->connection()->set($this->prefix.$key, $this->serialize($value)); + $connection = $this->connection(); + + return (bool) $connection->set($this->prefix.$key, $this->connectionAwareSerialize($value, $connection)); } /** @@ -344,4 +352,58 @@ protected function unserialize($value) { return is_numeric($value) ? $value : unserialize($value); } + + /** + * Prepares a value to be used with the redis cache store when used with eval scripts. + * + * @param mixed $value + * @param \Illuminate\Redis\Connections\Connection $connection + * @return mixed + */ + protected function pack($value, $connection) + { + if ($connection instanceof PhpRedisConnection) { + if ($connection->serialized()) { + return $connection->pack([$value])[0]; + } + + if ($connection->compressed()) { + return $connection->pack([$this->serialize($value)])[0]; + } + } + + return $this->serialize($value); + } + + /** + * Does connection specific considerations when a value needs to be serialized. + * + * @param mixed $value + * @param \Illuminate\Redis\Connections\Connection $connection + * @return mixed + */ + protected function connectionAwareSerialize($value, $connection) + { + if ($connection instanceof PhpRedisConnection && $connection->serialized()) { + return $value; + } + + return $this->serialize($value); + } + + /** + * Does connection specific considerations when a value needs to be unserialized. + * + * @param mixed $value + * @param \Illuminate\Redis\Connections\Connection $connection + * @return mixed + */ + protected function connectionAwareUnserialize($value, $connection) + { + if ($connection instanceof PhpRedisConnection && $connection->serialized()) { + return $value; + } + + return $this->unserialize($value); + } } diff --git a/src/Illuminate/Foundation/Testing/Concerns/InteractsWithRedis.php b/src/Illuminate/Foundation/Testing/Concerns/InteractsWithRedis.php index 5c8d9040e244..ba4286063668 100644 --- a/src/Illuminate/Foundation/Testing/Concerns/InteractsWithRedis.php +++ b/src/Illuminate/Foundation/Testing/Concerns/InteractsWithRedis.php @@ -2,15 +2,18 @@ namespace Illuminate\Foundation\Testing\Concerns; -use Exception; use Illuminate\Foundation\Application; use Illuminate\Redis\RedisManager; +use Illuminate\Support\Collection; use Illuminate\Support\Env; +use Redis; +use Throwable; +use UnexpectedValueException; trait InteractsWithRedis { /** - * Indicate connection failed if redis is not available. + * Indicates connection failed if redis is not available. * * @var bool */ @@ -21,93 +24,342 @@ trait InteractsWithRedis * * @var \Illuminate\Redis\RedisManager[] */ - private $redis; + private $redisManagers = []; /** - * Setup redis connection. + * Teardown redis connection. * * @return void */ - public function setUpRedis() + public function tearDownRedis() + { + /** @var \Illuminate\Redis\RedisManager $redisManager */ + foreach ($this->redisManagers as $label => $redisManager) { + $redisManager->connection()->flushdb(); + $redisManager->connection()->disconnect(); + } + } + + /** + * Builds a redis manager from a predefined list of available connection + * configurations. + * + * If a driver and a config are given, they are used to create a new redis + * connection instead of the defaulting to a predefined list of connections. + * This way you can also create for example cluster or a very customized + * redis connection. + * + * @param string $connection Connection label. + * @param string $driver Optional driver to use together with a config. + * @param array $config Optional config to use for the connection. + * @return \Illuminate\Redis\RedisManager + */ + public function getRedisManager($connection, $driver = 'phpredis', $config = []) { if (! extension_loaded('redis')) { - $this->markTestSkipped('The redis extension is not installed. Please install the extension to enable '.__CLASS__); + $this->markTestSkipped( + 'The redis extension is not installed. Please install the extension to enable '.__CLASS__ + ); } if (static::$connectionFailedOnceWithDefaultsSkip) { - $this->markTestSkipped('Trying default host/port failed, please set environment variable REDIS_HOST & REDIS_PORT to enable '.__CLASS__); + $this->markTestSkipped( + 'Trying default host/port failed, please set environment variable '. + 'REDIS_HOST & REDIS_PORT to enable '.__CLASS__ + ); } - $app = $this->app ?? new Application; - $host = Env::get('REDIS_HOST', '127.0.0.1'); - $port = Env::get('REDIS_PORT', 6379); + if (! empty($config)) { + return $this->redisManagers[$connection] = $this->initializeRedisManager($driver, $config); + } + + if (array_key_exists($connection, $this->redisManagers)) { + return $this->redisManagers[$connection]; + } - foreach ($this->redisDriverProvider() as $driver) { - $this->redis[$driver[0]] = new RedisManager($app, $driver[0], [ - 'cluster' => false, + $config = [ + 'cluster' => false, + 'default' => [ + 'host' => env('REDIS_HOST', '127.0.0.1'), + 'port' => (int) env('REDIS_PORT', 6379), + 'timeout' => 0.5, + 'database' => 5, 'options' => [ - 'prefix' => 'test_', + 'name' => 'base', ], - 'default' => [ - 'host' => $host, - 'port' => $port, - 'database' => 5, - 'timeout' => 0.5, - 'name' => 'default', - ], - ]); + ], + ]; + + switch ($connection) { + case 'predis': + $driver = 'predis'; + $config['default']['options']['name'] = 'predis'; + break; + case 'phpredis': + $config['default']['options']['name'] = 'phpredis'; + break; + case 'phpredis_url': + $config['default']['options']['name'] = 'phpredis_url'; + $config['default']['url'] = "redis://user@{$config['default']['host']}:{$config['default']['port']}"; + $config['default']['host'] = 'overwrittenByUrl'; + $config['default']['port'] = 'overwrittenByUrl'; + break; + case 'phpredis_prefix': + $config['default']['options']['name'] = 'phpredis_prefix'; + $config['default']['options']['prefix'] = 'laravel:'; + break; + case 'phpredis_persistent': + $config['default']['options']['name'] = 'phpredis_persistent'; + $config['default']['persistent'] = true; + $config['default']['persistent_id'] = 'laravel'; + break; + case 'phpredis_scan_noretry': + $config['default']['options']['name'] = 'phpredis_scan_noretry'; + $config['default']['options']['scan'] = Redis::SCAN_NORETRY; + break; + case 'phpredis_scan_retry': + $config['default']['options']['name'] = 'phpredis_scan_retry'; + $config['default']['options']['scan'] = Redis::SCAN_RETRY; + break; + case 'phpredis_scan_prefix': + $config['default']['options']['name'] = 'phpredis_scan_prefix'; + $config['default']['options']['scan'] = Redis::SCAN_PREFIX; + break; + case 'phpredis_scan_noprefix': + $config['default']['options']['name'] = 'phpredis_scan_noprefix'; + $config['default']['options']['scan'] = Redis::SCAN_NOPREFIX; + break; + case 'phpredis_serializer_none': + $config['default']['options']['name'] = 'phpredis_serializer_none'; + $config['default']['options']['serializer'] = Redis::SERIALIZER_NONE; + break; + case 'phpredis_serializer_php': + $config['default']['options']['name'] = 'phpredis_serializer_php'; + $config['default']['options']['serializer'] = Redis::SERIALIZER_PHP; + break; + case 'phpredis_serializer_igbinary': + $config['default']['options']['name'] = 'phpredis_serializer_igbinary'; + $config['default']['options']['serializer'] = Redis::SERIALIZER_IGBINARY; + break; + case 'phpredis_serializer_json': + $config['default']['options']['name'] = 'phpredis_serializer_json'; + $config['default']['options']['serializer'] = Redis::SERIALIZER_JSON; + break; + case 'phpredis_serializer_msgpack': + $config['default']['options']['name'] = 'phpredis_serializer_msgpack'; + $config['default']['options']['serializer'] = Redis::SERIALIZER_MSGPACK; + break; + case 'phpredis_compression_lzf': + $config['default']['options']['name'] = 'phpredis_compression_lzf'; + $config['default']['options']['compression'] = Redis::COMPRESSION_LZF; + break; + case 'phpredis_compression_zstd': + $config['default']['options']['name'] = 'phpredis_compression_zstd'; + $config['default']['options']['compression'] = Redis::COMPRESSION_ZSTD; + break; + case 'phpredis_compression_zstd_default': + $config['default']['options']['name'] = 'phpredis_compression_zstd_default'; + $config['default']['options']['compression'] = Redis::COMPRESSION_ZSTD; + $config['default']['options']['compression_level'] = Redis::COMPRESSION_ZSTD_DEFAULT; + break; + case 'phpredis_compression_zstd_min': + $config['default']['options']['name'] = 'phpredis_compression_zstd_min'; + $config['default']['options']['compression'] = Redis::COMPRESSION_ZSTD; + $config['default']['options']['compression_level'] = Redis::COMPRESSION_ZSTD_MIN; + break; + case 'phpredis_compression_zstd_max': + $config['default']['options']['name'] = 'phpredis_compression_zstd_max'; + $config['default']['options']['compression'] = Redis::COMPRESSION_ZSTD; + $config['default']['options']['compression_level'] = Redis::COMPRESSION_ZSTD_MAX; + break; + case 'phpredis_compression_lz4': + $config['default']['options']['name'] = 'phpredis_compression_lz4'; + $config['default']['options']['compression'] = Redis::COMPRESSION_LZ4; + break; + case 'phpredis_compression_lz4_default': + $config['default']['options']['name'] = 'phpredis_compression_lz4_default'; + $config['default']['options']['compression'] = Redis::COMPRESSION_LZ4; + $config['default']['options']['compression_level'] = 0; + break; + case 'phpredis_compression_lz4_min': + $config['default']['options']['name'] = 'phpredis_compression_lz4_min'; + $config['default']['options']['compression'] = Redis::COMPRESSION_LZ4; + $config['default']['options']['compression_level'] = 1; + break; + case 'phpredis_compression_lz4_max': + $config['default']['options']['name'] = 'phpredis_compression_lz4_max'; + $config['default']['options']['compression'] = Redis::COMPRESSION_LZ4; + $config['default']['options']['compression_level'] = 12; + break; + case 'phpredis_msgpack_and_lz4': + $config['default']['options']['name'] = 'phpredis_msgpack_and_lz4'; + $config['default']['options']['serializer'] = Redis::SERIALIZER_MSGPACK; + $config['default']['options']['compression'] = Redis::COMPRESSION_LZ4; + $config['default']['options']['compression_level'] = 12; + break; + default: + throw new UnexpectedValueException(sprintf( + 'Redis manager connection configuration %s is not defined.', + $connection, + )); } - try { - $this->redis['phpredis']->connection()->flushdb(); - } catch (Exception $e) { - if ($host === '127.0.0.1' && $port === 6379 && Env::get('REDIS_HOST') === null) { - static::$connectionFailedOnceWithDefaultsSkip = true; + return $this->redisManagers[$connection] = $this->initializeRedisManager($driver, $config); + } - $this->markTestSkipped('Trying default host/port failed, please set environment variable REDIS_HOST & REDIS_PORT to enable '.__CLASS__); - } - } + /** + * Returns a list of available redis connections. + * + * @return array + */ + public function getRedisConnections() + { + return [ + 'predis', + 'phpredis', + ]; } /** - * Teardown redis connection. + * Returns an extended list of available redis connections. * - * @return void + * @return array */ - public function tearDownRedis() + public function getExtendedRedisConnections() { - $this->redis['phpredis']->connection()->flushdb(); + $connections = [ + 'predis', + 'phpredis', + 'phpredis_url', + 'phpredis_prefix', + 'phpredis_persistent', + ]; + + if (defined('Redis::SCAN_NORETRY')) { + $connections[] = 'phpredis_scan_noretry'; + } + + if (defined('Redis::SCAN_RETRY')) { + $connections[] = 'phpredis_scan_retry'; + } + + if (defined('Redis::SCAN_PREFIX')) { + $connections[] = 'phpredis_scan_prefix'; + } + + if (defined('Redis::SCAN_NOPREFIX')) { + $connections[] = 'phpredis_scan_noprefix'; + } + + if (defined('Redis::SERIALIZER_NONE')) { + $connections[] = 'phpredis_serializer_none'; + } + + if (defined('Redis::SERIALIZER_PHP')) { + $connections[] = 'phpredis_serializer_php'; + } + + if (defined('Redis::SERIALIZER_IGBINARY')) { + $connections[] = 'phpredis_serializer_igbinary'; + } + + if (defined('Redis::SERIALIZER_JSON')) { + $connections[] = 'phpredis_serializer_json'; + } + + if (defined('Redis::SERIALIZER_MSGPACK')) { + $connections[] = 'phpredis_serializer_msgpack'; + } + + if (defined('Redis::COMPRESSION_LZF')) { + $connections[] = 'phpredis_compression_lzf'; + } + + if (defined('Redis::COMPRESSION_ZSTD')) { + $connections[] = 'phpredis_compression_zstd'; + $connections[] = 'phpredis_compression_zstd_default'; + $connections[] = 'phpredis_compression_zstd_min'; + $connections[] = 'phpredis_compression_zstd_max'; + } + + if (defined('Redis::COMPRESSION_LZ4')) { + $connections[] = 'phpredis_compression_lz4'; + $connections[] = 'phpredis_compression_lz4_default'; + $connections[] = 'phpredis_compression_lz4_min'; + $connections[] = 'phpredis_compression_lz4_max'; + } - foreach ($this->redisDriverProvider() as $driver) { - $this->redis[$driver[0]]->connection()->disconnect(); + if (defined('Redis::SERIALIZER_MSGPACK') && defined('Redis::COMPRESSION_LZ4')) { + $connections[] = 'phpredis_msgpack_and_lz4'; } + + return $connections; } /** - * Get redis driver provider. + * Data provider for tests that lists a default set of redis connections. * * @return array */ - public function redisDriverProvider() + public function redisConnectionDataProvider() { - return [ - ['predis'], - ['phpredis'], - ]; + return (new Collection($this->getRedisConnections()))->mapWithKeys(function ($label) { + return [ + $label => [ + $label, + ], + ]; + })->all(); } /** - * Run test if redis is available. + * Extended data provider for tests that also lists special configurations + * like serialization and compression support on phpredis. * - * @param callable $callback - * @return void + * @return array */ - public function ifRedisAvailable($callback) + public function extendedRedisConnectionDataProvider() { - $this->setUpRedis(); + return (new Collection($this->getExtendedRedisConnections()))->mapWithKeys(function ($label) { + return [ + $label => [ + $label, + ], + ]; + })->all(); + } - $callback(); + /** + * Initializes a new RedisManager with the given driver and config. + * + * @param string $driver + * @param array $config + * @return \Illuminate\Redis\RedisManager + */ + private function initializeRedisManager($driver, $config) + { + $app = $this->app ?? new Application(); + $redisManager = new RedisManager($app, $driver, $config); + + try { + $redisManager->connection()->flushdb(); + } catch (Throwable $exception) { + if ( + $config['default']['host'] === '127.0.0.1' && + $config['default']['port'] === 6379 && + Env::get('REDIS_HOST') === null + ) { + static::$connectionFailedOnceWithDefaultsSkip = true; + + $this->markTestSkipped( + 'Trying default host/port failed, please set environment variable '. + 'REDIS_HOST & REDIS_PORT to enable '.__CLASS__ + ); + } + + throw $exception; + } - $this->tearDownRedis(); + return $redisManager; } } diff --git a/src/Illuminate/Redis/Connections/PacksPhpRedisValues.php b/src/Illuminate/Redis/Connections/PacksPhpRedisValues.php index 4d27ff59aebd..d91041b19dad 100644 --- a/src/Illuminate/Redis/Connections/PacksPhpRedisValues.php +++ b/src/Illuminate/Redis/Connections/PacksPhpRedisValues.php @@ -82,6 +82,38 @@ public function pack(array $values): array return array_map($processor, $values); } + /** + * Determine whether serialization and/or compression is enabled. + * + * @return bool + */ + public function packed(): bool + { + return $this->serialized() || $this->compressed(); + } + + /** + * Determine if serialization is enabled. + * + * @return bool + */ + public function serialized(): bool + { + return defined('Redis::OPT_SERIALIZER') && + $this->client->getOption(Redis::OPT_SERIALIZER) !== Redis::SERIALIZER_NONE; + } + + /** + * Determine if JSON serialization is enabled. + * + * @return bool + */ + public function jsonSerialized(): bool + { + return defined('Redis::SERIALIZER_JSON') && + $this->client->getOption(Redis::OPT_SERIALIZER) === Redis::SERIALIZER_JSON; + } + /** * Determine if compression is enabled. * diff --git a/src/Illuminate/Support/Testing/Fakes/NotificationFake.php b/src/Illuminate/Support/Testing/Fakes/NotificationFake.php index c7b12f42d47c..e3b0d4024bdf 100644 --- a/src/Illuminate/Support/Testing/Fakes/NotificationFake.php +++ b/src/Illuminate/Support/Testing/Fakes/NotificationFake.php @@ -270,7 +270,7 @@ public function sendNow($notifiables, $notification, array $channels = null) foreach ($notifiables as $notifiable) { if (! $notification->id) { - $notification->id = Str::uuid()->toString(); + $notification->id = (string) Str::uuid(); } $notifiableChannels = $channels ?: $notification->via($notifiable); diff --git a/tests/Cache/RedisCacheIntegrationTest.php b/tests/Cache/RedisCacheIntegrationTest.php index 410a02c6f82a..a5f66f121ff8 100644 --- a/tests/Cache/RedisCacheIntegrationTest.php +++ b/tests/Cache/RedisCacheIntegrationTest.php @@ -11,60 +11,66 @@ class RedisCacheIntegrationTest extends TestCase { use InteractsWithRedis; - protected function setUp(): void - { - parent::setUp(); - $this->setUpRedis(); - } - protected function tearDown(): void { - parent::tearDown(); $this->tearDownRedis(); + + parent::tearDown(); } /** - * @dataProvider redisDriverProvider + * @dataProvider extendedRedisConnectionDataProvider * - * @param string $driver + * @param string $connection */ - public function testRedisCacheAddTwice($driver) + public function testRedisCacheAddTwice($connection) { - $store = new RedisStore($this->redis[$driver]); - $repository = new Repository($store); + $repository = $this->getRepository($connection); + $this->assertTrue($repository->add('k', 'v', 3600)); $this->assertFalse($repository->add('k', 'v', 3600)); - $this->assertGreaterThan(3500, $this->redis[$driver]->connection()->ttl('k')); + $this->assertGreaterThan(3500, $repository->getStore()->connection()->ttl('k')); } /** * Breaking change. * - * @dataProvider redisDriverProvider + * @dataProvider extendedRedisConnectionDataProvider * - * @param string $driver + * @param string $connection */ - public function testRedisCacheAddFalse($driver) + public function testRedisCacheAddFalse($connection) { - $store = new RedisStore($this->redis[$driver]); - $repository = new Repository($store); + $repository = $this->getRepository($connection); + $repository->forever('k', false); $this->assertFalse($repository->add('k', 'v', 60)); - $this->assertEquals(-1, $this->redis[$driver]->connection()->ttl('k')); + $this->assertEquals(-1, $repository->getStore()->connection()->ttl('k')); } /** * Breaking change. * - * @dataProvider redisDriverProvider + * @dataProvider extendedRedisConnectionDataProvider * - * @param string $driver + * @param string $connection */ - public function testRedisCacheAddNull($driver) + public function testRedisCacheAddNull($connection) { - $store = new RedisStore($this->redis[$driver]); - $repository = new Repository($store); + $repository = $this->getRepository($connection); + $repository->forever('k', null); $this->assertFalse($repository->add('k', 'v', 60)); } + + /** + * Builds a cache repository out of a predefined redis connection name. + * + * @param string $connection + * @return \Illuminate\Cache\Repository + */ + private function getRepository($connection) + { + return new Repository(new RedisStore($this->getRedisManager($connection))); + } } diff --git a/tests/Filesystem/FilesystemAdapterTest.php b/tests/Filesystem/FilesystemAdapterTest.php index 440c03663283..4dcf5afacc35 100644 --- a/tests/Filesystem/FilesystemAdapterTest.php +++ b/tests/Filesystem/FilesystemAdapterTest.php @@ -64,7 +64,10 @@ public function testDownloadNonAsciiFilename() $files = new FilesystemAdapter($this->filesystem); $response = $files->download('file.txt', 'пиздюк.txt'); $this->assertInstanceOf(StreamedResponse::class, $response); - $this->assertSame("attachment; filename=pizdyuk.txt; filename*=utf-8''%D0%BF%D0%B8%D0%B7%D0%B4%D1%8E%D0%BA.txt", $response->headers->get('content-disposition')); + $this->assertContains($response->headers->get('content-disposition'), [ + "attachment; filename=pizdyuk.txt; filename*=utf-8''%D0%BF%D0%B8%D0%B7%D0%B4%D1%8E%D0%BA.txt", + "attachment; filename=pizdiuk.txt; filename*=utf-8''%D0%BF%D0%B8%D0%B7%D0%B4%D1%8E%D0%BA.txt", + ]); } public function testDownloadNonAsciiEmptyFilename() @@ -73,7 +76,10 @@ public function testDownloadNonAsciiEmptyFilename() $files = new FilesystemAdapter($this->filesystem); $response = $files->download('пиздюк.txt'); $this->assertInstanceOf(StreamedResponse::class, $response); - $this->assertSame('attachment; filename=pizdyuk.txt; filename*=utf-8\'\'%D0%BF%D0%B8%D0%B7%D0%B4%D1%8E%D0%BA.txt', $response->headers->get('content-disposition')); + $this->assertContains($response->headers->get('content-disposition'), [ + 'attachment; filename=pizdyuk.txt; filename*=utf-8\'\'%D0%BF%D0%B8%D0%B7%D0%B4%D1%8E%D0%BA.txt', + 'attachment; filename=pizdiuk.txt; filename*=utf-8\'\'%D0%BF%D0%B8%D0%B7%D0%B4%D1%8E%D0%BA.txt', + ]); } public function testDownloadPercentInFilename() diff --git a/tests/Integration/Cache/PhpRedisCacheLockTest.php b/tests/Integration/Cache/PhpRedisCacheLockTest.php index 0ca4ea85f960..9bbb9ce5eaf5 100644 --- a/tests/Integration/Cache/PhpRedisCacheLockTest.php +++ b/tests/Integration/Cache/PhpRedisCacheLockTest.php @@ -2,293 +2,48 @@ namespace Illuminate\Tests\Integration\Cache; +use Illuminate\Cache\RedisStore; use Illuminate\Foundation\Testing\Concerns\InteractsWithRedis; -use Illuminate\Support\Facades\Cache; use Orchestra\Testbench\TestCase; -use Redis; class PhpRedisCacheLockTest extends TestCase { use InteractsWithRedis; - protected function setUp(): void - { - parent::setUp(); - - $this->setUpRedis(); - } - protected function tearDown(): void { - parent::tearDown(); - $this->tearDownRedis(); - } - - public function testRedisLockCanBeAcquiredAndReleasedWithoutSerializationAndCompression() - { - $this->app['config']->set('database.redis.client', 'phpredis'); - $this->app['config']->set('cache.stores.redis.connection', 'default'); - $this->app['config']->set('cache.stores.redis.lock_connection', 'default'); - - /** @var \Illuminate\Cache\RedisStore $store */ - $store = Cache::store('redis'); - /** @var \Redis $client */ - $client = $store->lockConnection()->client(); - - $client->setOption(Redis::OPT_SERIALIZER, Redis::SERIALIZER_NONE); - $store->lock('foo')->forceRelease(); - $this->assertNull($store->lockConnection()->get($store->getPrefix().'foo')); - $lock = $store->lock('foo', 10); - $this->assertTrue($lock->get()); - $this->assertFalse($store->lock('foo', 10)->get()); - $lock->release(); - $this->assertNull($store->lockConnection()->get($store->getPrefix().'foo')); - } - - public function testRedisLockCanBeAcquiredAndReleasedWithPhpSerialization() - { - $this->app['config']->set('database.redis.client', 'phpredis'); - $this->app['config']->set('cache.stores.redis.connection', 'default'); - $this->app['config']->set('cache.stores.redis.lock_connection', 'default'); - - /** @var \Illuminate\Cache\RedisStore $store */ - $store = Cache::store('redis'); - /** @var \Redis $client */ - $client = $store->lockConnection()->client(); - - $client->setOption(Redis::OPT_SERIALIZER, Redis::SERIALIZER_PHP); - $store->lock('foo')->forceRelease(); - $this->assertNull($store->lockConnection()->get($store->getPrefix().'foo')); - $lock = $store->lock('foo', 10); - $this->assertTrue($lock->get()); - $this->assertFalse($store->lock('foo', 10)->get()); - $lock->release(); - $this->assertNull($store->lockConnection()->get($store->getPrefix().'foo')); - } - public function testRedisLockCanBeAcquiredAndReleasedWithJsonSerialization() - { - $this->app['config']->set('database.redis.client', 'phpredis'); - $this->app['config']->set('cache.stores.redis.connection', 'default'); - $this->app['config']->set('cache.stores.redis.lock_connection', 'default'); - - /** @var \Illuminate\Cache\RedisStore $store */ - $store = Cache::store('redis'); - /** @var \Redis $client */ - $client = $store->lockConnection()->client(); - - $client->setOption(Redis::OPT_SERIALIZER, Redis::SERIALIZER_JSON); - $store->lock('foo')->forceRelease(); - $this->assertNull($store->lockConnection()->get($store->getPrefix().'foo')); - $lock = $store->lock('foo', 10); - $this->assertTrue($lock->get()); - $this->assertFalse($store->lock('foo', 10)->get()); - $lock->release(); - $this->assertNull($store->lockConnection()->get($store->getPrefix().'foo')); - } - - public function testRedisLockCanBeAcquiredAndReleasedWithIgbinarySerialization() - { - if (! defined('Redis::SERIALIZER_IGBINARY')) { - $this->markTestSkipped('Redis extension is not configured to support the igbinary serializer.'); - } - - $this->app['config']->set('database.redis.client', 'phpredis'); - $this->app['config']->set('cache.stores.redis.connection', 'default'); - $this->app['config']->set('cache.stores.redis.lock_connection', 'default'); - - /** @var \Illuminate\Cache\RedisStore $store */ - $store = Cache::store('redis'); - /** @var \Redis $client */ - $client = $store->lockConnection()->client(); - - $client->setOption(Redis::OPT_SERIALIZER, Redis::SERIALIZER_IGBINARY); - $store->lock('foo')->forceRelease(); - $this->assertNull($store->lockConnection()->get($store->getPrefix().'foo')); - $lock = $store->lock('foo', 10); - $this->assertTrue($lock->get()); - $this->assertFalse($store->lock('foo', 10)->get()); - $lock->release(); - $this->assertNull($store->lockConnection()->get($store->getPrefix().'foo')); - } - - public function testRedisLockCanBeAcquiredAndReleasedWithMsgpackSerialization() - { - if (! defined('Redis::SERIALIZER_MSGPACK')) { - $this->markTestSkipped('Redis extension is not configured to support the msgpack serializer.'); - } - - $this->app['config']->set('database.redis.client', 'phpredis'); - $this->app['config']->set('cache.stores.redis.connection', 'default'); - $this->app['config']->set('cache.stores.redis.lock_connection', 'default'); - - /** @var \Illuminate\Cache\RedisStore $store */ - $store = Cache::store('redis'); - /** @var \Redis $client */ - $client = $store->lockConnection()->client(); - - $client->setOption(Redis::OPT_SERIALIZER, Redis::SERIALIZER_MSGPACK); - $store->lock('foo')->forceRelease(); - $this->assertNull($store->lockConnection()->get($store->getPrefix().'foo')); - $lock = $store->lock('foo', 10); - $this->assertTrue($lock->get()); - $this->assertFalse($store->lock('foo', 10)->get()); - $lock->release(); - $this->assertNull($store->lockConnection()->get($store->getPrefix().'foo')); - } - - /** - * @requires extension lzf - */ - public function testRedisLockCanBeAcquiredAndReleasedWithLzfCompression() - { - if (! defined('Redis::COMPRESSION_LZF')) { - $this->markTestSkipped('Redis extension is not configured to support the lzf compression.'); - } - - $this->app['config']->set('database.redis.client', 'phpredis'); - $this->app['config']->set('cache.stores.redis.connection', 'default'); - $this->app['config']->set('cache.stores.redis.lock_connection', 'default'); - - /** @var \Illuminate\Cache\RedisStore $store */ - $store = Cache::store('redis'); - /** @var \Redis $client */ - $client = $store->lockConnection()->client(); - - $client->setOption(Redis::OPT_SERIALIZER, Redis::SERIALIZER_NONE); - $client->setOption(Redis::OPT_COMPRESSION, Redis::COMPRESSION_LZF); - $store->lock('foo')->forceRelease(); - $this->assertNull($store->lockConnection()->get($store->getPrefix().'foo')); - $lock = $store->lock('foo', 10); - $this->assertTrue($lock->get()); - $this->assertFalse($store->lock('foo', 10)->get()); - $lock->release(); - $this->assertNull($store->lockConnection()->get($store->getPrefix().'foo')); - } - - /** - * @requires extension zstd - */ - public function testRedisLockCanBeAcquiredAndReleasedWithZstdCompression() - { - if (! defined('Redis::COMPRESSION_ZSTD')) { - $this->markTestSkipped('Redis extension is not configured to support the zstd compression.'); - } - - $this->app['config']->set('database.redis.client', 'phpredis'); - $this->app['config']->set('cache.stores.redis.connection', 'default'); - $this->app['config']->set('cache.stores.redis.lock_connection', 'default'); - - /** @var \Illuminate\Cache\RedisStore $store */ - $store = Cache::store('redis'); - /** @var \Redis $client */ - $client = $store->lockConnection()->client(); - - $client->setOption(Redis::OPT_SERIALIZER, Redis::SERIALIZER_NONE); - $client->setOption(Redis::OPT_COMPRESSION, Redis::COMPRESSION_ZSTD); - $client->setOption(Redis::OPT_COMPRESSION_LEVEL, Redis::COMPRESSION_ZSTD_DEFAULT); - $store->lock('foo')->forceRelease(); - $this->assertNull($store->lockConnection()->get($store->getPrefix().'foo')); - $lock = $store->lock('foo', 10); - $this->assertTrue($lock->get()); - $this->assertFalse($store->lock('foo', 10)->get()); - $lock->release(); - $this->assertNull($store->lockConnection()->get($store->getPrefix().'foo')); - - $client->setOption(Redis::OPT_COMPRESSION_LEVEL, Redis::COMPRESSION_ZSTD_MIN); - $store->lock('foo')->forceRelease(); - $this->assertNull($store->lockConnection()->get($store->getPrefix().'foo')); - $lock = $store->lock('foo', 10); - $this->assertTrue($lock->get()); - $this->assertFalse($store->lock('foo', 10)->get()); - $lock->release(); - $this->assertNull($store->lockConnection()->get($store->getPrefix().'foo')); - - $client->setOption(Redis::OPT_COMPRESSION_LEVEL, Redis::COMPRESSION_ZSTD_MAX); - $store->lock('foo')->forceRelease(); - $this->assertNull($store->lockConnection()->get($store->getPrefix().'foo')); - $lock = $store->lock('foo', 10); - $this->assertTrue($lock->get()); - $this->assertFalse($store->lock('foo', 10)->get()); - $lock->release(); - $this->assertNull($store->lockConnection()->get($store->getPrefix().'foo')); + parent::tearDown(); } /** - * @requires extension lz4 + * @dataProvider extendedRedisConnectionDataProvider */ - public function testRedisLockCanBeAcquiredAndReleasedWithLz4Compression() + public function testPhpRedisLockCanBeAcquiredAndReleased($connection) { - if (! defined('Redis::COMPRESSION_LZ4')) { - $this->markTestSkipped('Redis extension is not configured to support the lz4 compression.'); - } - - $this->app['config']->set('database.redis.client', 'phpredis'); - $this->app['config']->set('cache.stores.redis.connection', 'default'); - $this->app['config']->set('cache.stores.redis.lock_connection', 'default'); - - /** @var \Illuminate\Cache\RedisStore $store */ - $store = Cache::store('redis'); - /** @var \Redis $client */ - $client = $store->lockConnection()->client(); + $repository = $this->getRepository($connection); - $client->setOption(Redis::OPT_SERIALIZER, Redis::SERIALIZER_NONE); - $client->setOption(Redis::OPT_COMPRESSION, Redis::COMPRESSION_LZ4); - $client->setOption(Redis::OPT_COMPRESSION_LEVEL, 1); - $store->lock('foo')->forceRelease(); - $this->assertNull($store->lockConnection()->get($store->getPrefix().'foo')); - $lock = $store->lock('foo', 10); + $repository->lock('foo')->forceRelease(); + $this->assertNull($repository->lockConnection()->get($repository->getPrefix().'foo')); + $lock = $repository->lock('foo', 10); $this->assertTrue($lock->get()); - $this->assertFalse($store->lock('foo', 10)->get()); + $this->assertFalse($repository->lock('foo', 10)->get()); $lock->release(); - $this->assertNull($store->lockConnection()->get($store->getPrefix().'foo')); - - $client->setOption(Redis::OPT_COMPRESSION_LEVEL, 3); - $store->lock('foo')->forceRelease(); - $this->assertNull($store->lockConnection()->get($store->getPrefix().'foo')); - $lock = $store->lock('foo', 10); - $this->assertTrue($lock->get()); - $this->assertFalse($store->lock('foo', 10)->get()); - $lock->release(); - $this->assertNull($store->lockConnection()->get($store->getPrefix().'foo')); - - $client->setOption(Redis::OPT_COMPRESSION_LEVEL, 12); - $store->lock('foo')->forceRelease(); - $this->assertNull($store->lockConnection()->get($store->getPrefix().'foo')); - $lock = $store->lock('foo', 10); - $this->assertTrue($lock->get()); - $this->assertFalse($store->lock('foo', 10)->get()); - $lock->release(); - $this->assertNull($store->lockConnection()->get($store->getPrefix().'foo')); + $this->assertNull($repository->lockConnection()->get($repository->getPrefix().'foo')); } /** - * @requires extension Lzf + * Builds a cache repository out of a predefined redis connection name. + * + * @param string $connection + * @return \Illuminate\Cache\Repository */ - public function testRedisLockCanBeAcquiredAndReleasedWithSerializationAndCompression() + private function getRepository($connection) { - if (! defined('Redis::COMPRESSION_LZF')) { - $this->markTestSkipped('Redis extension is not configured to support the lzf compression.'); - } - - $this->app['config']->set('database.redis.client', 'phpredis'); - $this->app['config']->set('cache.stores.redis.connection', 'default'); - $this->app['config']->set('cache.stores.redis.lock_connection', 'default'); - - /** @var \Illuminate\Cache\RedisStore $store */ - $store = Cache::store('redis'); - /** @var \Redis $client */ - $client = $store->lockConnection()->client(); + /** @var \Illuminate\Cache\CacheManager $cacheManager */ + $cacheManager = $this->app->get('cache'); - $client->setOption(Redis::OPT_SERIALIZER, Redis::SERIALIZER_PHP); - $client->setOption(Redis::OPT_COMPRESSION, Redis::COMPRESSION_LZF); - $store->lock('foo')->forceRelease(); - $this->assertNull($store->lockConnection()->get($store->getPrefix().'foo')); - $lock = $store->lock('foo', 10); - $this->assertTrue($lock->get()); - $this->assertFalse($store->lock('foo', 10)->get()); - $lock->release(); - $this->assertNull($store->lockConnection()->get($store->getPrefix().'foo')); + return $cacheManager->repository(new RedisStore($this->getRedisManager($connection))); } } diff --git a/tests/Integration/Cache/RedisCacheLockTest.php b/tests/Integration/Cache/RedisCacheLockTest.php index c131c0c23c2e..940a3c01fc88 100644 --- a/tests/Integration/Cache/RedisCacheLockTest.php +++ b/tests/Integration/Cache/RedisCacheLockTest.php @@ -3,6 +3,7 @@ namespace Illuminate\Tests\Integration\Cache; use Exception; +use Illuminate\Cache\RedisStore; use Illuminate\Foundation\Testing\Concerns\InteractsWithRedis; use Illuminate\Support\Carbon; use Illuminate\Support\Facades\Cache; @@ -12,76 +13,88 @@ class RedisCacheLockTest extends TestCase { use InteractsWithRedis; - protected function setUp(): void - { - parent::setUp(); - - $this->setUpRedis(); - } - protected function tearDown(): void { - parent::tearDown(); - $this->tearDownRedis(); + Carbon::setTestNow(false); + + parent::tearDown(); } - public function testRedisLocksCanBeAcquiredAndReleased() + /** + * @dataProvider extendedRedisConnectionDataProvider + */ + public function testRedisLocksCanBeAcquiredAndReleased($connection) { - Cache::store('redis')->lock('foo')->forceRelease(); + $repository = $this->getRepository($connection); + $repository->lock('foo')->forceRelease(); - $lock = Cache::store('redis')->lock('foo', 10); + $lock = $repository->lock('foo', 10); $this->assertTrue($lock->get()); - $this->assertFalse(Cache::store('redis')->lock('foo', 10)->get()); + $this->assertFalse($repository->lock('foo', 10)->get()); $lock->release(); - $lock = Cache::store('redis')->lock('foo', 10); + $lock = $repository->lock('foo', 10); $this->assertTrue($lock->get()); - $this->assertFalse(Cache::store('redis')->lock('foo', 10)->get()); - Cache::store('redis')->lock('foo')->release(); + $this->assertFalse($repository->lock('foo', 10)->get()); + $repository->lock('foo')->release(); } public function testRedisLockCanHaveASeparateConnection() { $this->app['config']->set('cache.stores.redis.lock_connection', 'default'); + $this->app['redis'] = $this->getRedisManager('phpredis'); + $this->assertSame('default', Cache::store('redis')->lock('foo')->getConnectionName()); } - public function testRedisLocksCanBlockForSeconds() + /** + * @dataProvider extendedRedisConnectionDataProvider + */ + public function testRedisLocksCanBlockForSeconds($connection) { + $repository = $this->getRepository($connection); Carbon::setTestNow(); - Cache::store('redis')->lock('foo')->forceRelease(); - $this->assertSame('taylor', Cache::store('redis')->lock('foo', 10)->block(1, function () { + $repository->lock('foo')->forceRelease(); + $this->assertSame('taylor', $repository->lock('foo', 10)->block(1, function () { return 'taylor'; })); - Cache::store('redis')->lock('foo')->forceRelease(); - $this->assertTrue(Cache::store('redis')->lock('foo', 10)->block(1)); + $repository->lock('foo')->forceRelease(); + $this->assertTrue($repository->lock('foo', 10)->block(1)); } - public function testConcurrentRedisLocksAreReleasedSafely() + /** + * @dataProvider redisConnectionDataProvider + */ + public function testConcurrentRedisLocksAreReleasedSafely($connection) { - Cache::store('redis')->lock('foo')->forceRelease(); + $repository = $this->getRepository($connection); + $repository->lock('foo')->forceRelease(); - $firstLock = Cache::store('redis')->lock('foo', 1); + $firstLock = $repository->lock('foo', 1); $this->assertTrue($firstLock->get()); - sleep(2); + usleep(1100000); - $secondLock = Cache::store('redis')->lock('foo', 10); + $secondLock = $repository->lock('foo', 10); $this->assertTrue($secondLock->get()); $firstLock->release(); - $this->assertFalse(Cache::store('redis')->lock('foo')->get()); + $this->assertFalse($repository->lock('foo')->get()); } - public function testRedisLocksWithFailedBlockCallbackAreReleased() + /** + * @dataProvider extendedRedisConnectionDataProvider + */ + public function testRedisLocksWithFailedBlockCallbackAreReleased($connection) { - Cache::store('redis')->lock('foo')->forceRelease(); + $repository = $this->getRepository($connection); + $repository->lock('foo')->forceRelease(); - $firstLock = Cache::store('redis')->lock('foo', 10); + $firstLock = $repository->lock('foo', 10); try { $firstLock->block(1, function () { @@ -93,22 +106,40 @@ public function testRedisLocksWithFailedBlockCallbackAreReleased() // thrown by the callback was handled. } - $secondLock = Cache::store('redis')->lock('foo', 1); + $secondLock = $repository->lock('foo', 1); $this->assertTrue($secondLock->get()); } - public function testRedisLocksCanBeReleasedUsingOwnerToken() + /** + * @dataProvider extendedRedisConnectionDataProvider + */ + public function testRedisLocksCanBeReleasedUsingOwnerToken($connection) { - Cache::store('redis')->lock('foo')->forceRelease(); + $repository = $this->getRepository($connection); + $repository->lock('foo')->forceRelease(); - $firstLock = Cache::store('redis')->lock('foo', 10); + $firstLock = $repository->lock('foo', 10); $this->assertTrue($firstLock->get()); $owner = $firstLock->owner(); - $secondLock = Cache::store('redis')->restoreLock('foo', $owner); + $secondLock = $repository->restoreLock('foo', $owner); $secondLock->release(); - $this->assertTrue(Cache::store('redis')->lock('foo')->get()); + $this->assertTrue($repository->lock('foo')->get()); + } + + /** + * Builds a cache repository out of a predefined redis connection name. + * + * @param string $connection + * @return \Illuminate\Cache\Repository + */ + private function getRepository($connection) + { + /** @var \Illuminate\Cache\CacheManager $cacheManager */ + $cacheManager = $this->app->get('cache'); + + return $cacheManager->repository(new RedisStore($this->getRedisManager($connection))); } } diff --git a/tests/Integration/Cache/RedisStoreTest.php b/tests/Integration/Cache/RedisStoreTest.php index ad89de93afd2..7f8355398619 100644 --- a/tests/Integration/Cache/RedisStoreTest.php +++ b/tests/Integration/Cache/RedisStoreTest.php @@ -2,47 +2,202 @@ namespace Illuminate\Tests\Integration\Cache; +use Illuminate\Cache\RedisStore; use Illuminate\Foundation\Testing\Concerns\InteractsWithRedis; -use Illuminate\Support\Facades\Cache; +use Illuminate\Redis\Connections\PhpRedisConnection; use Orchestra\Testbench\TestCase; class RedisStoreTest extends TestCase { use InteractsWithRedis; - protected function setUp(): void + protected function tearDown(): void { - parent::setUp(); + $this->tearDownRedis(); - $this->setUpRedis(); + parent::tearDown(); } - protected function tearDown(): void + /** + * @dataProvider extendedRedisConnectionDataProvider + */ + public function testItCanStoreInfinite($connection) { - parent::tearDown(); + $repository = $this->getRepository($connection); + /** @var \Illuminate\Cache\RedisStore $redisStore */ + $redisStore = $repository->getStore(); + $redisConnection = $redisStore->connection(); - $this->tearDownRedis(); + if ($redisConnection instanceof PhpRedisConnection && $redisConnection->jsonSerialized()) { + $this->markTestSkipped( + 'JSON does not support INF or -INF. It will be serialized to null '. + 'and as a result phpredis will store it as 0.' + ); + } + + $result = $repository->put('foo', INF); + $this->assertTrue($result); + $this->assertSame(INF, $repository->get('foo')); + + $result = $repository->put('foo', -INF); + $this->assertTrue($result); + $this->assertSame(-INF, $repository->get('foo')); + } + + /** + * @dataProvider extendedRedisConnectionDataProvider + */ + public function testItCanStoreNan($connection) + { + $repository = $this->getRepository($connection); + /** @var \Illuminate\Cache\RedisStore $redisStore */ + $redisStore = $repository->getStore(); + $redisConnection = $redisStore->connection(); + + if ($redisConnection instanceof PhpRedisConnection && $redisConnection->jsonSerialized()) { + $this->markTestSkipped( + 'JSON does not support NAN. It will be serialized to null '. + 'and as a result phpredis will store it as 0.' + ); + } + + $result = $repository->put('foo', NAN); + $this->assertTrue($result); + $this->assertNan($repository->get('foo')); + } + + /** + * @dataProvider extendedRedisConnectionDataProvider + */ + public function testItCanAdd($connection) + { + $repository = $this->getRepository($connection); + + $result = $repository->add('foo', 'test test test'); + $this->assertTrue($result); + $this->assertSame('test test test', $repository->get('foo')); + $result = $repository->forget('foo'); + $this->assertTrue($result); + } + + /** + * @dataProvider extendedRedisConnectionDataProvider + */ + public function testItCanAddWithTtl($connection) + { + $repository = $this->getRepository($connection); + + $result = $repository->add('foo', 'test test test', 10); + $this->assertTrue($result); + $this->assertSame('test test test', $repository->get('foo')); + $result = $repository->forget('foo'); + $this->assertTrue($result); } - public function testItCanStoreInfinite() + /** + * @dataProvider extendedRedisConnectionDataProvider + */ + public function testItCanPut($connection) { - Cache::store('redis')->clear(); + $repository = $this->getRepository($connection); - $result = Cache::store('redis')->put('foo', INF); + $result = $repository->put('foo', 'test test test'); + $this->assertTrue($result); + $this->assertSame('test test test', $repository->get('foo')); + $result = $repository->forget('foo'); $this->assertTrue($result); - $this->assertSame(INF, Cache::store('redis')->get('foo')); + } + + /** + * @dataProvider extendedRedisConnectionDataProvider + */ + public function testItCanPutWithTtl($connection) + { + $repository = $this->getRepository($connection); - $result = Cache::store('redis')->put('bar', -INF); + $result = $repository->put('foo', 'test test test', 10); + $this->assertTrue($result); + $this->assertSame('test test test', $repository->get('foo')); + $result = $repository->forget('foo'); $this->assertTrue($result); - $this->assertSame(-INF, Cache::store('redis')->get('bar')); } - public function testItCanStoreNan() + /** + * @dataProvider extendedRedisConnectionDataProvider + */ + public function testItCanPutMany($connection) { - Cache::store('redis')->clear(); + $repository = $this->getRepository($connection); - $result = Cache::store('redis')->put('foo', NAN); + $result = $repository->put([ + 'foo1' => 'test test test', + 'foo2' => 'best best best', + ], null); + $this->assertTrue($result); + $this->assertSame('test test test', $repository->get('foo1')); + $result = $repository->forget('foo1'); + $this->assertSame('best best best', $repository->get('foo2')); + $result = $repository->forget('foo2'); $this->assertTrue($result); - $this->assertNan(Cache::store('redis')->get('foo')); + } + + /** + * @dataProvider extendedRedisConnectionDataProvider + */ + public function testItCanPutManyWithTtl($connection) + { + $repository = $this->getRepository($connection); + + $result = $repository->put([ + 'foo1' => 'test test test', + 'foo2' => 'best best best', + ], 10); + $this->assertTrue($result); + $this->assertSame('test test test', $repository->get('foo1')); + $result = $repository->forget('foo1'); + $this->assertSame('best best best', $repository->get('foo2')); + $result = $repository->forget('foo2'); + $this->assertTrue($result); + } + + /** + * @dataProvider extendedRedisConnectionDataProvider + */ + public function testItCanGetMany($connection) + { + $repository = $this->getRepository($connection); + + $result = $repository->put([ + 'foo1' => 'test test test', + 'foo2' => 'best best best', + 'foo3' => 'this is the best test', + ], null); + $this->assertTrue($result); + $result = $repository->getMultiple(['foo1', 'foo2', 'foo3', 'foo4'], 'sure?'); + $this->assertIsArray($result); + $this->assertArrayHasKey('foo1', $result); + $this->assertArrayHasKey('foo2', $result); + $this->assertArrayHasKey('foo3', $result); + $this->assertArrayHasKey('foo4', $result); + $this->assertSame('test test test', $result['foo1']); + $this->assertSame('best best best', $result['foo2']); + $this->assertSame('this is the best test', $result['foo3']); + $this->assertSame('sure?', $result['foo4']); + $result = $repository->deleteMultiple(['foo1', 'foo2', 'foo3']); + $this->assertTrue($result); + } + + /** + * Builds a cache repository out of a predefined redis connection name. + * + * @param string $connection + * @return \Illuminate\Cache\Repository + */ + private function getRepository($connection) + { + /** @var \Illuminate\Cache\CacheManager $cacheManager */ + $cacheManager = $this->app->get('cache'); + + return $cacheManager->repository(new RedisStore($this->getRedisManager($connection))); } } diff --git a/tests/Integration/Http/ThrottleRequestsWithRedisTest.php b/tests/Integration/Http/ThrottleRequestsWithRedisTest.php index ef7a98b75401..a5a768c73938 100644 --- a/tests/Integration/Http/ThrottleRequestsWithRedisTest.php +++ b/tests/Integration/Http/ThrottleRequestsWithRedisTest.php @@ -15,8 +15,10 @@ class ThrottleRequestsWithRedisTest extends TestCase protected function tearDown(): void { + Carbon::setTestNow(false); + $this->tearDownRedis(); + parent::tearDown(); - Carbon::setTestNow(null); } public function getEnvironmentSetUp($app) @@ -24,38 +26,41 @@ public function getEnvironmentSetUp($app) $app['config']->set('hashing', ['driver' => 'bcrypt']); } - public function testLockOpensImmediatelyAfterDecay() + /** + * @dataProvider extendedRedisConnectionDataProvider + */ + public function testLockOpensImmediatelyAfterDecay($connection) { - $this->ifRedisAvailable(function () { - $now = Carbon::now(); - - Carbon::setTestNow($now); - - Route::get('/', function () { - return 'yes'; - })->middleware(ThrottleRequestsWithRedis::class.':2,1'); - - $response = $this->withoutExceptionHandling()->get('/'); - $this->assertSame('yes', $response->getContent()); - $this->assertEquals(2, $response->headers->get('X-RateLimit-Limit')); - $this->assertEquals(1, $response->headers->get('X-RateLimit-Remaining')); - - $response = $this->withoutExceptionHandling()->get('/'); - $this->assertSame('yes', $response->getContent()); - $this->assertEquals(2, $response->headers->get('X-RateLimit-Limit')); - $this->assertEquals(0, $response->headers->get('X-RateLimit-Remaining')); - - Carbon::setTestNow($finish = $now->addSeconds(58)); - - try { - $this->withoutExceptionHandling()->get('/'); - } catch (Throwable $e) { - $this->assertEquals(429, $e->getStatusCode()); - $this->assertEquals(2, $e->getHeaders()['X-RateLimit-Limit']); - $this->assertEquals(0, $e->getHeaders()['X-RateLimit-Remaining']); - // $this->assertTrue(in_array($e->getHeaders()['Retry-After'], [2, 3])); - // $this->assertTrue(in_array($e->getHeaders()['X-RateLimit-Reset'], [$finish->getTimestamp() + 2, $finish->getTimestamp() + 3])); - } - }); + $this->app['redis'] = $this->getRedisManager($connection); + + $now = Carbon::now(); + + Carbon::setTestNow($now); + + Route::get('/', function () { + return 'yes'; + })->middleware(ThrottleRequestsWithRedis::class.':2,1'); + + $response = $this->withoutExceptionHandling()->get('/'); + $this->assertSame('yes', $response->getContent()); + $this->assertEquals(2, $response->headers->get('X-RateLimit-Limit')); + $this->assertEquals(1, $response->headers->get('X-RateLimit-Remaining')); + + $response = $this->withoutExceptionHandling()->get('/'); + $this->assertSame('yes', $response->getContent()); + $this->assertEquals(2, $response->headers->get('X-RateLimit-Limit')); + $this->assertEquals(0, $response->headers->get('X-RateLimit-Remaining')); + + Carbon::setTestNow($finish = $now->addSeconds(58)); + + try { + $this->withoutExceptionHandling()->get('/'); + } catch (Throwable $e) { + $this->assertEquals(429, $e->getStatusCode()); + $this->assertEquals(2, $e->getHeaders()['X-RateLimit-Limit']); + $this->assertEquals(0, $e->getHeaders()['X-RateLimit-Remaining']); + // $this->assertTrue(in_array($e->getHeaders()['Retry-After'], [2, 3])); + // $this->assertTrue(in_array($e->getHeaders()['X-RateLimit-Reset'], [$finish->getTimestamp() + 2, $finish->getTimestamp() + 3])); + } } } diff --git a/tests/Integration/Queue/RateLimitedWithRedisTest.php b/tests/Integration/Queue/RateLimitedWithRedisTest.php index 768b3c2db9b0..ef5cf45828c8 100644 --- a/tests/Integration/Queue/RateLimitedWithRedisTest.php +++ b/tests/Integration/Queue/RateLimitedWithRedisTest.php @@ -13,31 +13,28 @@ use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\Middleware\RateLimitedWithRedis; use Illuminate\Support\Str; -use Mockery as m; +use Mockery; use Orchestra\Testbench\TestCase; class RateLimitedWithRedisTest extends TestCase { use InteractsWithRedis; - protected function setUp(): void - { - parent::setUp(); - - $this->setUpRedis(); - } - protected function tearDown(): void { - parent::tearDown(); - $this->tearDownRedis(); + Mockery::close(); - m::close(); + parent::tearDown(); } - public function testUnlimitedJobsAreExecuted() + /** + * @dataProvider extendedRedisConnectionDataProvider + */ + public function testUnlimitedJobsAreExecuted($connection) { + $this->app['redis'] = $this->getRedisManager($connection); + $rateLimiter = $this->app->make(RateLimiter::class); $testJob = new RedisRateLimitedTestJob; @@ -50,8 +47,13 @@ public function testUnlimitedJobsAreExecuted() $this->assertJobRanSuccessfully($testJob); } - public function testRateLimitedJobsAreNotExecutedOnLimitReached() + /** + * @dataProvider extendedRedisConnectionDataProvider + */ + public function testRateLimitedJobsAreNotExecutedOnLimitReached($connection) { + $this->app['redis'] = $this->getRedisManager($connection); + $rateLimiter = $this->app->make(RateLimiter::class); $testJob = new RedisRateLimitedTestJob; @@ -64,8 +66,13 @@ public function testRateLimitedJobsAreNotExecutedOnLimitReached() $this->assertJobWasReleased($testJob); } - public function testRateLimitedJobsCanBeSkippedOnLimitReached() + /** + * @dataProvider extendedRedisConnectionDataProvider + */ + public function testRateLimitedJobsCanBeSkippedOnLimitReached($connection) { + $this->app['redis'] = $this->getRedisManager($connection); + $rateLimiter = $this->app->make(RateLimiter::class); $testJob = new RedisRateLimitedDontReleaseTestJob; @@ -78,8 +85,13 @@ public function testRateLimitedJobsCanBeSkippedOnLimitReached() $this->assertJobWasSkipped($testJob); } - public function testJobsCanHaveConditionalRateLimits() + /** + * @dataProvider extendedRedisConnectionDataProvider + */ + public function testJobsCanHaveConditionalRateLimits($connection) { + $this->app['redis'] = $this->getRedisManager($connection); + $rateLimiter = $this->app->make(RateLimiter::class); $adminJob = new RedisAdminTestJob; @@ -109,8 +121,13 @@ public function testJobsCanHaveConditionalRateLimits() $this->assertJobWasReleased($nonAdminJob); } - public function testMiddlewareSerialization() + /** + * @dataProvider extendedRedisConnectionDataProvider + */ + public function testMiddlewareSerialization($connection) { + $this->app['redis'] = $this->getRedisManager($connection); + $rateLimited = new RateLimitedWithRedis('limiterName'); $rateLimited->shouldRelease = false; @@ -131,7 +148,7 @@ protected function assertJobRanSuccessfully($testJob) $testJob::$handled = false; $instance = new CallQueuedHandler(new Dispatcher($this->app), $this->app); - $job = m::mock(Job::class); + $job = Mockery::mock(Job::class); $job->shouldReceive('hasFailed')->once()->andReturn(false); $job->shouldReceive('isReleased')->andReturn(false); @@ -150,7 +167,7 @@ protected function assertJobWasReleased($testJob) $testJob::$handled = false; $instance = new CallQueuedHandler(new Dispatcher($this->app), $this->app); - $job = m::mock(Job::class); + $job = Mockery::mock(Job::class); $job->shouldReceive('hasFailed')->once()->andReturn(false); $job->shouldReceive('release')->once(); @@ -169,7 +186,7 @@ protected function assertJobWasSkipped($testJob) $testJob::$handled = false; $instance = new CallQueuedHandler(new Dispatcher($this->app), $this->app); - $job = m::mock(Job::class); + $job = Mockery::mock(Job::class); $job->shouldReceive('hasFailed')->once()->andReturn(false); $job->shouldReceive('isReleased')->andReturn(false); diff --git a/tests/Integration/Queue/ThrottlesExceptionsWithRedisTest.php b/tests/Integration/Queue/ThrottlesExceptionsWithRedisTest.php index f6d1146ff010..55fbb5a00749 100644 --- a/tests/Integration/Queue/ThrottlesExceptionsWithRedisTest.php +++ b/tests/Integration/Queue/ThrottlesExceptionsWithRedisTest.php @@ -11,45 +11,52 @@ use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\Middleware\ThrottlesExceptionsWithRedis; use Illuminate\Support\Str; -use Mockery as m; +use Mockery; use Orchestra\Testbench\TestCase; class ThrottlesExceptionsWithRedisTest extends TestCase { use InteractsWithRedis; - protected function setUp(): void - { - parent::setUp(); - - $this->setUpRedis(); - } - protected function tearDown(): void { - parent::tearDown(); - $this->tearDownRedis(); + Mockery::close(); - m::close(); + parent::tearDown(); } - public function testCircuitIsOpenedForJobErrors() + /** + * @dataProvider extendedRedisConnectionDataProvider + */ + public function testCircuitIsOpenedForJobErrors($connection) { + $this->app['redis'] = $this->getRedisManager($connection); + $this->assertJobWasReleasedImmediately(CircuitBreakerWithRedisTestJob::class, $key = Str::random()); $this->assertJobWasReleasedImmediately(CircuitBreakerWithRedisTestJob::class, $key); $this->assertJobWasReleasedWithDelay(CircuitBreakerWithRedisTestJob::class, $key); } - public function testCircuitStaysClosedForSuccessfulJobs() + /** + * @dataProvider extendedRedisConnectionDataProvider + */ + public function testCircuitStaysClosedForSuccessfulJobs($connection) { + $this->app['redis'] = $this->getRedisManager($connection); + $this->assertJobRanSuccessfully(CircuitBreakerWithRedisSuccessfulJob::class, $key = Str::random()); $this->assertJobRanSuccessfully(CircuitBreakerWithRedisSuccessfulJob::class, $key); $this->assertJobRanSuccessfully(CircuitBreakerWithRedisSuccessfulJob::class, $key); } - public function testCircuitResetsAfterSuccess() + /** + * @dataProvider extendedRedisConnectionDataProvider + */ + public function testCircuitResetsAfterSuccess($connection) { + $this->app['redis'] = $this->getRedisManager($connection); + $this->assertJobWasReleasedImmediately(CircuitBreakerWithRedisTestJob::class, $key = Str::random()); $this->assertJobRanSuccessfully(CircuitBreakerWithRedisSuccessfulJob::class, $key); $this->assertJobWasReleasedImmediately(CircuitBreakerWithRedisTestJob::class, $key); @@ -62,7 +69,7 @@ protected function assertJobWasReleasedImmediately($class, $key) $class::$handled = false; $instance = new CallQueuedHandler(new Dispatcher($this->app), $this->app); - $job = m::mock(Job::class); + $job = Mockery::mock(Job::class); $job->shouldReceive('hasFailed')->once()->andReturn(false); $job->shouldReceive('release')->with(0)->once(); @@ -81,7 +88,7 @@ protected function assertJobWasReleasedWithDelay($class, $key) $class::$handled = false; $instance = new CallQueuedHandler(new Dispatcher($this->app), $this->app); - $job = m::mock(Job::class); + $job = Mockery::mock(Job::class); $job->shouldReceive('hasFailed')->once()->andReturn(false); $job->shouldReceive('release')->withArgs(function ($delay) { @@ -102,7 +109,7 @@ protected function assertJobRanSuccessfully($class, $key) $class::$handled = false; $instance = new CallQueuedHandler(new Dispatcher($this->app), $this->app); - $job = m::mock(Job::class); + $job = Mockery::mock(Job::class); $job->shouldReceive('hasFailed')->once()->andReturn(false); $job->shouldReceive('isReleased')->andReturn(false); diff --git a/tests/Queue/DynamoDbFailedJobProviderTest.php b/tests/Queue/DynamoDbFailedJobProviderTest.php index 8ee85988a88d..279f70644aa7 100644 --- a/tests/Queue/DynamoDbFailedJobProviderTest.php +++ b/tests/Queue/DynamoDbFailedJobProviderTest.php @@ -17,6 +17,7 @@ class DynamoDbFailedJobProviderTest extends TestCase protected function tearDown(): void { m::close(); + Str::createUuidsNormally(); } public function testCanProperlyLogFailedJob() @@ -50,8 +51,6 @@ public function testCanProperlyLogFailedJob() $provider = new DynamoDbFailedJobProvider($dynamoDbClient, 'application', 'table'); $provider->log('connection', 'queue', json_encode(['uuid' => (string) $uuid]), $exception); - - Str::createUuidsNormally(); } public function testCanRetrieveAllFailedJobs() diff --git a/tests/Queue/QueueBeanstalkdQueueTest.php b/tests/Queue/QueueBeanstalkdQueueTest.php index 02195bc58ff5..c34fcbc36096 100755 --- a/tests/Queue/QueueBeanstalkdQueueTest.php +++ b/tests/Queue/QueueBeanstalkdQueueTest.php @@ -26,6 +26,7 @@ class QueueBeanstalkdQueueTest extends TestCase protected function tearDown(): void { m::close(); + Str::createUuidsNormally(); } public function testPushProperlyPushesJobOntoBeanstalkd() @@ -46,8 +47,6 @@ public function testPushProperlyPushesJobOntoBeanstalkd() $this->queue->push('foo', ['data']); $this->container->shouldHaveReceived('bound')->with('events')->times(2); - - Str::createUuidsNormally(); } public function testDelayedPushProperlyPushesJobOntoBeanstalkd() @@ -68,8 +67,6 @@ public function testDelayedPushProperlyPushesJobOntoBeanstalkd() $this->queue->later(5, 'foo', ['data']); $this->container->shouldHaveReceived('bound')->with('events')->times(2); - - Str::createUuidsNormally(); } public function testPopProperlyPopsJobOffOfBeanstalkd() diff --git a/tests/Queue/QueueDatabaseQueueUnitTest.php b/tests/Queue/QueueDatabaseQueueUnitTest.php index 118a38434ac1..9a6981638c90 100644 --- a/tests/Queue/QueueDatabaseQueueUnitTest.php +++ b/tests/Queue/QueueDatabaseQueueUnitTest.php @@ -17,6 +17,7 @@ class QueueDatabaseQueueUnitTest extends TestCase protected function tearDown(): void { m::close(); + Str::createUuidsNormally(); } public function testPushProperlyPushesJobOntoDatabase() @@ -42,8 +43,6 @@ public function testPushProperlyPushesJobOntoDatabase() $queue->push('foo', ['data']); $container->shouldHaveReceived('bound')->with('events')->once(); - - Str::createUuidsNormally(); } public function testDelayedPushProperlyPushesJobOntoDatabase() @@ -73,8 +72,6 @@ public function testDelayedPushProperlyPushesJobOntoDatabase() $queue->later(10, 'foo', ['data']); $container->shouldHaveReceived('bound')->with('events')->once(); - - Str::createUuidsNormally(); } public function testFailureToCreatePayloadFromObject() @@ -142,8 +139,6 @@ public function testBulkBatchPushesOntoDatabase() }); $queue->bulk(['foo', 'bar'], ['data'], 'queue'); - - Str::createUuidsNormally(); } public function testBuildDatabaseRecordWithPayloadAtTheEnd() diff --git a/tests/Queue/QueueRedisQueueTest.php b/tests/Queue/QueueRedisQueueTest.php index 442676de71ce..20c1e52afa97 100644 --- a/tests/Queue/QueueRedisQueueTest.php +++ b/tests/Queue/QueueRedisQueueTest.php @@ -17,6 +17,7 @@ class QueueRedisQueueTest extends TestCase protected function tearDown(): void { m::close(); + Str::createUuidsNormally(); } public function testPushProperlyPushesJobOntoRedis() @@ -36,8 +37,6 @@ public function testPushProperlyPushesJobOntoRedis() $id = $queue->push('foo', ['data']); $this->assertSame('foo', $id); $container->shouldHaveReceived('bound')->with('events')->once(); - - Str::createUuidsNormally(); } public function testPushProperlyPushesJobOntoRedisWithCustomPayloadHook() @@ -63,8 +62,6 @@ public function testPushProperlyPushesJobOntoRedisWithCustomPayloadHook() $container->shouldHaveReceived('bound')->with('events')->once(); Queue::createPayloadUsing(null); - - Str::createUuidsNormally(); } public function testPushProperlyPushesJobOntoRedisWithTwoCustomPayloadHook() @@ -94,8 +91,6 @@ public function testPushProperlyPushesJobOntoRedisWithTwoCustomPayloadHook() $container->shouldHaveReceived('bound')->with('events')->once(); Queue::createPayloadUsing(null); - - Str::createUuidsNormally(); } public function testDelayedPushProperlyPushesJobOntoRedis() @@ -121,8 +116,6 @@ public function testDelayedPushProperlyPushesJobOntoRedis() $id = $queue->later(1, 'foo', ['data']); $this->assertSame('foo', $id); $container->shouldHaveReceived('bound')->with('events')->once(); - - Str::createUuidsNormally(); } public function testDelayedPushWithDateTimeProperlyPushesJobOntoRedis() @@ -148,7 +141,5 @@ public function testDelayedPushWithDateTimeProperlyPushesJobOntoRedis() $queue->later($date, 'foo', ['data']); $container->shouldHaveReceived('bound')->with('events')->once(); - - Str::createUuidsNormally(); } } diff --git a/tests/Queue/RedisQueueIntegrationTest.php b/tests/Queue/RedisQueueIntegrationTest.php index 18f543492052..c7ab08afdc74 100644 --- a/tests/Queue/RedisQueueIntegrationTest.php +++ b/tests/Queue/RedisQueueIntegrationTest.php @@ -11,7 +11,7 @@ use Illuminate\Support\Carbon; use Illuminate\Support\InteractsWithTime; use Illuminate\Support\Str; -use Mockery as m; +use Mockery; use PHPUnit\Framework\TestCase; class RedisQueueIntegrationTest extends TestCase @@ -30,27 +30,29 @@ class RedisQueueIntegrationTest extends TestCase protected function setUp(): void { - Carbon::setTestNow(Carbon::now()); parent::setUp(); - $this->setUpRedis(); + + Carbon::setTestNow(Carbon::now()); } protected function tearDown(): void { - Carbon::setTestNow(null); - parent::tearDown(); $this->tearDownRedis(); - m::close(); + Carbon::setTestNow(false); + Mockery::close(); + Str::createUuidsNormally(); + + parent::tearDown(); } /** - * @dataProvider redisDriverProvider + * @dataProvider redisConnectionDataProvider * - * @param string $driver + * @param string $connection */ - public function testExpiredJobsArePopped($driver) + public function testExpiredJobsArePopped($connection) { - $this->setQueue($driver); + $this->setQueue($connection); $jobs = [ new RedisQueueIntegrationTestJob(0), @@ -71,30 +73,28 @@ public function testExpiredJobsArePopped($driver) $this->assertEquals($jobs[3], unserialize(json_decode($this->queue->pop()->getRawBody())->data->command)); $this->assertNull($this->queue->pop()); - $this->assertEquals(1, $this->redis[$driver]->connection()->zcard('queues:default:delayed')); - $this->assertEquals(3, $this->redis[$driver]->connection()->zcard('queues:default:reserved')); + $this->assertEquals(1, $this->getRedisManager($connection)->connection()->zcard('queues:default:delayed')); + $this->assertEquals(3, $this->getRedisManager($connection)->connection()->zcard('queues:default:reserved')); } /** - * @dataProvider redisDriverProvider + * @dataProvider redisConnectionDataProvider * @requires extension pcntl * - * @param mixed $driver + * @param mixed $connection * * @throws \Exception */ - public function testBlockingPop($driver) + public function testBlockingPop($connection) { $this->tearDownRedis(); if ($pid = pcntl_fork() > 0) { - $this->setUpRedis(); - $this->setQueue($driver, 'default', null, 60, 10); + $this->setQueue($connection, 'default', null, 60, 10); $this->assertEquals(12, unserialize(json_decode($this->queue->pop()->getRawBody())->data->command)->i); } elseif ($pid == 0) { - $this->setUpRedis(); $this->setQueue('phpredis'); - sleep(1); + usleep(1100000); $this->queue->push(new RedisQueueIntegrationTestJob(12)); exit; } else { @@ -103,30 +103,30 @@ public function testBlockingPop($driver) } /** - * @dataProvider redisDriverProvider + * @dataProvider redisConnectionDataProvider * - * @param string $driver + * @param string $connection */ - public function testMigrateMoreThan100Jobs($driver) + public function testMigrateMoreThan100Jobs($connection) { - $this->setQueue($driver); + $this->setQueue($connection); for ($i = -1; $i >= -201; $i--) { $this->queue->later($i, new RedisQueueIntegrationTestJob($i)); } for ($i = -201; $i <= -1; $i++) { $this->assertEquals($i, unserialize(json_decode($this->queue->pop()->getRawBody())->data->command)->i); - $this->assertEquals(-$i - 1, $this->redis[$driver]->llen('queues:default:notify')); + $this->assertEquals(-$i - 1, $this->getRedisManager($connection)->llen('queues:default:notify')); } } /** - * @dataProvider redisDriverProvider + * @dataProvider redisConnectionDataProvider * - * @param string $driver + * @param string $connection */ - public function testPopProperlyPopsJobOffOfRedis($driver) + public function testPopProperlyPopsJobOffOfRedis($connection) { - $this->setQueue($driver); + $this->setQueue($connection); // Push an item into queue $job = new RedisQueueIntegrationTestJob(10); @@ -145,8 +145,8 @@ public function testPopProperlyPopsJobOffOfRedis($driver) $this->assertEquals($redisJob->getJobId(), json_decode($redisJob->getReservedJob())->id); // Check reserved queue - $this->assertEquals(1, $this->redis[$driver]->connection()->zcard('queues:default:reserved')); - $result = $this->redis[$driver]->connection()->zrangebyscore('queues:default:reserved', -INF, INF, ['withscores' => true]); + $this->assertEquals(1, $this->getRedisManager($connection)->connection()->zcard('queues:default:reserved')); + $result = $this->getRedisManager($connection)->connection()->zrangebyscore('queues:default:reserved', -INF, INF, ['withscores' => true]); $reservedJob = array_keys($result)[0]; $score = $result[$reservedJob]; $this->assertLessThanOrEqual($score, $before + 60); @@ -155,13 +155,13 @@ public function testPopProperlyPopsJobOffOfRedis($driver) } /** - * @dataProvider redisDriverProvider + * @dataProvider redisConnectionDataProvider * - * @param string $driver + * @param string $connection */ - public function testPopProperlyPopsDelayedJobOffOfRedis($driver) + public function testPopProperlyPopsDelayedJobOffOfRedis($connection) { - $this->setQueue($driver); + $this->setQueue($connection); // Push an item into queue $job = new RedisQueueIntegrationTestJob(10); $this->queue->later(-10, $job); @@ -172,8 +172,8 @@ public function testPopProperlyPopsDelayedJobOffOfRedis($driver) $after = $this->currentTime(); // Check reserved queue - $this->assertEquals(1, $this->redis[$driver]->connection()->zcard('queues:default:reserved')); - $result = $this->redis[$driver]->connection()->zrangebyscore('queues:default:reserved', -INF, INF, ['withscores' => true]); + $this->assertEquals(1, $this->getRedisManager($connection)->connection()->zcard('queues:default:reserved')); + $result = $this->getRedisManager($connection)->connection()->zrangebyscore('queues:default:reserved', -INF, INF, ['withscores' => true]); $reservedJob = array_keys($result)[0]; $score = $result[$reservedJob]; $this->assertLessThanOrEqual($score, $before + 60); @@ -182,13 +182,13 @@ public function testPopProperlyPopsDelayedJobOffOfRedis($driver) } /** - * @dataProvider redisDriverProvider + * @dataProvider redisConnectionDataProvider * - * @param string $driver + * @param string $connection */ - public function testPopPopsDelayedJobOffOfRedisWhenExpireNull($driver) + public function testPopPopsDelayedJobOffOfRedisWhenExpireNull($connection) { - $this->setQueue($driver, 'default', null, null); + $this->setQueue($connection, 'default', null, null); // Push an item into queue $job = new RedisQueueIntegrationTestJob(10); @@ -202,8 +202,8 @@ public function testPopPopsDelayedJobOffOfRedisWhenExpireNull($driver) $after = $this->currentTime(); // Check reserved queue - $this->assertEquals(1, $this->redis[$driver]->connection()->zcard('queues:default:reserved')); - $result = $this->redis[$driver]->connection()->zrangebyscore('queues:default:reserved', -INF, INF, ['withscores' => true]); + $this->assertEquals(1, $this->getRedisManager($connection)->connection()->zcard('queues:default:reserved')); + $result = $this->getRedisManager($connection)->connection()->zrangebyscore('queues:default:reserved', -INF, INF, ['withscores' => true]); $reservedJob = array_keys($result)[0]; $score = $result[$reservedJob]; $this->assertLessThanOrEqual($score, $before); @@ -212,13 +212,13 @@ public function testPopPopsDelayedJobOffOfRedisWhenExpireNull($driver) } /** - * @dataProvider redisDriverProvider + * @dataProvider redisConnectionDataProvider * - * @param string $driver + * @param string $connection */ - public function testBlockingPopProperlyPopsJobOffOfRedis($driver) + public function testBlockingPopProperlyPopsJobOffOfRedis($connection) { - $this->setQueue($driver, 'default', null, 60, 5); + $this->setQueue($connection, 'default', null, 60, 5); // Push an item into queue $job = new RedisQueueIntegrationTestJob(10); @@ -233,17 +233,17 @@ public function testBlockingPopProperlyPopsJobOffOfRedis($driver) } /** - * @dataProvider redisDriverProvider + * @dataProvider redisConnectionDataProvider * - * @param string $driver + * @param string $connection */ - public function testBlockingPopProperlyPopsExpiredJobs($driver) + public function testBlockingPopProperlyPopsExpiredJobs($connection) { Str::createUuidsUsing(function () { return 'uuid'; }); - $this->setQueue($driver, 'default', null, 60, 5); + $this->setQueue($connection, 'default', null, 60, 5); $jobs = [ new RedisQueueIntegrationTestJob(0), @@ -256,21 +256,19 @@ public function testBlockingPopProperlyPopsExpiredJobs($driver) $this->assertEquals($jobs[0], unserialize(json_decode($this->queue->pop()->getRawBody())->data->command)); $this->assertEquals($jobs[1], unserialize(json_decode($this->queue->pop()->getRawBody())->data->command)); - $this->assertEquals(0, $this->redis[$driver]->connection()->llen('queues:default:notify')); - $this->assertEquals(0, $this->redis[$driver]->connection()->zcard('queues:default:delayed')); - $this->assertEquals(2, $this->redis[$driver]->connection()->zcard('queues:default:reserved')); - - Str::createUuidsNormally(); + $this->assertEquals(0, $this->getRedisManager($connection)->connection()->llen('queues:default:notify')); + $this->assertEquals(0, $this->getRedisManager($connection)->connection()->zcard('queues:default:delayed')); + $this->assertEquals(2, $this->getRedisManager($connection)->connection()->zcard('queues:default:reserved')); } /** - * @dataProvider redisDriverProvider + * @dataProvider redisConnectionDataProvider * - * @param string $driver + * @param string $connection */ - public function testNotExpireJobsWhenExpireNull($driver) + public function testNotExpireJobsWhenExpireNull($connection) { - $this->setQueue($driver, 'default', null, null); + $this->setQueue($connection, 'default', null, null); // Make an expired reserved job $failed = new RedisQueueIntegrationTestJob(-20); @@ -292,8 +290,8 @@ public function testNotExpireJobsWhenExpireNull($driver) $after = $this->currentTime(); // Check reserved queue - $this->assertEquals(2, $this->redis[$driver]->connection()->zcard('queues:default:reserved')); - $result = $this->redis[$driver]->connection()->zrangebyscore('queues:default:reserved', -INF, INF, ['withscores' => true]); + $this->assertEquals(2, $this->getRedisManager($connection)->connection()->zcard('queues:default:reserved')); + $result = $this->getRedisManager($connection)->connection()->zrangebyscore('queues:default:reserved', -INF, INF, ['withscores' => true]); foreach ($result as $payload => $score) { $command = unserialize(json_decode($payload)->data->command); @@ -311,13 +309,13 @@ public function testNotExpireJobsWhenExpireNull($driver) } /** - * @dataProvider redisDriverProvider + * @dataProvider redisConnectionDataProvider * - * @param string $driver + * @param string $connection */ - public function testExpireJobsWhenExpireSet($driver) + public function testExpireJobsWhenExpireSet($connection) { - $this->setQueue($driver, 'default', null, 30); + $this->setQueue($connection, 'default', null, 30); // Push an item into queue $job = new RedisQueueIntegrationTestJob(10); @@ -330,8 +328,8 @@ public function testExpireJobsWhenExpireSet($driver) $after = $this->currentTime(); // Check reserved queue - $this->assertEquals(1, $this->redis[$driver]->connection()->zcard('queues:default:reserved')); - $result = $this->redis[$driver]->connection()->zrangebyscore('queues:default:reserved', -INF, INF, ['withscores' => true]); + $this->assertEquals(1, $this->getRedisManager($connection)->connection()->zcard('queues:default:reserved')); + $result = $this->getRedisManager($connection)->connection()->zrangebyscore('queues:default:reserved', -INF, INF, ['withscores' => true]); $reservedJob = array_keys($result)[0]; $score = $result[$reservedJob]; $this->assertLessThanOrEqual($score, $before + 30); @@ -340,13 +338,13 @@ public function testExpireJobsWhenExpireSet($driver) } /** - * @dataProvider redisDriverProvider + * @dataProvider redisConnectionDataProvider * - * @param string $driver + * @param string $connection */ - public function testRelease($driver) + public function testRelease($connection) { - $this->setQueue($driver); + $this->setQueue($connection); // push a job into queue $job = new RedisQueueIntegrationTestJob(30); @@ -360,9 +358,9 @@ public function testRelease($driver) $after = $this->currentTime(); // check the content of delayed queue - $this->assertEquals(1, $this->redis[$driver]->connection()->zcard('queues:default:delayed')); + $this->assertEquals(1, $this->getRedisManager($connection)->connection()->zcard('queues:default:delayed')); - $results = $this->redis[$driver]->connection()->zrangebyscore('queues:default:delayed', -INF, INF, ['withscores' => true]); + $results = $this->getRedisManager($connection)->connection()->zrangebyscore('queues:default:delayed', -INF, INF, ['withscores' => true]); $payload = array_keys($results)[0]; @@ -381,13 +379,13 @@ public function testRelease($driver) } /** - * @dataProvider redisDriverProvider + * @dataProvider redisConnectionDataProvider * - * @param string $driver + * @param string $connection */ - public function testReleaseInThePast($driver) + public function testReleaseInThePast($connection) { - $this->setQueue($driver); + $this->setQueue($connection); $job = new RedisQueueIntegrationTestJob(30); $this->queue->push($job); @@ -399,13 +397,13 @@ public function testReleaseInThePast($driver) } /** - * @dataProvider redisDriverProvider + * @dataProvider redisConnectionDataProvider * - * @param string $driver + * @param string $connection */ - public function testDelete($driver) + public function testDelete($connection) { - $this->setQueue($driver); + $this->setQueue($connection); $job = new RedisQueueIntegrationTestJob(30); $this->queue->push($job); @@ -415,21 +413,21 @@ public function testDelete($driver) $redisJob->delete(); - $this->assertEquals(0, $this->redis[$driver]->connection()->zcard('queues:default:delayed')); - $this->assertEquals(0, $this->redis[$driver]->connection()->zcard('queues:default:reserved')); - $this->assertEquals(0, $this->redis[$driver]->connection()->llen('queues:default')); + $this->assertEquals(0, $this->getRedisManager($connection)->connection()->zcard('queues:default:delayed')); + $this->assertEquals(0, $this->getRedisManager($connection)->connection()->zcard('queues:default:reserved')); + $this->assertEquals(0, $this->getRedisManager($connection)->connection()->llen('queues:default')); $this->assertNull($this->queue->pop()); } /** - * @dataProvider redisDriverProvider + * @dataProvider redisConnectionDataProvider * - * @param string $driver + * @param string $connection */ - public function testClear($driver) + public function testClear($connection) { - $this->setQueue($driver); + $this->setQueue($connection); $job1 = new RedisQueueIntegrationTestJob(30); $job2 = new RedisQueueIntegrationTestJob(40); @@ -439,17 +437,17 @@ public function testClear($driver) $this->assertEquals(2, $this->queue->clear(null)); $this->assertEquals(0, $this->queue->size()); - $this->assertEquals(0, $this->redis[$driver]->connection()->llen('queues:default:notify')); + $this->assertEquals(0, $this->getRedisManager($connection)->connection()->llen('queues:default:notify')); } /** - * @dataProvider redisDriverProvider + * @dataProvider redisConnectionDataProvider * - * @param string $driver + * @param string $connection */ - public function testSize($driver) + public function testSize($connection) { - $this->setQueue($driver); + $this->setQueue($connection); $this->assertEquals(0, $this->queue->size()); $this->queue->push(new RedisQueueIntegrationTestJob(1)); $this->assertEquals(1, $this->queue->size()); @@ -464,13 +462,13 @@ public function testSize($driver) } /** - * @dataProvider redisDriverProvider + * @dataProvider redisConnectionDataProvider * - * @param string $driver + * @param string $connection */ - public function testPushJobQueuedEvent($driver) + public function testPushJobQueuedEvent($connection) { - $events = m::mock(Dispatcher::class); + $events = Mockery::mock(Dispatcher::class); $events->shouldReceive('dispatch')->withArgs(function (JobQueued $jobQueued) { $this->assertInstanceOf(RedisQueueIntegrationTestJob::class, $jobQueued->job); $this->assertIsString(RedisQueueIntegrationTestJob::class, $jobQueued->id); @@ -478,31 +476,31 @@ public function testPushJobQueuedEvent($driver) return true; })->andReturnNull()->once(); - $container = m::mock(Container::class); + $container = Mockery::mock(Container::class); $container->shouldReceive('bound')->with('events')->andReturn(true)->once(); $container->shouldReceive('offsetGet')->with('events')->andReturn($events)->once(); - $queue = new RedisQueue($this->redis[$driver]); + $queue = new RedisQueue($this->getRedisManager($connection)); $queue->setContainer($container); $queue->push(new RedisQueueIntegrationTestJob(5)); } /** - * @dataProvider redisDriverProvider + * @dataProvider redisConnectionDataProvider * - * @param string $driver + * @param string $connection */ - public function testBulkJobQueuedEvent($driver) + public function testBulkJobQueuedEvent($connection) { - $events = m::mock(Dispatcher::class); - $events->shouldReceive('dispatch')->with(m::type(JobQueued::class))->andReturnNull()->times(3); + $events = Mockery::mock(Dispatcher::class); + $events->shouldReceive('dispatch')->with(Mockery::type(JobQueued::class))->andReturnNull()->times(3); - $container = m::mock(Container::class); + $container = Mockery::mock(Container::class); $container->shouldReceive('bound')->with('events')->andReturn(true)->times(3); $container->shouldReceive('offsetGet')->with('events')->andReturn($events)->times(3); - $queue = new RedisQueue($this->redis[$driver]); + $queue = new RedisQueue($this->getRedisManager($connection)); $queue->setContainer($container); $queue->bulk([ @@ -519,10 +517,10 @@ public function testBulkJobQueuedEvent($driver) * @param int $retryAfter * @param int|null $blockFor */ - private function setQueue($driver, $default = 'default', $connection = null, $retryAfter = 60, $blockFor = null) + private function setQueue($redisConnection, $default = 'default', $connection = null, $retryAfter = 60, $blockFor = null) { - $this->queue = new RedisQueue($this->redis[$driver], $default, $connection, $retryAfter, $blockFor); - $this->container = m::spy(Container::class); + $this->queue = new RedisQueue($this->getRedisManager($redisConnection), $default, $connection, $retryAfter, $blockFor); + $this->container = Mockery::spy(Container::class); $this->queue->setContainer($this->container); } } diff --git a/tests/Redis/ConcurrentLimiterTest.php b/tests/Redis/ConcurrentLimiterTest.php index 22d5d0f385c7..7f8acb613de4 100644 --- a/tests/Redis/ConcurrentLimiterTest.php +++ b/tests/Redis/ConcurrentLimiterTest.php @@ -13,13 +13,6 @@ class ConcurrentLimiterTest extends TestCase { use InteractsWithRedis; - protected function setUp(): void - { - parent::setUp(); - - $this->setUpRedis(); - } - protected function tearDown(): void { parent::tearDown(); @@ -27,37 +20,43 @@ protected function tearDown(): void $this->tearDownRedis(); } - public function testItLocksTasksWhenNoSlotAvailable() + /** + * @dataProvider redisConnectionDataProvider + */ + public function testItLocksTasksWhenNoSlotAvailable($connection) { $store = []; foreach (range(1, 2) as $i) { - (new ConcurrencyLimiterMockThatDoesntRelease($this->redis(), 'key', 2, 5))->block(2, function () use (&$store, $i) { + (new ConcurrencyLimiterMockThatDoesntRelease($this->redis($connection), 'key', 2, 5))->block(2, function () use (&$store, $i) { $store[] = $i; }); } try { - (new ConcurrencyLimiterMockThatDoesntRelease($this->redis(), 'key', 2, 5))->block(0, function () use (&$store) { + (new ConcurrencyLimiterMockThatDoesntRelease($this->redis($connection), 'key', 2, 5))->block(0, function () use (&$store) { $store[] = 3; }); } catch (Throwable $e) { $this->assertInstanceOf(LimiterTimeoutException::class, $e); } - (new ConcurrencyLimiterMockThatDoesntRelease($this->redis(), 'other_key', 2, 5))->block(2, function () use (&$store) { + (new ConcurrencyLimiterMockThatDoesntRelease($this->redis($connection), 'other_key', 2, 5))->block(2, function () use (&$store) { $store[] = 4; }); $this->assertEquals([1, 2, 4], $store); } - public function testItReleasesLockAfterTaskFinishes() + /** + * @dataProvider redisConnectionDataProvider + */ + public function testItReleasesLockAfterTaskFinishes($connection) { $store = []; foreach (range(1, 4) as $i) { - (new ConcurrencyLimiter($this->redis(), 'key', 2, 5))->block(2, function () use (&$store, $i) { + (new ConcurrencyLimiter($this->redis($connection), 'key', 2, 5))->block(2, function () use (&$store, $i) { $store[] = $i; }); } @@ -65,11 +64,14 @@ public function testItReleasesLockAfterTaskFinishes() $this->assertEquals([1, 2, 3, 4], $store); } - public function testItReleasesLockIfTaskTookTooLong() + /** + * @dataProvider redisConnectionDataProvider + */ + public function testItReleasesLockIfTaskTookTooLong($connection) { $store = []; - $lock = (new ConcurrencyLimiterMockThatDoesntRelease($this->redis(), 'key', 1, 1)); + $lock = (new ConcurrencyLimiterMockThatDoesntRelease($this->redis($connection), 'key', 1, 1)); $lock->block(2, function () use (&$store) { $store[] = 1; @@ -83,7 +85,7 @@ public function testItReleasesLockIfTaskTookTooLong() $this->assertInstanceOf(LimiterTimeoutException::class, $e); } - usleep(1.2 * 1000000); + usleep(1100000); $lock->block(0, function () use (&$store) { $store[] = 3; @@ -92,11 +94,14 @@ public function testItReleasesLockIfTaskTookTooLong() $this->assertEquals([1, 3], $store); } - public function testItFailsImmediatelyOrRetriesForAWhileBasedOnAGivenTimeout() + /** + * @dataProvider redisConnectionDataProvider + */ + public function testItFailsImmediatelyOrRetriesForAWhileBasedOnAGivenTimeout($connection) { $store = []; - $lock = (new ConcurrencyLimiterMockThatDoesntRelease($this->redis(), 'key', 1, 2)); + $lock = (new ConcurrencyLimiterMockThatDoesntRelease($this->redis($connection), 'key', 1, 2)); $lock->block(2, function () use (&$store) { $store[] = 1; @@ -117,11 +122,14 @@ public function testItFailsImmediatelyOrRetriesForAWhileBasedOnAGivenTimeout() $this->assertEquals([1, 3], $store); } - public function testItFailsAfterRetryTimeout() + /** + * @dataProvider redisConnectionDataProvider + */ + public function testItFailsAfterRetryTimeout($connection) { $store = []; - $lock = (new ConcurrencyLimiterMockThatDoesntRelease($this->redis(), 'key', 1, 10)); + $lock = (new ConcurrencyLimiterMockThatDoesntRelease($this->redis($connection), 'key', 1, 10)); $lock->block(2, function () use (&$store) { $store[] = 1; @@ -138,11 +146,14 @@ public function testItFailsAfterRetryTimeout() $this->assertEquals([1], $store); } - public function testItReleasesIfErrorIsThrown() + /** + * @dataProvider redisConnectionDataProvider + */ + public function testItReleasesIfErrorIsThrown($connection) { $store = []; - $lock = new ConcurrencyLimiter($this->redis(), 'key', 1, 5); + $lock = new ConcurrencyLimiter($this->redis($connection), 'key', 1, 5); try { $lock->block(1, function () { @@ -151,7 +162,7 @@ public function testItReleasesIfErrorIsThrown() } catch (Error $e) { } - $lock = new ConcurrencyLimiter($this->redis(), 'key', 1, 5); + $lock = new ConcurrencyLimiter($this->redis($connection), 'key', 1, 5); $lock->block(1, function () use (&$store) { $store[] = 1; }); @@ -159,9 +170,9 @@ public function testItReleasesIfErrorIsThrown() $this->assertEquals([1], $store); } - private function redis() + private function redis($connection) { - return $this->redis['phpredis']->connection(); + return $this->getRedisManager($connection)->connection(); } } diff --git a/tests/Redis/DurationLimiterTest.php b/tests/Redis/DurationLimiterTest.php index 32539958b0db..ebf630fa7079 100644 --- a/tests/Redis/DurationLimiterTest.php +++ b/tests/Redis/DurationLimiterTest.php @@ -12,13 +12,6 @@ class DurationLimiterTest extends TestCase { use InteractsWithRedis; - protected function setUp(): void - { - parent::setUp(); - - $this->setUpRedis(); - } - protected function tearDown(): void { parent::tearDown(); @@ -26,20 +19,23 @@ protected function tearDown(): void $this->tearDownRedis(); } - public function testItLocksTasksWhenNoSlotAvailable() + /** + * @dataProvider redisConnectionDataProvider + */ + public function testItLocksTasksWhenNoSlotAvailable($connection) { $store = []; - (new DurationLimiter($this->redis(), 'key', 2, 2))->block(0, function () use (&$store) { + (new DurationLimiter($this->redis($connection), 'key', 2, 2))->block(0, function () use (&$store) { $store[] = 1; }); - (new DurationLimiter($this->redis(), 'key', 2, 2))->block(0, function () use (&$store) { + (new DurationLimiter($this->redis($connection), 'key', 2, 2))->block(0, function () use (&$store) { $store[] = 2; }); try { - (new DurationLimiter($this->redis(), 'key', 2, 2))->block(0, function () use (&$store) { + (new DurationLimiter($this->redis($connection), 'key', 2, 2))->block(0, function () use (&$store) { $store[] = 3; }); } catch (Throwable $e) { @@ -50,39 +46,45 @@ public function testItLocksTasksWhenNoSlotAvailable() sleep(2); - (new DurationLimiter($this->redis(), 'key', 2, 2))->block(0, function () use (&$store) { + (new DurationLimiter($this->redis($connection), 'key', 2, 2))->block(0, function () use (&$store) { $store[] = 3; }); $this->assertEquals([1, 2, 3], $store); } - public function testItFailsImmediatelyOrRetriesForAWhileBasedOnAGivenTimeout() + /** + * @dataProvider redisConnectionDataProvider + */ + public function testItFailsImmediatelyOrRetriesForAWhileBasedOnAGivenTimeout($connection) { $store = []; - (new DurationLimiter($this->redis(), 'key', 1, 1))->block(2, function () use (&$store) { + (new DurationLimiter($this->redis($connection), 'key', 1, 1))->block(2, function () use (&$store) { $store[] = 1; }); try { - (new DurationLimiter($this->redis(), 'key', 1, 1))->block(0, function () use (&$store) { + (new DurationLimiter($this->redis($connection), 'key', 1, 1))->block(0, function () use (&$store) { $store[] = 2; }); } catch (Throwable $e) { $this->assertInstanceOf(LimiterTimeoutException::class, $e); } - (new DurationLimiter($this->redis(), 'key', 1, 1))->block(2, function () use (&$store) { + (new DurationLimiter($this->redis($connection), 'key', 1, 1))->block(2, function () use (&$store) { $store[] = 3; }); $this->assertEquals([1, 3], $store); } - public function testItReturnsTheCallbackResult() + /** + * @dataProvider redisConnectionDataProvider + */ + public function testItReturnsTheCallbackResult($connection) { - $limiter = new DurationLimiter($this->redis(), 'key', 1, 1); + $limiter = new DurationLimiter($this->redis($connection), 'key', 1, 1); $result = $limiter->block(1, function () { return 'foo'; @@ -91,8 +93,8 @@ public function testItReturnsTheCallbackResult() $this->assertSame('foo', $result); } - private function redis() + private function redis($connection) { - return $this->redis['phpredis']->connection(); + return $this->getRedisManager($connection)->connection(); } } diff --git a/tests/Redis/RedisConnectionTest.php b/tests/Redis/RedisConnectionTest.php index a89ebd2d4fc4..f2e3c00ecad0 100644 --- a/tests/Redis/RedisConnectionTest.php +++ b/tests/Redis/RedisConnectionTest.php @@ -3,575 +3,599 @@ namespace Illuminate\Tests\Redis; use Illuminate\Contracts\Events\Dispatcher; -use Illuminate\Foundation\Application; use Illuminate\Foundation\Testing\Concerns\InteractsWithRedis; use Illuminate\Redis\Connections\Connection; use Illuminate\Redis\Connections\PhpRedisConnection; -use Illuminate\Redis\RedisManager; -use Mockery as m; +use Mockery; use PHPUnit\Framework\TestCase; -use Predis\Client; use Redis; class RedisConnectionTest extends TestCase { use InteractsWithRedis; - protected function setUp(): void - { - parent::setUp(); - $this->setUpRedis(); - } - protected function tearDown(): void { - parent::tearDown(); - $this->tearDownRedis(); + Mockery::close(); - m::close(); + parent::tearDown(); } - public function testItSetsValuesWithExpiry() + /** + * @dataProvider extendedRedisConnectionDataProvider + */ + public function testItSetsValuesWithExpiry($connection) { - foreach ($this->connections() as $redis) { - $redis->set('one', 'mohamed', 'EX', 5, 'NX'); - $this->assertSame('mohamed', $redis->get('one')); - $this->assertNotEquals(-1, $redis->ttl('one')); + $redis = $this->getRedisManager($connection); - // It doesn't override when NX mode - $redis->set('one', 'taylor', 'EX', 5, 'NX'); - $this->assertSame('mohamed', $redis->get('one')); + $redis->set('one', 'mohamed', 'EX', 5, 'NX'); + $this->assertSame('mohamed', $redis->get('one')); + $this->assertNotEquals(-1, $redis->ttl('one')); - // It overrides when XX mode - $redis->set('one', 'taylor', 'EX', 5, 'XX'); - $this->assertSame('taylor', $redis->get('one')); + // It doesn't override when NX mode + $redis->set('one', 'taylor', 'EX', 5, 'NX'); + $this->assertSame('mohamed', $redis->get('one')); - // It fails if XX mode is on and key doesn't exist - $redis->set('two', 'taylor', 'PX', 5, 'XX'); - $this->assertNull($redis->get('two')); + // It overrides when XX mode + $redis->set('one', 'taylor', 'EX', 5, 'XX'); + $this->assertSame('taylor', $redis->get('one')); - $redis->set('three', 'mohamed', 'PX', 5000); - $this->assertSame('mohamed', $redis->get('three')); - $this->assertNotEquals(-1, $redis->ttl('three')); - $this->assertNotEquals(-1, $redis->pttl('three')); + // It fails if XX mode is on and key doesn't exist + $redis->set('two', 'taylor', 'PX', 5, 'XX'); + $this->assertNull($redis->get('two')); - $redis->flushall(); - } + $redis->set('three', 'mohamed', 'PX', 5000); + $this->assertSame('mohamed', $redis->get('three')); + $this->assertNotEquals(-1, $redis->ttl('three')); + $this->assertNotEquals(-1, $redis->pttl('three')); } - public function testItDeletesKeys() + /** + * @dataProvider extendedRedisConnectionDataProvider + */ + public function testItDeletesKeys($connection) { - foreach ($this->connections() as $redis) { - $redis->set('one', 'mohamed'); - $redis->set('two', 'mohamed'); - $redis->set('three', 'mohamed'); + $redis = $this->getRedisManager($connection); - $redis->del('one'); - $this->assertNull($redis->get('one')); - $this->assertNotNull($redis->get('two')); - $this->assertNotNull($redis->get('three')); + $redis->set('one', 'mohamed'); + $redis->set('two', 'mohamed'); + $redis->set('three', 'mohamed'); - $redis->del('two', 'three'); - $this->assertNull($redis->get('two')); - $this->assertNull($redis->get('three')); + $redis->del('one'); + $this->assertNull($redis->get('one')); + $this->assertNotNull($redis->get('two')); + $this->assertNotNull($redis->get('three')); - $redis->flushall(); - } + $redis->del('two', 'three'); + $this->assertNull($redis->get('two')); + $this->assertNull($redis->get('three')); } - public function testItChecksForExistence() + /** + * @dataProvider extendedRedisConnectionDataProvider + */ + public function testItChecksForExistence($connection) { - foreach ($this->connections() as $redis) { - $redis->set('one', 'mohamed'); - $redis->set('two', 'mohamed'); + $redis = $this->getRedisManager($connection); - $this->assertEquals(1, $redis->exists('one')); - $this->assertEquals(0, $redis->exists('nothing')); - $this->assertEquals(2, $redis->exists('one', 'two')); - $this->assertEquals(2, $redis->exists('one', 'two', 'nothing')); + $redis->set('one', 'mohamed'); + $redis->set('two', 'mohamed'); - $redis->flushall(); - } + $this->assertEquals(1, $redis->exists('one')); + $this->assertEquals(0, $redis->exists('nothing')); + $this->assertEquals(2, $redis->exists('one', 'two')); + $this->assertEquals(2, $redis->exists('one', 'two', 'nothing')); } - public function testItExpiresKeys() + /** + * @dataProvider extendedRedisConnectionDataProvider + */ + public function testItExpiresKeys($connection) { - foreach ($this->connections() as $redis) { - $redis->set('one', 'mohamed'); - $this->assertEquals(-1, $redis->ttl('one')); - $this->assertEquals(1, $redis->expire('one', 10)); - $this->assertNotEquals(-1, $redis->ttl('one')); + $redis = $this->getRedisManager($connection); - $this->assertEquals(0, $redis->expire('nothing', 10)); + $redis->set('one', 'mohamed'); + $this->assertEquals(-1, $redis->ttl('one')); + $this->assertEquals(1, $redis->expire('one', 10)); + $this->assertNotEquals(-1, $redis->ttl('one')); - $redis->set('two', 'mohamed'); - $this->assertEquals(-1, $redis->ttl('two')); - $this->assertEquals(1, $redis->pexpire('two', 10)); - $this->assertNotEquals(-1, $redis->pttl('two')); + $this->assertEquals(0, $redis->expire('nothing', 10)); - $this->assertEquals(0, $redis->pexpire('nothing', 10)); + $redis->set('two', 'mohamed'); + $this->assertEquals(-1, $redis->ttl('two')); + $this->assertEquals(1, $redis->pexpire('two', 10)); + $this->assertNotEquals(-1, $redis->pttl('two')); - $redis->flushall(); - } + $this->assertEquals(0, $redis->pexpire('nothing', 10)); } - public function testItRenamesKeys() + /** + * @dataProvider extendedRedisConnectionDataProvider + */ + public function testItRenamesKeys($connection) { - foreach ($this->connections() as $redis) { - $redis->set('one', 'mohamed'); - $redis->rename('one', 'two'); - $this->assertNull($redis->get('one')); - $this->assertSame('mohamed', $redis->get('two')); + $redis = $this->getRedisManager($connection); - $redis->set('three', 'adam'); - $redis->renamenx('two', 'three'); - $this->assertSame('mohamed', $redis->get('two')); - $this->assertSame('adam', $redis->get('three')); + $redis->set('one', 'mohamed'); + $redis->rename('one', 'two'); + $this->assertNull($redis->get('one')); + $this->assertSame('mohamed', $redis->get('two')); - $redis->renamenx('two', 'four'); - $this->assertNull($redis->get('two')); - $this->assertSame('mohamed', $redis->get('four')); - $this->assertSame('adam', $redis->get('three')); + $redis->set('three', 'adam'); + $redis->renamenx('two', 'three'); + $this->assertSame('mohamed', $redis->get('two')); + $this->assertSame('adam', $redis->get('three')); - $redis->flushall(); - } + $redis->renamenx('two', 'four'); + $this->assertNull($redis->get('two')); + $this->assertSame('mohamed', $redis->get('four')); + $this->assertSame('adam', $redis->get('three')); } - public function testItAddsMembersToSortedSet() + /** + * @dataProvider extendedRedisConnectionDataProvider + */ + public function testItAddsMembersToSortedSet($connection) { - foreach ($this->connections() as $redis) { - $redis->zadd('set', 1, 'mohamed'); - $this->assertEquals(1, $redis->zcard('set')); + $redis = $this->getRedisManager($connection); - $redis->zadd('set', 2, 'taylor', 3, 'adam'); - $this->assertEquals(3, $redis->zcard('set')); + $redis->zadd('set', 1, 'mohamed'); + $this->assertEquals(1, $redis->zcard('set')); - $redis->zadd('set', ['jeffrey' => 4, 'matt' => 5]); - $this->assertEquals(5, $redis->zcard('set')); + $redis->zadd('set', 2, 'taylor', 3, 'adam'); + $this->assertEquals(3, $redis->zcard('set')); - $redis->zadd('set', 'NX', 1, 'beric'); - $this->assertEquals(6, $redis->zcard('set')); + $redis->zadd('set', ['jeffrey' => 4, 'matt' => 5]); + $this->assertEquals(5, $redis->zcard('set')); - $redis->zadd('set', 'NX', ['joffrey' => 1]); - $this->assertEquals(7, $redis->zcard('set')); + $redis->zadd('set', 'NX', 1, 'beric'); + $this->assertEquals(6, $redis->zcard('set')); - $redis->zadd('set', 'XX', ['ned' => 1]); - $this->assertEquals(7, $redis->zcard('set')); + $redis->zadd('set', 'NX', ['joffrey' => 1]); + $this->assertEquals(7, $redis->zcard('set')); - $this->assertEquals(1, $redis->zadd('set', ['sansa' => 10])); - $this->assertEquals(0, $redis->zadd('set', 'XX', 'CH', ['arya' => 11])); + $redis->zadd('set', 'XX', ['ned' => 1]); + $this->assertEquals(7, $redis->zcard('set')); - $redis->zadd('set', ['mohamed' => 100]); - $this->assertEquals(100, $redis->zscore('set', 'mohamed')); + $this->assertEquals(1, $redis->zadd('set', ['sansa' => 10])); + $this->assertEquals(0, $redis->zadd('set', 'XX', 'CH', ['arya' => 11])); - $redis->flushall(); - } + $redis->zadd('set', ['mohamed' => 100]); + $this->assertEquals(100, $redis->zscore('set', 'mohamed')); } - public function testItCountsMembersInSortedSet() + /** + * @dataProvider extendedRedisConnectionDataProvider + */ + public function testItCountsMembersInSortedSet($connection) { - foreach ($this->connections() as $redis) { - $redis->zadd('set', ['jeffrey' => 1, 'matt' => 10]); + $redis = $this->getRedisManager($connection); - $this->assertEquals(1, $redis->zcount('set', 1, 5)); - $this->assertEquals(2, $redis->zcount('set', '-inf', '+inf')); - $this->assertEquals(2, $redis->zcard('set')); + $redis->zadd('set', ['jeffrey' => 1, 'matt' => 10]); - $redis->flushall(); - } + $this->assertEquals(1, $redis->zcount('set', 1, 5)); + $this->assertEquals(2, $redis->zcount('set', '-inf', '+inf')); + $this->assertEquals(2, $redis->zcard('set')); } - public function testItIncrementsScoreOfSortedSet() + /** + * @dataProvider extendedRedisConnectionDataProvider + */ + public function testItIncrementsScoreOfSortedSet($connection) { - foreach ($this->connections() as $redis) { - $redis->zadd('set', ['jeffrey' => 1, 'matt' => 10]); - $redis->zincrby('set', 2, 'jeffrey'); - $this->assertEquals(3, $redis->zscore('set', 'jeffrey')); + $redis = $this->getRedisManager($connection); - $redis->flushall(); - } + $redis->zadd('set', ['jeffrey' => 1, 'matt' => 10]); + $redis->zincrby('set', 2, 'jeffrey'); + $this->assertEquals(3, $redis->zscore('set', 'jeffrey')); } - public function testItSetsKeyIfNotExists() + /** + * @dataProvider extendedRedisConnectionDataProvider + */ + public function testItSetsKeyIfNotExists($connection) { - foreach ($this->connections() as $redis) { - $redis->set('name', 'mohamed'); + $redis = $this->getRedisManager($connection); - $this->assertSame(0, $redis->setnx('name', 'taylor')); - $this->assertSame('mohamed', $redis->get('name')); + $redis->set('name', 'mohamed'); - $this->assertSame(1, $redis->setnx('boss', 'taylor')); - $this->assertSame('taylor', $redis->get('boss')); + $this->assertSame(0, $redis->setnx('name', 'taylor')); + $this->assertSame('mohamed', $redis->get('name')); - $redis->flushall(); - } + $this->assertSame(1, $redis->setnx('boss', 'taylor')); + $this->assertSame('taylor', $redis->get('boss')); } - public function testItSetsHashFieldIfNotExists() + /** + * @dataProvider extendedRedisConnectionDataProvider + */ + public function testItSetsHashFieldIfNotExists($connection) { - foreach ($this->connections() as $redis) { - $redis->hset('person', 'name', 'mohamed'); + $redis = $this->getRedisManager($connection); - $this->assertSame(0, $redis->hsetnx('person', 'name', 'taylor')); - $this->assertSame('mohamed', $redis->hget('person', 'name')); + $redis->hset('person', 'name', 'mohamed'); - $this->assertSame(1, $redis->hsetnx('person', 'boss', 'taylor')); - $this->assertSame('taylor', $redis->hget('person', 'boss')); + $this->assertSame(0, $redis->hsetnx('person', 'name', 'taylor')); + $this->assertSame('mohamed', $redis->hget('person', 'name')); - $redis->flushall(); - } + $this->assertSame(1, $redis->hsetnx('person', 'boss', 'taylor')); + $this->assertSame('taylor', $redis->hget('person', 'boss')); } - public function testItCalculatesIntersectionOfSortedSetsAndStores() + /** + * @dataProvider extendedRedisConnectionDataProvider + */ + public function testItCalculatesIntersectionOfSortedSetsAndStores($connection) { - foreach ($this->connections() as $redis) { - $redis->zadd('set1', ['jeffrey' => 1, 'matt' => 2, 'taylor' => 3]); - $redis->zadd('set2', ['jeffrey' => 2, 'matt' => 3]); + $redis = $this->getRedisManager($connection); - $redis->zinterstore('output', ['set1', 'set2']); - $this->assertEquals(2, $redis->zcard('output')); - $this->assertEquals(3, $redis->zscore('output', 'jeffrey')); - $this->assertEquals(5, $redis->zscore('output', 'matt')); + $redis->zadd('set1', ['jeffrey' => 1, 'matt' => 2, 'taylor' => 3]); + $redis->zadd('set2', ['jeffrey' => 2, 'matt' => 3]); - $redis->zinterstore('output2', ['set1', 'set2'], [ - 'weights' => [3, 2], - 'aggregate' => 'sum', - ]); - $this->assertEquals(7, $redis->zscore('output2', 'jeffrey')); - $this->assertEquals(12, $redis->zscore('output2', 'matt')); + $redis->zinterstore('output', ['set1', 'set2']); + $this->assertEquals(2, $redis->zcard('output')); + $this->assertEquals(3, $redis->zscore('output', 'jeffrey')); + $this->assertEquals(5, $redis->zscore('output', 'matt')); - $redis->zinterstore('output3', ['set1', 'set2'], [ - 'weights' => [3, 2], - 'aggregate' => 'min', - ]); - $this->assertEquals(3, $redis->zscore('output3', 'jeffrey')); - $this->assertEquals(6, $redis->zscore('output3', 'matt')); + $redis->zinterstore('output2', ['set1', 'set2'], [ + 'weights' => [3, 2], + 'aggregate' => 'sum', + ]); + $this->assertEquals(7, $redis->zscore('output2', 'jeffrey')); + $this->assertEquals(12, $redis->zscore('output2', 'matt')); - $redis->flushall(); - } + $redis->zinterstore('output3', ['set1', 'set2'], [ + 'weights' => [3, 2], + 'aggregate' => 'min', + ]); + $this->assertEquals(3, $redis->zscore('output3', 'jeffrey')); + $this->assertEquals(6, $redis->zscore('output3', 'matt')); } - public function testItCalculatesUnionOfSortedSetsAndStores() + /** + * @dataProvider extendedRedisConnectionDataProvider + */ + public function testItCalculatesUnionOfSortedSetsAndStores($connection) { - foreach ($this->connections() as $redis) { - $redis->zadd('set1', ['jeffrey' => 1, 'matt' => 2, 'taylor' => 3]); - $redis->zadd('set2', ['jeffrey' => 2, 'matt' => 3]); + $redis = $this->getRedisManager($connection); - $redis->zunionstore('output', ['set1', 'set2']); - $this->assertEquals(3, $redis->zcard('output')); - $this->assertEquals(3, $redis->zscore('output', 'jeffrey')); - $this->assertEquals(5, $redis->zscore('output', 'matt')); - $this->assertEquals(3, $redis->zscore('output', 'taylor')); + $redis->zadd('set1', ['jeffrey' => 1, 'matt' => 2, 'taylor' => 3]); + $redis->zadd('set2', ['jeffrey' => 2, 'matt' => 3]); - $redis->zunionstore('output2', ['set1', 'set2'], [ - 'weights' => [3, 2], - 'aggregate' => 'sum', - ]); - $this->assertEquals(7, $redis->zscore('output2', 'jeffrey')); - $this->assertEquals(12, $redis->zscore('output2', 'matt')); - $this->assertEquals(9, $redis->zscore('output2', 'taylor')); + $redis->zunionstore('output', ['set1', 'set2']); + $this->assertEquals(3, $redis->zcard('output')); + $this->assertEquals(3, $redis->zscore('output', 'jeffrey')); + $this->assertEquals(5, $redis->zscore('output', 'matt')); + $this->assertEquals(3, $redis->zscore('output', 'taylor')); - $redis->zunionstore('output3', ['set1', 'set2'], [ - 'weights' => [3, 2], - 'aggregate' => 'min', - ]); - $this->assertEquals(3, $redis->zscore('output3', 'jeffrey')); - $this->assertEquals(6, $redis->zscore('output3', 'matt')); - $this->assertEquals(9, $redis->zscore('output3', 'taylor')); + $redis->zunionstore('output2', ['set1', 'set2'], [ + 'weights' => [3, 2], + 'aggregate' => 'sum', + ]); + $this->assertEquals(7, $redis->zscore('output2', 'jeffrey')); + $this->assertEquals(12, $redis->zscore('output2', 'matt')); + $this->assertEquals(9, $redis->zscore('output2', 'taylor')); - $redis->flushall(); - } + $redis->zunionstore('output3', ['set1', 'set2'], [ + 'weights' => [3, 2], + 'aggregate' => 'min', + ]); + $this->assertEquals(3, $redis->zscore('output3', 'jeffrey')); + $this->assertEquals(6, $redis->zscore('output3', 'matt')); + $this->assertEquals(9, $redis->zscore('output3', 'taylor')); } - public function testItReturnsRangeInSortedSet() + /** + * @dataProvider extendedRedisConnectionDataProvider + */ + public function testItReturnsRangeInSortedSet($connection) { - foreach ($this->connections() as $connector => $redis) { - $redis->zadd('set', ['jeffrey' => 1, 'matt' => 5, 'taylor' => 10]); - $this->assertEquals(['jeffrey', 'matt'], $redis->zrange('set', 0, 1)); - $this->assertEquals(['jeffrey', 'matt', 'taylor'], $redis->zrange('set', 0, -1)); + $redis = $this->getRedisManager($connection); - if ($connector === 'predis') { - $this->assertEquals(['jeffrey' => 1, 'matt' => 5], $redis->zrange('set', 0, 1, 'withscores')); - } else { - $this->assertEquals(['jeffrey' => 1, 'matt' => 5], $redis->zrange('set', 0, 1, true)); - } + $redis->zadd('set', ['jeffrey' => 1, 'matt' => 5, 'taylor' => 10]); + $this->assertEquals(['jeffrey', 'matt'], $redis->zrange('set', 0, 1)); + $this->assertEquals(['jeffrey', 'matt', 'taylor'], $redis->zrange('set', 0, -1)); - $redis->flushall(); + if ($connection === 'predis') { + $this->assertEquals(['jeffrey' => 1, 'matt' => 5], $redis->zrange('set', 0, 1, 'withscores')); + } else { + $this->assertEquals(['jeffrey' => 1, 'matt' => 5], $redis->zrange('set', 0, 1, true)); } } - public function testItReturnsRevRangeInSortedSet() + /** + * @dataProvider extendedRedisConnectionDataProvider + */ + public function testItReturnsRevRangeInSortedSet($connection) { - foreach ($this->connections() as $connector => $redis) { - $redis->zadd('set', ['jeffrey' => 1, 'matt' => 5, 'taylor' => 10]); - $this->assertEquals(['taylor', 'matt'], $redis->ZREVRANGE('set', 0, 1)); - $this->assertEquals(['taylor', 'matt', 'jeffrey'], $redis->ZREVRANGE('set', 0, -1)); + $redis = $this->getRedisManager($connection); - if ($connector === 'predis') { - $this->assertEquals(['matt' => 5, 'taylor' => 10], $redis->ZREVRANGE('set', 0, 1, 'withscores')); - } else { - $this->assertEquals(['matt' => 5, 'taylor' => 10], $redis->ZREVRANGE('set', 0, 1, true)); - } + $redis->zadd('set', ['jeffrey' => 1, 'matt' => 5, 'taylor' => 10]); + $this->assertEquals(['taylor', 'matt'], $redis->ZREVRANGE('set', 0, 1)); + $this->assertEquals(['taylor', 'matt', 'jeffrey'], $redis->ZREVRANGE('set', 0, -1)); - $redis->flushall(); + if ($connection === 'predis') { + $this->assertEquals(['matt' => 5, 'taylor' => 10], $redis->ZREVRANGE('set', 0, 1, 'withscores')); + } else { + $this->assertEquals(['matt' => 5, 'taylor' => 10], $redis->ZREVRANGE('set', 0, 1, true)); } } - public function testItReturnsRangeByScoreInSortedSet() - { - foreach ($this->connections() as $redis) { - $redis->zadd('set', ['jeffrey' => 1, 'matt' => 5, 'taylor' => 10]); - $this->assertEquals(['jeffrey'], $redis->zrangebyscore('set', 0, 3)); - $this->assertEquals(['matt' => 5, 'taylor' => 10], $redis->zrangebyscore('set', 0, 11, [ - 'withscores' => true, - 'limit' => [ - 'offset' => 1, - 'count' => 2, - ], - ])); - $this->assertEquals(['matt' => 5, 'taylor' => 10], $redis->zrangebyscore('set', 0, 11, [ - 'withscores' => true, - 'limit' => [1, 2], - ])); - - $redis->flushall(); - } - } + /** + * @dataProvider extendedRedisConnectionDataProvider + */ + public function testItReturnsRangeByScoreInSortedSet($connection) + { + $redis = $this->getRedisManager($connection); - public function testItReturnsRevRangeByScoreInSortedSet() - { - foreach ($this->connections() as $redis) { - $redis->zadd('set', ['jeffrey' => 1, 'matt' => 5, 'taylor' => 10]); - $this->assertEquals(['taylor'], $redis->ZREVRANGEBYSCORE('set', 10, 6)); - $this->assertEquals(['matt' => 5, 'jeffrey' => 1], $redis->ZREVRANGEBYSCORE('set', 10, 0, [ - 'withscores' => true, - 'limit' => [ - 'offset' => 1, - 'count' => 2, - ], - ])); - $this->assertEquals(['matt' => 5, 'jeffrey' => 1], $redis->ZREVRANGEBYSCORE('set', 10, 0, [ - 'withscores' => true, - 'limit' => [1, 2], - ])); - - $redis->flushall(); - } + $redis->zadd('set', ['jeffrey' => 1, 'matt' => 5, 'taylor' => 10]); + $this->assertEquals(['jeffrey'], $redis->zrangebyscore('set', 0, 3)); + $this->assertEquals(['matt' => 5, 'taylor' => 10], $redis->zrangebyscore('set', 0, 11, [ + 'withscores' => true, + 'limit' => [ + 'offset' => 1, + 'count' => 2, + ], + ])); + $this->assertEquals(['matt' => 5, 'taylor' => 10], $redis->zrangebyscore('set', 0, 11, [ + 'withscores' => true, + 'limit' => [1, 2], + ])); + } + + /** + * @dataProvider extendedRedisConnectionDataProvider + */ + public function testItReturnsRevRangeByScoreInSortedSet($connection) + { + $redis = $this->getRedisManager($connection); + + $redis->zadd('set', ['jeffrey' => 1, 'matt' => 5, 'taylor' => 10]); + $this->assertEquals(['taylor'], $redis->ZREVRANGEBYSCORE('set', 10, 6)); + $this->assertEquals(['matt' => 5, 'jeffrey' => 1], $redis->ZREVRANGEBYSCORE('set', 10, 0, [ + 'withscores' => true, + 'limit' => [ + 'offset' => 1, + 'count' => 2, + ], + ])); + $this->assertEquals(['matt' => 5, 'jeffrey' => 1], $redis->ZREVRANGEBYSCORE('set', 10, 0, [ + 'withscores' => true, + 'limit' => [1, 2], + ])); } - public function testItReturnsRankInSortedSet() + /** + * @dataProvider extendedRedisConnectionDataProvider + */ + public function testItReturnsRankInSortedSet($connection) { - foreach ($this->connections() as $redis) { - $redis->zadd('set', ['jeffrey' => 1, 'matt' => 5, 'taylor' => 10]); + $redis = $this->getRedisManager($connection); - $this->assertEquals(0, $redis->zrank('set', 'jeffrey')); - $this->assertEquals(2, $redis->zrank('set', 'taylor')); + $redis->zadd('set', ['jeffrey' => 1, 'matt' => 5, 'taylor' => 10]); - $redis->flushall(); - } + $this->assertEquals(0, $redis->zrank('set', 'jeffrey')); + $this->assertEquals(2, $redis->zrank('set', 'taylor')); } - public function testItReturnsScoreInSortedSet() + /** + * @dataProvider extendedRedisConnectionDataProvider + */ + public function testItReturnsScoreInSortedSet($connection) { - foreach ($this->connections() as $redis) { - $redis->zadd('set', ['jeffrey' => 1, 'matt' => 5, 'taylor' => 10]); + $redis = $this->getRedisManager($connection); - $this->assertEquals(1, $redis->zscore('set', 'jeffrey')); - $this->assertEquals(10, $redis->zscore('set', 'taylor')); + $redis->zadd('set', ['jeffrey' => 1, 'matt' => 5, 'taylor' => 10]); - $redis->flushall(); - } + $this->assertEquals(1, $redis->zscore('set', 'jeffrey')); + $this->assertEquals(10, $redis->zscore('set', 'taylor')); } - public function testItRemovesMembersInSortedSet() + /** + * @dataProvider extendedRedisConnectionDataProvider + */ + public function testItRemovesMembersInSortedSet($connection) { - foreach ($this->connections() as $redis) { - $redis->zadd('set', ['jeffrey' => 1, 'matt' => 5, 'taylor' => 10, 'adam' => 11]); + $redis = $this->getRedisManager($connection); - $redis->zrem('set', 'jeffrey'); - $this->assertEquals(3, $redis->zcard('set')); + $redis->zadd('set', ['jeffrey' => 1, 'matt' => 5, 'taylor' => 10, 'adam' => 11]); - $redis->zrem('set', 'matt', 'adam'); - $this->assertEquals(1, $redis->zcard('set')); + $redis->zrem('set', 'jeffrey'); + $this->assertEquals(3, $redis->zcard('set')); - $redis->flushall(); - } + $redis->zrem('set', 'matt', 'adam'); + $this->assertEquals(1, $redis->zcard('set')); } - public function testItRemovesMembersByScoreInSortedSet() + /** + * @dataProvider extendedRedisConnectionDataProvider + */ + public function testItRemovesMembersByScoreInSortedSet($connection) { - foreach ($this->connections() as $redis) { - $redis->zadd('set', ['jeffrey' => 1, 'matt' => 5, 'taylor' => 10, 'adam' => 11]); - $redis->ZREMRANGEBYSCORE('set', 5, '+inf'); - $this->assertEquals(1, $redis->zcard('set')); + $redis = $this->getRedisManager($connection); - $redis->flushall(); - } + $redis->zadd('set', ['jeffrey' => 1, 'matt' => 5, 'taylor' => 10, 'adam' => 11]); + $redis->ZREMRANGEBYSCORE('set', 5, '+inf'); + $this->assertEquals(1, $redis->zcard('set')); } - public function testItRemovesMembersByRankInSortedSet() + /** + * @dataProvider extendedRedisConnectionDataProvider + */ + public function testItRemovesMembersByRankInSortedSet($connection) { - foreach ($this->connections() as $redis) { - $redis->zadd('set', ['jeffrey' => 1, 'matt' => 5, 'taylor' => 10, 'adam' => 11]); - $redis->ZREMRANGEBYRANK('set', 1, -1); - $this->assertEquals(1, $redis->zcard('set')); + $redis = $this->getRedisManager($connection); - $redis->flushall(); - } + $redis->zadd('set', ['jeffrey' => 1, 'matt' => 5, 'taylor' => 10, 'adam' => 11]); + $redis->ZREMRANGEBYRANK('set', 1, -1); + $this->assertEquals(1, $redis->zcard('set')); } - public function testItSetsMultipleHashFields() + /** + * @dataProvider extendedRedisConnectionDataProvider + */ + public function testItSetsMultipleHashFields($connection) { - foreach ($this->connections() as $redis) { - $redis->hmset('hash', ['name' => 'mohamed', 'hobby' => 'diving']); - $this->assertEquals(['name' => 'mohamed', 'hobby' => 'diving'], $redis->hgetall('hash')); + $redis = $this->getRedisManager($connection); - $redis->hmset('hash2', 'name', 'mohamed', 'hobby', 'diving'); - $this->assertEquals(['name' => 'mohamed', 'hobby' => 'diving'], $redis->hgetall('hash2')); + $redis->hmset('hash', ['name' => 'mohamed', 'hobby' => 'diving']); + $this->assertEquals(['name' => 'mohamed', 'hobby' => 'diving'], $redis->hgetall('hash')); - $redis->flushall(); - } + $redis->hmset('hash2', 'name', 'mohamed', 'hobby', 'diving'); + $this->assertEquals(['name' => 'mohamed', 'hobby' => 'diving'], $redis->hgetall('hash2')); } - public function testItGetsMultipleHashFields() + /** + * @dataProvider extendedRedisConnectionDataProvider + */ + public function testItGetsMultipleHashFields($connection) { - foreach ($this->connections() as $redis) { - $redis->hmset('hash', ['name' => 'mohamed', 'hobby' => 'diving']); + $redis = $this->getRedisManager($connection); - $this->assertEquals(['mohamed', 'diving'], - $redis->hmget('hash', 'name', 'hobby') - ); + $redis->hmset('hash', ['name' => 'mohamed', 'hobby' => 'diving']); - $this->assertEquals(['mohamed', 'diving'], - $redis->hmget('hash', ['name', 'hobby']) - ); + $this->assertEquals(['mohamed', 'diving'], + $redis->hmget('hash', 'name', 'hobby') + ); - $redis->flushall(); - } + $this->assertEquals(['mohamed', 'diving'], + $redis->hmget('hash', ['name', 'hobby']) + ); } - public function testItGetsMultipleKeys() + /** + * @dataProvider extendedRedisConnectionDataProvider + */ + public function testItGetsMultipleKeys($connection) { - $valueSet = ['name' => 'mohamed', 'hobby' => 'diving']; + $redis = $this->getRedisManager($connection); - foreach ($this->connections() as $redis) { - $redis->mset($valueSet); + $valueSet = ['name' => 'mohamed', 'hobby' => 'diving']; - $this->assertEquals( - array_values($valueSet), - $redis->mget(array_keys($valueSet)) - ); + $redis->mset($valueSet); - $redis->flushall(); - } + $this->assertEquals( + array_values($valueSet), + $redis->mget(array_keys($valueSet)) + ); } - public function testItFlushes() + /** + * @dataProvider extendedRedisConnectionDataProvider + */ + public function testItFlushes($connection) { - foreach ($this->connections() as $redis) { - $redis->set('name', 'Till'); - $this->assertSame(1, $redis->exists('name')); + $redis = $this->getRedisManager($connection); - $redis->flushdb(); - $this->assertSame(0, $redis->exists('name')); - } + $redis->set('name', 'Till'); + $this->assertSame(1, $redis->exists('name')); + + $redis->flushdb(); + $this->assertSame(0, $redis->exists('name')); } - public function testItFlushesAsynchronous() + /** + * @dataProvider extendedRedisConnectionDataProvider + */ + public function testItFlushesAsynchronous($connection) { - foreach ($this->connections() as $redis) { - $redis->set('name', 'Till'); - $this->assertSame(1, $redis->exists('name')); + $redis = $this->getRedisManager($connection); - $redis->flushdb('ASYNC'); - $this->assertSame(0, $redis->exists('name')); - } + $redis->set('name', 'Till'); + $this->assertSame(1, $redis->exists('name')); + + $redis->flushdb('ASYNC'); + $this->assertSame(0, $redis->exists('name')); } - public function testItRunsEval() + /** + * @dataProvider extendedRedisConnectionDataProvider + */ + public function testItRunsEval($connection) { - foreach ($this->connections() as $redis) { - if ($redis instanceof PhpRedisConnection) { - // User must decide what needs to be serialized and compressed. - $redis->eval('redis.call("set", KEYS[1], ARGV[1])', 1, 'name', ...$redis->pack(['mohamed'])); - } else { - $redis->eval('redis.call("set", KEYS[1], ARGV[1])', 1, 'name', 'mohamed'); - } - - $this->assertSame('mohamed', $redis->get('name')); + $redis = $this->getRedisManager($connection); - $redis->flushall(); + if ($redis->connection() instanceof PhpRedisConnection) { + // User must decide what needs to be serialized and compressed. + $redis->eval('redis.call("set", KEYS[1], ARGV[1])', 1, 'name', ...$redis->pack(['mohamed'])); + } else { + $redis->eval('redis.call("set", KEYS[1], ARGV[1])', 1, 'name', 'mohamed'); } + + $this->assertSame('mohamed', $redis->get('name')); } - public function testItRunsPipes() + /** + * @dataProvider extendedRedisConnectionDataProvider + */ + public function testItRunsPipes($connection) { - foreach ($this->connections() as $redis) { - $result = $redis->pipeline(function ($pipe) { - $pipe->set('test:pipeline:1', 1); - $pipe->get('test:pipeline:1'); - $pipe->set('test:pipeline:2', 2); - $pipe->get('test:pipeline:2'); - }); + $redis = $this->getRedisManager($connection); - $this->assertCount(4, $result); - $this->assertEquals(1, $result[1]); - $this->assertEquals(2, $result[3]); + $result = $redis->pipeline(function ($pipe) { + $pipe->set('test:pipeline:1', 1); + $pipe->get('test:pipeline:1'); + $pipe->set('test:pipeline:2', 2); + $pipe->get('test:pipeline:2'); + }); - $redis->flushall(); - } + $this->assertCount(4, $result); + $this->assertEquals(1, $result[1]); + $this->assertEquals(2, $result[3]); } - public function testItRunsTransactions() + /** + * @dataProvider extendedRedisConnectionDataProvider + */ + public function testItRunsTransactions($connection) { - foreach ($this->connections() as $redis) { - $result = $redis->transaction(function ($pipe) { - $pipe->set('test:transaction:1', 1); - $pipe->get('test:transaction:1'); - $pipe->set('test:transaction:2', 2); - $pipe->get('test:transaction:2'); - }); + $redis = $this->getRedisManager($connection); - $this->assertCount(4, $result); - $this->assertEquals(1, $result[1]); - $this->assertEquals(2, $result[3]); + $result = $redis->transaction(function ($pipe) { + $pipe->set('test:transaction:1', 1); + $pipe->get('test:transaction:1'); + $pipe->set('test:transaction:2', 2); + $pipe->get('test:transaction:2'); + }); - $redis->flushall(); - } + $this->assertCount(4, $result); + $this->assertEquals(1, $result[1]); + $this->assertEquals(2, $result[3]); } - public function testItRunsRawCommand() + /** + * @dataProvider extendedRedisConnectionDataProvider + */ + public function testItRunsRawCommand($connection) { - foreach ($this->connections() as $redis) { - $redis->executeRaw(['SET', 'test:raw:1', '1']); + $redis = $this->getRedisManager($connection); - $this->assertEquals( - 1, $redis->executeRaw(['GET', 'test:raw:1']) - ); + $redis->executeRaw(['SET', 'test:raw:1', '1']); - $redis->flushall(); - } + $this->assertEquals( + 1, $redis->executeRaw(['GET', 'test:raw:1']) + ); } public function testItDispatchesQueryEvent() { - foreach ($this->connections() as $redis) { - $redis->setEventDispatcher($events = m::mock(Dispatcher::class)); + $redis = $this->getRedisManager('phpredis'); - $events->shouldReceive('dispatch')->once()->with(m::on(function ($event) { - $this->assertSame('get', $event->command); - $this->assertEquals(['foobar'], $event->parameters); - $this->assertSame('default', $event->connectionName); - $this->assertInstanceOf(Connection::class, $event->connection); + $redis->setEventDispatcher($events = Mockery::mock(Dispatcher::class)); - return true; - })); + $events->shouldReceive('dispatch')->once()->with(Mockery::on(function ($event) { + $this->assertSame('get', $event->command); + $this->assertEquals(['foobar'], $event->parameters); + $this->assertSame('default', $event->connectionName); + $this->assertInstanceOf(Connection::class, $event->connection); - $redis->get('foobar'); + return true; + })); - $redis->unsetEventDispatcher(); - } + $redis->get('foobar'); + + $redis->unsetEventDispatcher(); } public function testItPersistsConnection() @@ -582,415 +606,204 @@ public function testItPersistsConnection() $this->assertSame( 'laravel', - $this->connections()['persistent']->getPersistentID() + $this->getRedisManager('phpredis_persistent')->getPersistentID() ); } - public function testItScansForKeys() + /** + * @dataProvider extendedRedisConnectionDataProvider + */ + public function testItScansForKeys($connection) { - foreach ($this->connections() as $redis) { - $initialKeys = ['test:scan:1', 'test:scan:2']; + $redis = $this->getRedisManager($connection); - foreach ($initialKeys as $k => $key) { - $redis->set($key, 'test'); - $initialKeys[$k] = $this->getPrefix($redis->client()).$key; - } + $initialKeys = ['test:scan:1', 'test:scan:2']; - $iterator = null; + foreach ($initialKeys as $k => $key) { + $redis->set($key, 'test'); + $initialKeys[$k] = $this->getPrefix($redis->client()).$key; + } - do { - [$cursor, $returnedKeys] = $redis->scan($iterator); + $iterator = null; - if (! is_array($returnedKeys)) { - $returnedKeys = [$returnedKeys]; - } + do { + [$cursor, $returnedKeys] = $redis->scan($iterator); - foreach ($returnedKeys as $returnedKey) { - $this->assertContains($returnedKey, $initialKeys); - } - } while ($iterator > 0); + if (! is_array($returnedKeys)) { + $returnedKeys = [$returnedKeys]; + } - $redis->flushAll(); - } + foreach ($returnedKeys as $returnedKey) { + $this->assertContains($returnedKey, $initialKeys); + } + } while ($iterator > 0); } - public function testItZscansForKeys() + /** + * @dataProvider extendedRedisConnectionDataProvider + */ + public function testItZscansForKeys($connection) { - foreach ($this->connections() as $redis) { - $members = [100 => 'test:zscan:1', 200 => 'test:zscan:2']; + $redis = $this->getRedisManager($connection); - foreach ($members as $score => $member) { - $redis->zadd('set', $score, $member); - } + $members = [100 => 'test:zscan:1', 200 => 'test:zscan:2']; - $iterator = null; - $result = []; + foreach ($members as $score => $member) { + $redis->zadd('set', $score, $member); + } - do { - [$iterator, $returnedMembers] = $redis->zscan('set', $iterator); + $iterator = null; + $result = []; - if (! is_array($returnedMembers)) { - $returnedMembers = [$returnedMembers]; - } + do { + [$iterator, $returnedMembers] = $redis->zscan('set', $iterator); - foreach ($returnedMembers as $member => $score) { - $this->assertArrayHasKey((int) $score, $members); - $this->assertContains($member, $members); - } + if (! is_array($returnedMembers)) { + $returnedMembers = [$returnedMembers]; + } - $result += $returnedMembers; - } while ($iterator > 0); + foreach ($returnedMembers as $member => $score) { + $this->assertArrayHasKey((int) $score, $members); + $this->assertContains($member, $members); + } - $this->assertCount(2, $result); + $result += $returnedMembers; + } while ($iterator > 0); - $iterator = null; - [$iterator, $returned] = $redis->zscan('set', $iterator, ['match' => 'test:unmatch:*']); - $this->assertEmpty($returned); + $this->assertCount(2, $result); - $iterator = null; - [$iterator, $returned] = $redis->zscan('set', $iterator, ['count' => 5]); - $this->assertCount(2, $returned); + $iterator = null; + [$iterator, $returned] = $redis->zscan('set', $iterator, ['match' => 'test:unmatch:*']); + $this->assertEmpty($returned); - $redis->flushAll(); - } + $iterator = null; + [$iterator, $returned] = $redis->zscan('set', $iterator, ['count' => 5]); + $this->assertCount(2, $returned); } - public function testItHscansForKeys() + /** + * @dataProvider extendedRedisConnectionDataProvider + */ + public function testItHscansForKeys($connection) { - foreach ($this->connections() as $redis) { - $fields = ['name' => 'mohamed', 'hobby' => 'diving']; + $redis = $this->getRedisManager($connection); - foreach ($fields as $field => $value) { - $redis->hset('hash', $field, $value); - } + $fields = ['name' => 'mohamed', 'hobby' => 'diving']; - $iterator = null; - $result = []; + foreach ($fields as $field => $value) { + $redis->hset('hash', $field, $value); + } - do { - [$iterator, $returnedFields] = $redis->hscan('hash', $iterator); + $iterator = null; + $result = []; - foreach ($returnedFields as $field => $value) { - $this->assertArrayHasKey($field, $fields); - $this->assertContains($value, $fields); - } + do { + [$iterator, $returnedFields] = $redis->hscan('hash', $iterator); - $result += $returnedFields; - } while ($iterator > 0); + foreach ($returnedFields as $field => $value) { + $this->assertArrayHasKey($field, $fields); + $this->assertContains($value, $fields); + } - $this->assertCount(2, $result); + $result += $returnedFields; + } while ($iterator > 0); - $iterator = null; - [$iterator, $returned] = $redis->hscan('hash', $iterator, ['match' => 'test:unmatch:*']); - $this->assertEmpty($returned); + $this->assertCount(2, $result); - $iterator = null; - [$iterator, $returned] = $redis->hscan('hash', $iterator, ['count' => 5]); - $this->assertCount(2, $returned); + $iterator = null; + [$iterator, $returned] = $redis->hscan('hash', $iterator, ['match' => 'test:unmatch:*']); + $this->assertEmpty($returned); - $redis->flushAll(); - } + $iterator = null; + [$iterator, $returned] = $redis->hscan('hash', $iterator, ['count' => 5]); + $this->assertCount(2, $returned); } - public function testItSscansForKeys() + /** + * @dataProvider extendedRedisConnectionDataProvider + */ + public function testItSscansForKeys($connection) { - foreach ($this->connections() as $redis) { - $members = ['test:sscan:1', 'test:sscan:2']; + $redis = $this->getRedisManager($connection); - foreach ($members as $member) { - $redis->sadd('set', $member); - } + $members = ['test:sscan:1', 'test:sscan:2']; - $iterator = null; - $result = []; + foreach ($members as $member) { + $redis->sadd('set', $member); + } - do { - [$iterator, $returnedMembers] = $redis->sscan('set', $iterator); + $iterator = null; + $result = []; - foreach ($returnedMembers as $member) { - $this->assertContains($member, $members); - array_push($result, $member); - } - } while ($iterator > 0); + do { + [$iterator, $returnedMembers] = $redis->sscan('set', $iterator); - $this->assertCount(2, $result); + foreach ($returnedMembers as $member) { + $this->assertContains($member, $members); + array_push($result, $member); + } + } while ($iterator > 0); - $iterator = null; - [$iterator, $returned] = $redis->sscan('set', $iterator, ['match' => 'test:unmatch:*']); - $this->assertEmpty($returned); + $this->assertCount(2, $result); - $iterator = null; - [$iterator, $returned] = $redis->sscan('set', $iterator, ['count' => 5]); - $this->assertCount(2, $returned); + $iterator = null; + [$iterator, $returned] = $redis->sscan('set', $iterator, ['match' => 'test:unmatch:*']); + $this->assertEmpty($returned); - $redis->flushAll(); - } + $iterator = null; + [$iterator, $returned] = $redis->sscan('set', $iterator, ['count' => 5]); + $this->assertCount(2, $returned); } - public function testItSPopsForKeys() + /** + * @dataProvider extendedRedisConnectionDataProvider + */ + public function testItSPopsForKeys($connection) { - foreach ($this->connections() as $redis) { - $members = ['test:spop:1', 'test:spop:2', 'test:spop:3', 'test:spop:4']; - - foreach ($members as $member) { - $redis->sadd('set', $member); - } - - $result = $redis->spop('set'); - $this->assertIsNotArray($result); - $this->assertContains($result, $members); + $redis = $this->getRedisManager($connection); - $result = $redis->spop('set', 1); + $members = ['test:spop:1', 'test:spop:2', 'test:spop:3', 'test:spop:4']; - $this->assertIsArray($result); - $this->assertCount(1, $result); - - $result = $redis->spop('set', 2); - - $this->assertIsArray($result); - $this->assertCount(2, $result); - - $redis->flushAll(); + foreach ($members as $member) { + $redis->sadd('set', $member); } - } - public function testPhpRedisScanOption() - { - foreach ($this->connections() as $redis) { - if ($redis->client() instanceof Client) { - continue; - } + $result = $redis->spop('set'); + $this->assertIsNotArray($result); + $this->assertContains($result, $members); - $iterator = null; + $result = $redis->spop('set', 1); - do { - $returned = $redis->scan($iterator); + $this->assertIsArray($result); + $this->assertCount(1, $result); - if ($redis->client()->getOption(Redis::OPT_SCAN) === Redis::SCAN_RETRY) { - $this->assertEmpty($returned); - } - } while ($iterator > 0); - } - } + $result = $redis->spop('set', 2); - private function getPrefix($client) - { - if ($client instanceof Redis) { - return $client->getOption(Redis::OPT_PREFIX); - } - - return $client->getOptions()->prefix; + $this->assertIsArray($result); + $this->assertCount(2, $result); } - public function testMacroable() + /** + * @dataProvider extendedRedisConnectionDataProvider + */ + public function testMacroable($connection) { Connection::macro('foo', function () { return 'foo'; }); - foreach ($this->connections() as $redis) { - $this->assertSame( - 'foo', - $redis->foo() - ); - } + $this->assertSame( + 'foo', + $this->getRedisManager($connection)->foo() + ); } - public function connections() + private function getPrefix($client) { - $connections = [ - 'predis' => $this->redis['predis']->connection(), - 'phpredis' => $this->redis['phpredis']->connection(), - ]; - - $host = env('REDIS_HOST', '127.0.0.1'); - $port = env('REDIS_PORT', 6379); - - $connections[] = (new RedisManager(new Application, 'phpredis', [ - 'cluster' => false, - 'default' => [ - 'url' => "redis://user@$host:$port", - 'host' => 'overwrittenByUrl', - 'port' => 'overwrittenByUrl', - 'database' => 5, - 'options' => ['prefix' => 'laravel:'], - 'timeout' => 0.5, - ], - ]))->connection(); - - $connections['persistent'] = (new RedisManager(new Application, 'phpredis', [ - 'cluster' => false, - 'default' => [ - 'host' => $host, - 'port' => $port, - 'database' => 6, - 'options' => ['prefix' => 'laravel:'], - 'timeout' => 0.5, - 'persistent' => true, - 'persistent_id' => 'laravel', - ], - ]))->connection(); - - $connections[] = (new RedisManager(new Application, 'phpredis', [ - 'cluster' => false, - 'default' => [ - 'host' => $host, - 'port' => $port, - 'database' => 7, - 'options' => ['serializer' => Redis::SERIALIZER_JSON], - 'timeout' => 0.5, - ], - ]))->connection(); - - $connections[] = (new RedisManager(new Application, 'phpredis', [ - 'cluster' => false, - 'default' => [ - 'host' => $host, - 'port' => $port, - 'database' => 8, - 'options' => ['scan' => Redis::SCAN_RETRY], - 'timeout' => 0.5, - ], - ]))->connection(); - - if (defined('Redis::COMPRESSION_LZF')) { - $connections['compression_lzf'] = (new RedisManager(new Application, 'phpredis', [ - 'cluster' => false, - 'default' => [ - 'host' => $host, - 'port' => $port, - 'database' => 9, - 'options' => [ - 'compression' => Redis::COMPRESSION_LZF, - 'name' => 'compression_lzf', - ], - 'timeout' => 0.5, - ], - ]))->connection(); - } - - if (defined('Redis::COMPRESSION_ZSTD')) { - $connections['compression_zstd'] = (new RedisManager(new Application, 'phpredis', [ - 'cluster' => false, - 'default' => [ - 'host' => $host, - 'port' => $port, - 'database' => 10, - 'options' => [ - 'compression' => Redis::COMPRESSION_ZSTD, - 'name' => 'compression_zstd', - ], - 'timeout' => 0.5, - ], - ]))->connection(); - - $connections['compression_zstd_default'] = (new RedisManager(new Application, 'phpredis', [ - 'cluster' => false, - 'default' => [ - 'host' => $host, - 'port' => $port, - 'database' => 11, - 'options' => [ - 'compression' => Redis::COMPRESSION_ZSTD, - 'compression_level' => Redis::COMPRESSION_ZSTD_DEFAULT, - 'name' => 'compression_zstd_default', - ], - 'timeout' => 0.5, - ], - ]))->connection(); - - $connections['compression_zstd_min'] = (new RedisManager(new Application, 'phpredis', [ - 'cluster' => false, - 'default' => [ - 'host' => $host, - 'port' => $port, - 'database' => 12, - 'options' => [ - 'compression' => Redis::COMPRESSION_ZSTD, - 'compression_level' => Redis::COMPRESSION_ZSTD_MIN, - 'name' => 'compression_zstd_min', - ], - 'timeout' => 0.5, - ], - ]))->connection(); - - $connections['compression_zstd_max'] = (new RedisManager(new Application, 'phpredis', [ - 'cluster' => false, - 'default' => [ - 'host' => $host, - 'port' => $port, - 'database' => 13, - 'options' => [ - 'compression' => Redis::COMPRESSION_ZSTD, - 'compression_level' => Redis::COMPRESSION_ZSTD_MAX, - 'name' => 'compression_zstd_max', - ], - 'timeout' => 0.5, - ], - ]))->connection(); - } - - if (defined('Redis::COMPRESSION_LZ4')) { - $connections['compression_lz4'] = (new RedisManager(new Application, 'phpredis', [ - 'cluster' => false, - 'default' => [ - 'host' => $host, - 'port' => $port, - 'database' => 14, - 'options' => [ - 'compression' => Redis::COMPRESSION_LZ4, - 'name' => 'compression_lz4', - ], - 'timeout' => 0.5, - ], - ]))->connection(); - - $connections['compression_lz4_default'] = (new RedisManager(new Application, 'phpredis', [ - 'cluster' => false, - 'default' => [ - 'host' => $host, - 'port' => $port, - 'database' => 15, - 'options' => [ - 'compression' => Redis::COMPRESSION_LZ4, - 'compression_level' => 0, - 'name' => 'compression_lz4_default', - ], - 'timeout' => 0.5, - ], - ]))->connection(); - - $connections['compression_lz4_min'] = (new RedisManager(new Application, 'phpredis', [ - 'cluster' => false, - 'default' => [ - 'host' => $host, - 'port' => $port, - 'database' => 16, - 'options' => [ - 'compression' => Redis::COMPRESSION_LZ4, - 'compression_level' => 1, - 'name' => 'compression_lz4_min', - ], - 'timeout' => 0.5, - ], - ]))->connection(); - - $connections['compression_lz4_max'] = (new RedisManager(new Application, 'phpredis', [ - 'cluster' => false, - 'default' => [ - 'host' => $host, - 'port' => $port, - 'database' => 17, - 'options' => [ - 'compression' => Redis::COMPRESSION_LZ4, - 'compression_level' => 12, - 'name' => 'compression_lz4_max', - ], - 'timeout' => 0.5, - ], - ]))->connection(); + if ($client instanceof Redis) { + return $client->getOption(Redis::OPT_PREFIX); } - return $connections; + return $client->getOptions()->prefix; } } diff --git a/tests/Redis/RedisConnectorTest.php b/tests/Redis/RedisConnectorTest.php index 86e330538848..ed40ae5bc5d5 100644 --- a/tests/Redis/RedisConnectorTest.php +++ b/tests/Redis/RedisConnectorTest.php @@ -2,26 +2,18 @@ namespace Illuminate\Tests\Redis; -use Illuminate\Foundation\Application; use Illuminate\Foundation\Testing\Concerns\InteractsWithRedis; -use Illuminate\Redis\RedisManager; use PHPUnit\Framework\TestCase; class RedisConnectorTest extends TestCase { use InteractsWithRedis; - protected function setUp(): void - { - parent::setUp(); - $this->setUpRedis(); - } - protected function tearDown(): void { - parent::tearDown(); - $this->tearDownRedis(); + + parent::tearDown(); } public function testDefaultConfiguration() @@ -29,16 +21,16 @@ public function testDefaultConfiguration() $host = env('REDIS_HOST', '127.0.0.1'); $port = env('REDIS_PORT', 6379); - $predisClient = $this->redis['predis']->connection()->client(); + $predisClient = $this->getRedisManager('predis')->connection()->client(); $parameters = $predisClient->getConnection()->getParameters(); $this->assertSame('tcp', $parameters->scheme); $this->assertEquals($host, $parameters->host); $this->assertEquals($port, $parameters->port); - $phpRedisClient = $this->redis['phpredis']->connection()->client(); + $phpRedisClient = $this->getRedisManager('phpredis')->connection()->client(); $this->assertEquals($host, $phpRedisClient->getHost()); $this->assertEquals($port, $phpRedisClient->getPort()); - $this->assertSame('default', $phpRedisClient->client('GETNAME')); + $this->assertSame('phpredis', $phpRedisClient->client('getname')); } public function testUrl() @@ -46,13 +38,15 @@ public function testUrl() $host = env('REDIS_HOST', '127.0.0.1'); $port = env('REDIS_PORT', 6379); - $predis = new RedisManager(new Application, 'predis', [ + $predis = $this->getRedisManager('predis', 'predis', [ 'cluster' => false, 'options' => [ 'prefix' => 'test_', ], 'default' => [ 'url' => "redis://{$host}:{$port}", + 'host' => 'willBeOverwrittenByUrl', + 'port' => 'willBeOverwrittenByUrl', 'database' => 5, 'timeout' => 0.5, ], @@ -63,13 +57,15 @@ public function testUrl() $this->assertEquals($host, $parameters->host); $this->assertEquals($port, $parameters->port); - $phpRedis = new RedisManager(new Application, 'phpredis', [ + $phpRedis = $this->getRedisManager('phpredis', 'phpredis', [ 'cluster' => false, 'options' => [ 'prefix' => 'test_', ], 'default' => [ 'url' => "redis://{$host}:{$port}", + 'host' => 'willBeOverwrittenByUrl', + 'port' => 'willBeOverwrittenByUrl', 'database' => 5, 'timeout' => 0.5, ], @@ -84,30 +80,34 @@ public function testUrlWithScheme() $host = env('REDIS_HOST', '127.0.0.1'); $port = env('REDIS_PORT', 6379); - $predis = new RedisManager(new Application, 'predis', [ + $predis = $this->getRedisManager('predis', 'predis', [ 'cluster' => false, 'options' => [ 'prefix' => 'test_', ], 'default' => [ - 'url' => "tls://{$host}:{$port}", + 'url' => "tlsv1.2://{$host}:{$port}", + 'host' => 'willBeOverwrittenByUrl', + 'port' => 'willBeOverwrittenByUrl', 'database' => 5, 'timeout' => 0.5, ], ]); $predisClient = $predis->connection()->client(); $parameters = $predisClient->getConnection()->getParameters(); - $this->assertSame('tls', $parameters->scheme); + $this->assertSame('tcp', $parameters->scheme); $this->assertEquals($host, $parameters->host); $this->assertEquals($port, $parameters->port); - $phpRedis = new RedisManager(new Application, 'phpredis', [ + $phpRedis = $this->getRedisManager('phpredis', 'phpredis', [ 'cluster' => false, 'options' => [ 'prefix' => 'test_', ], 'default' => [ 'url' => "tcp://{$host}:{$port}", + 'host' => 'willBeOverwrittenByUrl', + 'port' => 'willBeOverwrittenByUrl', 'database' => 5, 'timeout' => 0.5, ], @@ -122,13 +122,13 @@ public function testScheme() $host = env('REDIS_HOST', '127.0.0.1'); $port = env('REDIS_PORT', 6379); - $predis = new RedisManager(new Application, 'predis', [ + $predis = $this->getRedisManager('predis', 'predis', [ 'cluster' => false, 'options' => [ 'prefix' => 'test_', ], 'default' => [ - 'scheme' => 'tls', + 'scheme' => 'tcp', 'host' => $host, 'port' => $port, 'database' => 5, @@ -137,11 +137,11 @@ public function testScheme() ]); $predisClient = $predis->connection()->client(); $parameters = $predisClient->getConnection()->getParameters(); - $this->assertSame('tls', $parameters->scheme); + $this->assertSame('tcp', $parameters->scheme); $this->assertEquals($host, $parameters->host); $this->assertEquals($port, $parameters->port); - $phpRedis = new RedisManager(new Application, 'phpredis', [ + $phpRedis = $this->getRedisManager('phpredis', 'phpredis', [ 'cluster' => false, 'options' => [ 'prefix' => 'test_', @@ -166,7 +166,7 @@ public function testPredisConfigurationWithUsername() $username = 'testuser'; $password = 'testpw'; - $predis = new RedisManager(new Application, 'predis', [ + $predis = $this->getRedisManager('predis', 'predis', [ 'default' => [ 'host' => $host, 'port' => $port, @@ -187,7 +187,7 @@ public function testPredisConfigurationWithSentinel() $host = env('REDIS_HOST', '127.0.0.1'); $port = env('REDIS_PORT', 6379); - $predis = new RedisManager(new Application, 'predis', [ + $predis = $this->getRedisManager('predis', 'predis', [ 'cluster' => false, 'options' => [ 'replication' => 'sentinel',