Skip to content

Commit

Permalink
Added support for FUNCTION DUMP, FUNCTION FLUSH, FUNCTION RESTORE com…
Browse files Browse the repository at this point in the history
…mands (#1332)
  • Loading branch information
vladvildanov authored Jul 3, 2023
1 parent 90da582 commit dd64569
Show file tree
Hide file tree
Showing 8 changed files with 368 additions and 5 deletions.
3 changes: 3 additions & 0 deletions src/Command/Redis/Container/FunctionContainer.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
/**
* @method string load(string $functionCode, bool $replace = 'false')
* @method Status delete(string $libraryName)
* @method string dump()
* @method Status flush(?string $mode = null)
* @method Status restore(string $value, ?string $policy = null)
*/
class FunctionContainer extends AbstractContainer
{
Expand Down
26 changes: 26 additions & 0 deletions src/Command/Strategy/ContainerCommands/Functions/DumpStrategy.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Predis\Command\Strategy\ContainerCommands\Functions;

use Predis\Command\Strategy\SubcommandStrategyInterface;

class DumpStrategy implements SubcommandStrategyInterface
{
/**
* {@inheritDoc}
*/
public function processArguments(array $arguments): array
{
return $arguments;
}
}
32 changes: 32 additions & 0 deletions src/Command/Strategy/ContainerCommands/Functions/FlushStrategy.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Predis\Command\Strategy\ContainerCommands\Functions;

use Predis\Command\Strategy\SubcommandStrategyInterface;

class FlushStrategy implements SubcommandStrategyInterface
{
/**
* {@inheritDoc}
*/
public function processArguments(array $arguments): array
{
$processedArguments = [$arguments[0]];

if (array_key_exists(1, $arguments) && null !== $arguments[1]) {
$processedArguments[] = strtoupper($arguments[1]);
}

return $processedArguments;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Predis\Command\Strategy\ContainerCommands\Functions;

use Predis\Command\Strategy\SubcommandStrategyInterface;

class RestoreStrategy implements SubcommandStrategyInterface
{
/**
* {@inheritDoc}
*/
public function processArguments(array $arguments): array
{
$processedArguments = [$arguments[0], $arguments[1]];

if (array_key_exists(2, $arguments) && null !== $arguments[2]) {
$processedArguments[] = strtoupper($arguments[2]);
}

return $processedArguments;
}
}
135 changes: 130 additions & 5 deletions tests/Predis/Command/Redis/FUNCTIONS_Test.php
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,44 @@ public function testDeleteFilterArguments(): void
$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());
}

/**
* @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());
}

/**
* @group disconnected
*/
Expand All @@ -86,7 +124,7 @@ public function testParseResponse(): void
public function testLoadFunctionAddFunctionIntoGivenLibrary(): void
{
$redis = $this->getClient();
$redis->executeRaw(['FUNCTION', 'FLUSH']);
$redis->function->flush();

$actualResponse = $redis->function->load(
"#!lua name={$this->libName} \n redis.register_function('myfunc', function(keys, args) return args[1] end)"
Expand All @@ -105,7 +143,7 @@ public function testLoadFunctionAddFunctionIntoGivenLibrary(): void
public function testLoadFunctionOverridesExistingFunctionWithReplaceArgumentGiven(): void
{
$redis = $this->getClient();
$redis->executeRaw(['FUNCTION', 'FLUSH']);
$redis->function->flush();

$actualResponse = $redis->function->load(
"#!lua name={$this->libName} \n redis.register_function('myfunc', function(keys, args) return args[1] end)"
Expand All @@ -132,7 +170,7 @@ public function testLoadFunctionOverridesExistingFunctionWithReplaceArgumentGive
public function testLoadFunctionThrowsErrorOnAlreadyExistingLibraryGiven(): void
{
$redis = $this->getClient();
$redis->executeRaw(['FUNCTION', 'FLUSH']);
$redis->function->flush();

$actualResponse = $redis->function->load(
"#!lua name={$this->libName} \n redis.register_function('myfunc', function(keys, args) return args[1] end)"
Expand Down Expand Up @@ -160,7 +198,7 @@ public function testLoadFunctionThrowsErrorOnAlreadyExistingLibraryGiven(): void
public function testDeleteFunctionRemovesAlreadyExistingLibrary(): void
{
$redis = $this->getClient();
$redis->executeRaw(['FUNCTION', 'FLUSH']);
$redis->function->flush();

$actualResponse = $redis->function->load(
"#!lua name={$this->libName} \n redis.register_function('myfunc', function(keys, args) return args[1] end)"
Expand All @@ -170,6 +208,65 @@ public function testDeleteFunctionRemovesAlreadyExistingLibrary(): void
$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
* @return void
Expand All @@ -178,11 +275,39 @@ public function testDeleteFunctionRemovesAlreadyExistingLibrary(): void
public function testDeleteFunctionThrowsErrorOnNonExistingLibrary(): void
{
$redis = $this->getClient();
$redis->executeRaw(['FUNCTION', 'FLUSH']);
$redis->function->flush();

$this->expectException(ServerException::class);
$this->expectExceptionMessage('ERR Library not found');

$redis->function->delete($this->libName);
}

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'],
],
];
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Predis\Command\Strategy\ContainerCommands\Functions;

use PredisTestCase;

class DumpStrategyTest extends PredisTestCase
{
/**
* @var DumpStrategy
*/
private $strategy;

protected function setUp(): void
{
$this->strategy = new DumpStrategy();
}

/**
* @group disconnected
* @return void
*/
public function testProcessArguments(): void
{
$this->assertSame(['arg1', 'arg2'], $this->strategy->processArguments(['arg1', 'arg2']));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php

/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Predis\Command\Strategy\ContainerCommands\Functions;

use PredisTestCase;

class FlushStrategyTest extends PredisTestCase
{
/**
* @var FlushStrategy
*/
private $strategy;

protected function setUp(): void
{
$this->strategy = new FlushStrategy();
}

/**
* @dataProvider argumentsProvider
* @group disconnected
* @param array $actualArguments
* @param array $expectedResponse
* @return void
*/
public function testProcessArguments(array $actualArguments, array $expectedResponse): void
{
$this->assertSame($expectedResponse, $this->strategy->processArguments($actualArguments));
}

public function argumentsProvider(): array
{
return [
'with default arguments' => [
['FLUSH', null],
['FLUSH'],
],
'with mode argument' => [
['FLUSH', 'sync'],
['FLUSH', 'SYNC'],
],
];
}
}
Loading

0 comments on commit dd64569

Please sign in to comment.