= 7.0.0 */ class FUNCTIONS_Test extends PredisCommandTestCase { /** * @var string */ private $libName = 'mylib'; /** * {@inheritdoc} */ protected function getExpectedCommand(): string { return FUNCTIONS::class; } /** * {@inheritdoc} */ protected function getExpectedId(): string { return 'FUNCTION'; } /** * @group disconnected */ public function testLoadFilterArguments(): void { $arguments = ['LOAD', 'function-code', true]; $expected = ['LOAD', 'function-code', 'REPLACE']; $command = $this->getCommand(); $command->setArguments($arguments); $this->assertSameValues($expected, $command->getArguments()); } /** * @group disconnected */ public function testDeleteFilterArguments(): void { $arguments = ['DELETE', 'libraryName']; $expected = ['DELETE', 'libraryName']; $command = $this->getCommand(); $command->setArguments($arguments); $this->assertSameValues($expected, $command->getArguments()); } /** * @group disconnected */ public function testDumpFilterArguments(): void { $arguments = ['DUMP']; $expected = ['DUMP']; $command = $this->getCommand(); $command->setArguments($arguments); $this->assertSameValues($expected, $command->getArguments()); } /** * @group disconnected */ public function testKillFilterArguments(): void { $arguments = ['KILL']; $expected = ['KILL']; $command = $this->getCommand(); $command->setArguments($arguments); $this->assertSameValues($expected, $command->getArguments()); } /** * @group disconnected */ public function testStatsFilterArguments(): void { $arguments = ['STATS']; $expected = ['STATS']; $command = $this->getCommand(); $command->setArguments($arguments); $this->assertSameValues($expected, $command->getArguments()); } /** * @dataProvider flushArgumentsProvider * @group disconnected */ public function testFlushFilterArguments(array $actualArguments, array $expectedResponse): void { $command = $this->getCommand(); $command->setArguments($actualArguments); $this->assertSameValues($expectedResponse, $command->getArguments()); } /** * @dataProvider restoreArgumentsProvider * @group disconnected */ public function testRestoreFilterArguments(array $actualArguments, array $expectedResponse): void { $command = $this->getCommand(); $command->setArguments($actualArguments); $this->assertSameValues($expectedResponse, $command->getArguments()); } /** * @dataProvider listArgumentsProvider * @group disconnected */ public function testListFilterArguments(array $actualArguments, array $expectedResponse): void { $command = $this->getCommand(); $command->setArguments($actualArguments); $this->assertSameValues($expectedResponse, $command->getArguments()); } /** * @group disconnected */ public function testParseResponse(): void { $this->assertSame(1, $this->getCommand()->parseResponse(1)); } /** * @group connected * @return void * @requiresRedisVersion >= 7.0.0 */ public function testLoadFunctionAddFunctionIntoGivenLibrary(): void { $redis = $this->getClient(); $redis->function->flush(); $actualResponse = $redis->function->load( "#!lua name={$this->libName} \n redis.register_function('myfunc', function(keys, args) return args[1] end)" ); $this->assertSame('mylib', $actualResponse); $this->assertSame('arg1', $redis->fcall('myfunc', [], 'arg1')); $this->assertEquals('OK', $redis->function->delete($this->libName)); } /** * @group connected * @return void * @requiresRedisVersion >= 7.0.0 */ public function testLoadFunctionAddFunctionIntoGivenLibraryResp3(): void { $redis = $this->getResp3Client(); $actualResponse = $redis->function->load( "#!lua name={$this->libName} \n redis.register_function('myfunc', function(keys, args) return args[1] end)" ); $this->assertSame('mylib', $actualResponse); $this->assertSame('arg1', $redis->fcall('myfunc', [], 'arg1')); $this->assertEquals('OK', $redis->function->delete($this->libName)); } /** * @group connected * @return void * @requiresRedisVersion >= 7.0.0 */ public function testLoadFunctionOverridesExistingFunctionWithReplaceArgumentGiven(): void { $redis = $this->getClient(); $redis->function->flush(); $actualResponse = $redis->function->load( "#!lua name={$this->libName} \n redis.register_function('myfunc', function(keys, args) return args[1] end)" ); $this->assertSame($this->libName, $actualResponse); $this->assertSame('arg1', $redis->fcall('myfunc', [], 'arg1')); $overriddenResponse = $redis->function->load( "#!lua name={$this->libName} \n redis.register_function('myfunc', function(keys, args) return args[2] end)", true ); $this->assertSame($this->libName, $overriddenResponse); $this->assertSame('arg2', $redis->fcall('myfunc', [], 'arg1', 'arg2')); $this->assertEquals('OK', $redis->function->delete($this->libName)); } /** * @group connected * @return void * @requiresRedisVersion >= 7.0.0 */ public function testLoadFunctionThrowsErrorOnAlreadyExistingLibraryGiven(): void { $redis = $this->getClient(); $redis->function->flush(); $actualResponse = $redis->function->load( "#!lua name={$this->libName} \n redis.register_function('myfunc', function(keys, args) return args[1] end)" ); $this->assertSame($this->libName, $actualResponse); $this->expectException(ServerException::class); $this->expectExceptionMessage("ERR Library '{$this->libName}' already exists"); try { $redis->function->load( "#!lua name={$this->libName} \n redis.register_function('myfunc', function(keys, args) return args[1] end)" ); } finally { $this->assertEquals('OK', $redis->function->delete($this->libName)); } } /** * @group connected * @return void * @requiresRedisVersion >= 7.0.0 */ public function testDeleteFunctionRemovesAlreadyExistingLibrary(): void { $redis = $this->getClient(); $redis->function->flush(); $actualResponse = $redis->function->load( "#!lua name={$this->libName} \n redis.register_function('myfunc', function(keys, args) return args[1] end)" ); $this->assertSame($this->libName, $actualResponse); $this->assertEquals('OK', $redis->function->delete($this->libName)); } /** * @group connected * @return void * @requiresRedisVersion >= 7.0.0 */ public function testDumpReturnsSerializedPayloadOfLibrary(): void { $redis = $this->getClient(); $redis->function->flush(); $libName = $redis->function->load( "#!lua name={$this->libName} \n redis.register_function('myfunc', function(keys, args) return args[1] end)" ); $this->assertSame($this->libName, $libName); $this->assertStringContainsString($libName, $redis->function->dump()); } /** * @group connected * @return void * @requiresRedisVersion >= 7.0.0 */ public function testFlushRemovesAllLibraries(): void { $redis = $this->getClient(); $redis->function->flush(); $libName = $redis->function->load( "#!lua name={$this->libName} \n redis.register_function('myfunc', function(keys, args) return args[1] end)" ); $this->assertEquals($this->libName, $libName); $this->assertEquals('OK', $redis->function->flush()); } /** * @group connected * @return void * @requiresRedisVersion >= 7.0.0 */ public function testRestoresLibraryFromSerializedPayload(): void { $redis = $this->getClient(); $redis->function->flush(); $libName = $redis->function->load( "#!lua name={$this->libName} \n redis.register_function('myfunc', function(keys, args) return args[1] end)" ); $this->assertEquals($this->libName, $libName); $serializedPayload = $redis->function->dump(); $this->assertStringContainsString($libName, $serializedPayload); $redis->function->flush(); $this->assertEquals('OK', $redis->function->restore($serializedPayload)); } /** * @group connected * @group relay-incompatible * @return void * @requiresRedisVersion >= 7.0.0 */ public function testListReturnsListOfAvailableFunctions(): void { $redis = $this->getClient(); $redis->function->flush(); $expectedResponse = [ [ 'library_name', 'mylib', 'engine', 'LUA', 'functions', [ ['name', 'myfunc', 'description', null, 'flags', []], ], ], ]; $libName = $redis->function->load( "#!lua name={$this->libName} \n redis.register_function('myfunc', function(keys, args) return args[1] end)" ); $this->assertEquals($this->libName, $libName); $this->assertSame($expectedResponse, $redis->function->list()); } /** * @group connected * @group relay-incompatible * @return void * @requiresRedisVersion >= 7.0.0 */ public function testStatsReturnsInformationAboutRunningScript(): void { $redis = $this->getClient(); $redis->function->flush(); $expectedResponse = ['running_script', null, 'engines', ['LUA', ['libraries_count', 1, 'functions_count', 1]]]; $libName = $redis->function->load( "#!lua name={$this->libName} \n redis.register_function('myfunc', function(keys, args) return args[1] end)" ); $this->assertEquals($this->libName, $libName); $this->assertSame($expectedResponse, $redis->function->stats()); } /** * @group connected * @return void * @requiresRedisVersion >= 7.0.0 */ public function testDeleteFunctionThrowsErrorOnNonExistingLibrary(): void { $redis = $this->getClient(); $redis->function->flush(); $this->expectException(ServerException::class); $this->expectExceptionMessage('ERR Library not found'); $redis->function->delete($this->libName); } /** * @group connected * @return void * @requiresRedisVersion >= 7.0.0 */ public function testKillThrowsExceptionOnNonExistingRunningScript(): void { $redis = $this->getClient(); $redis->function->flush(); $this->expectException(ServerException::class); $this->expectExceptionMessage('NOTBUSY No scripts in execution right now.'); $redis->function->kill(); } public function flushArgumentsProvider(): array { return [ 'with default arguments' => [ ['FLUSH', null], ['FLUSH'], ], 'with mode argument' => [ ['FLUSH', 'sync'], ['FLUSH', 'SYNC'], ], ]; } public function restoreArgumentsProvider(): array { return [ 'with default arguments' => [ ['RESTORE', 'value', null], ['RESTORE', 'value'], ], 'with mode argument' => [ ['RESTORE', 'value', 'append'], ['RESTORE', 'value', 'APPEND'], ], ]; } public function listArgumentsProvider(): array { return [ 'with default arguments' => [ ['LIST', null, false], ['LIST'], ], 'with LIBRARYNAME modifier' => [ ['LIST', 'libraryname', false], ['LIST', 'LIBRARYNAME', 'libraryname'], ], 'with WITHCODE modifier' => [ ['LIST', null, true], ['LIST', 'WITHCODE'], ], 'with all arguments' => [ ['LIST', 'libraryname', true], ['LIST', 'LIBRARYNAME', 'libraryname', 'WITHCODE'], ], ]; } }