CommandObjectsScriptingCommandsTest.java
package redis.clients.jedis.commands.commandobjects;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasEntry;
import static org.hamcrest.Matchers.hasKey;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.nullValue;
import static org.junit.jupiter.api.Assertions.assertThrows;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import io.redis.test.annotations.SinceRedisVersion;
import io.redis.test.utils.RedisVersion;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import redis.clients.jedis.RedisProtocol;
import redis.clients.jedis.args.FlushMode;
import redis.clients.jedis.args.FunctionRestorePolicy;
import redis.clients.jedis.exceptions.JedisException;
import redis.clients.jedis.resps.FunctionStats;
import redis.clients.jedis.resps.LibraryInfo;
import redis.clients.jedis.util.RedisVersionUtil;
/**
* Tests related to <a href="https://redis.io/commands/?group=scripting">Scripting</a> commands.
*/
public class CommandObjectsScriptingCommandsTest extends CommandObjectsStandaloneTestBase {
public CommandObjectsScriptingCommandsTest(RedisProtocol protocol) {
super(protocol);
}
@BeforeEach
@Override
public void setUp() {
super.setUp();
if (RedisVersionUtil.getRedisVersion(endpoint).isGreaterThanOrEqualTo(RedisVersion.V7_0_0)) {
assertThat(exec(commandObjects.functionFlush(FlushMode.SYNC)), equalTo("OK"));
}
}
@Test
public void testEvalWithOnlyScript() {
String set = exec(commandObjects.set("foo", "bar"));
assertThat(set, equalTo("OK"));
String script = "return redis.call('get', 'foo')";
Object eval = exec(commandObjects.eval(script));
assertThat(eval, equalTo("bar"));
Object evalBinary = exec(commandObjects.eval(script.getBytes()));
assertThat(evalBinary, equalTo("bar".getBytes()));
// eval with incorrect script
assertThrows(JedisException.class,
() -> exec(commandObjects.eval("return x")));
}
@Test
public void testEvalWithScriptAndSampleKey() {
String set = exec(commandObjects.set("foo", "bar"));
assertThat(set, equalTo("OK"));
String script = "return redis.call('get', 'foo');";
Object eval = exec(commandObjects.eval(script, "sampleKey"));
assertThat(eval, equalTo("bar"));
Object evalBinary = exec(commandObjects.eval(script.getBytes(), "sampleKey".getBytes()));
assertThat(evalBinary, equalTo("bar".getBytes()));
}
@Test
public void testEvalWithScriptKeyCountAndParams() {
exec(commandObjects.set("key1", "value1"));
exec(commandObjects.set("key2", "value2"));
// Script to get values of two keys and compare them
String script = "if redis.call('get', KEYS[1]) == ARGV[1] and redis.call('get', KEYS[2]) == ARGV[2] then return 'true' else return 'false' end";
Object evalTrue = exec(commandObjects.eval(
script, 2, "key1", "key2", "value1", "value2"));
assertThat(evalTrue, equalTo("true"));
Object evalTrueBinary = exec(commandObjects.eval(
script.getBytes(), 2, "key1".getBytes(), "key2".getBytes(), "value1".getBytes(), "value2".getBytes()));
assertThat(evalTrueBinary, equalTo("true".getBytes()));
Object evalFalse = exec(commandObjects.eval(
script, 2, "key1", "key2", "value1", "value3"));
assertThat(evalFalse, equalTo("false"));
Object evalFalseBinary = exec(commandObjects.eval(
script.getBytes(), 2, "key1".getBytes(), "key2".getBytes(), "value1".getBytes(), "value3".getBytes()));
assertThat(evalFalseBinary, equalTo("false".getBytes()));
// Incorrect number of keys specified
assertThrows(JedisException.class,
() -> exec(commandObjects.eval(script, 1, "key1", "value1", "value2")));
}
@Test
public void testEvalWithScriptKeysAndArgsList() {
exec(commandObjects.hset("fruits", "apples", "5"));
exec(commandObjects.hset("fruits", "bananas", "3"));
exec(commandObjects.hset("fruits", "oranges", "4"));
// Script to sum the values for the fruits provided as args. The hash name is provided as key.
// The sum is written to a string value whose name is also provided as keys.
String script = "local sum = 0\n" +
"for i, fruitKey in ipairs(ARGV) do\n" +
" local value = redis.call('HGET', KEYS[1], fruitKey)\n" +
" if value then\n" +
" sum = sum + tonumber(value)\n" +
" end\n" +
"end\n" +
"redis.call('SET', KEYS[2], sum)\n" +
"return sum";
String initialTotal = exec(commandObjects.get("total"));
assertThat(initialTotal, nullValue());
Object eval = exec(commandObjects.eval(script,
Arrays.asList("fruits", "total"), Arrays.asList("apples", "bananas", "oranges")));
assertThat(eval, equalTo(12L));
String totalAfterEval = exec(commandObjects.get("total"));
assertThat(totalAfterEval, equalTo("12"));
// reset
assertThat(exec(commandObjects.del("total")), equalTo(1L));
// binary
String initialTotalBinary = exec(commandObjects.get("total"));
assertThat(initialTotalBinary, nullValue());
Object evalBinary = exec(commandObjects.eval(script.getBytes(),
Arrays.asList("fruits".getBytes(), "total".getBytes()), Arrays.asList("apples".getBytes(), "bananas".getBytes(), "oranges".getBytes())));
assertThat(evalBinary, equalTo(12L));
String totalAfterEvalBinary = exec(commandObjects.get("total"));
assertThat(totalAfterEvalBinary, equalTo("12"));
}
@Test
@SinceRedisVersion(value = "7.0.0")
public void testEvalReadonlyWithScriptKeysAndArgsList() {
exec(commandObjects.set("readonlyKey1", "readonlyValue1"));
exec(commandObjects.set("readonlyKey2", "readonlyValue2"));
// Script to retrieve values for provided keys, concatenates
String script = "return redis.call('get', KEYS[1]) .. redis.call('get', KEYS[2])";
Object eval = exec(commandObjects.evalReadonly(
script, Arrays.asList("readonlyKey1", "readonlyKey2"), Collections.emptyList()));
assertThat(eval, equalTo("readonlyValue1readonlyValue2"));
Object evalBinary = exec(commandObjects.evalReadonly(
script.getBytes(), Arrays.asList("readonlyKey1".getBytes(), "readonlyKey2".getBytes()), Collections.emptyList()));
assertThat(evalBinary, equalTo("readonlyValue1readonlyValue2".getBytes()));
}
@Test
public void testEvalshaWithSha1() {
String script = "return 42";
String sha1 = exec(commandObjects.scriptLoad(script));
assertThat(sha1, notNullValue());
Object eval = exec(commandObjects.evalsha(sha1));
assertThat(eval, equalTo(42L));
Object evalBinary = exec(commandObjects.evalsha(sha1.getBytes()));
assertThat(evalBinary, equalTo(42L));
// incorrect SHA1 hash
assertThrows(JedisException.class,
() -> exec(commandObjects.evalsha("incorrectSha1")));
}
@Test
public void testEvalshaWithSha1AndSampleKey() {
String script = "return redis.call('get', 'foo')";
String sha1 = exec(commandObjects.scriptLoad(script));
assertThat(sha1, notNullValue());
exec(commandObjects.set("foo", "bar"));
Object eval = exec(commandObjects.evalsha(sha1, "sampleKey"));
assertThat(eval, equalTo("bar"));
Object evalBinary = exec(commandObjects.evalsha(sha1.getBytes(), "sampleKey".getBytes()));
assertThat(evalBinary, equalTo("bar".getBytes()));
}
@Test
public void testEvalWithScriptKeyCountAndParamsSha() {
exec(commandObjects.set("key1", "value1"));
exec(commandObjects.set("key2", "value2"));
// Script to get values of two keys and compare them with expected values
String script = "if redis.call('get', KEYS[1]) == ARGV[1] and redis.call('get', KEYS[2]) == ARGV[2] then return 'true' else return 'false' end";
String sha1 = exec(commandObjects.scriptLoad(script));
assertThat(sha1, notNullValue());
Object evalTrue = exec(commandObjects.evalsha(
sha1, 2, "key1", "key2", "value1", "value2"));
assertThat(evalTrue, equalTo("true"));
Object evalTrueBinary = exec(commandObjects.evalsha(
sha1.getBytes(), 2, "key1".getBytes(), "key2".getBytes(), "value1".getBytes(), "value2".getBytes()));
assertThat(evalTrueBinary, equalTo("true".getBytes()));
Object evalFalse = exec(commandObjects.evalsha(
sha1, 2, "key1", "key2", "value1", "value3"));
assertThat(evalFalse, equalTo("false"));
Object evalFalseBinary = exec(commandObjects.evalsha(
sha1.getBytes(), 2, "key1".getBytes(), "key2".getBytes(), "value1".getBytes(), "value3".getBytes()));
assertThat(evalFalseBinary, equalTo("false".getBytes()));
// Incorrect number of keys
assertThrows(JedisException.class,
() -> exec(commandObjects.evalsha(sha1, 1, "key1", "value1", "value2")));
}
@Test
public void testEvalWithScriptKeysAndArgsListSha() {
exec(commandObjects.hset("fruits", "apples", "5"));
exec(commandObjects.hset("fruits", "bananas", "3"));
exec(commandObjects.hset("fruits", "oranges", "4"));
// Sums the values for given fruits, stores the result, and returns it
String script = "local sum = 0\n" +
"for i, fruitKey in ipairs(ARGV) do\n" +
" local value = redis.call('HGET', KEYS[1], fruitKey)\n" +
" if value then\n" +
" sum = sum + tonumber(value)\n" +
" end\n" +
"end\n" +
"redis.call('SET', KEYS[2], sum)\n" +
"return sum";
String sha1 = exec(commandObjects.scriptLoad(script));
assertThat(sha1, notNullValue());
String initialTotal = exec(commandObjects.get("total"));
assertThat(initialTotal, nullValue());
Object eval = exec(commandObjects.evalsha(
sha1, Arrays.asList("fruits", "total"), Arrays.asList("apples", "bananas", "oranges")));
assertThat(eval, equalTo(12L));
String totalAfterEval = exec(commandObjects.get("total"));
assertThat(totalAfterEval, equalTo("12"));
// reset
assertThat(exec(commandObjects.del("total")), equalTo(1L));
// binary
String initialTotalBinary = exec(commandObjects.get("total"));
assertThat(initialTotalBinary, nullValue());
Object evalBinary = exec(commandObjects.evalsha(
sha1.getBytes(),
Arrays.asList("fruits".getBytes(), "total".getBytes()),
Arrays.asList("apples".getBytes(), "bananas".getBytes(), "oranges".getBytes())));
assertThat(evalBinary, equalTo(12L));
String totalAfterEvalBinary = exec(commandObjects.get("total"));
assertThat(totalAfterEvalBinary, equalTo("12"));
}
@Test
@SinceRedisVersion(value = "7.0.0")
public void testEvalReadonlyWithScriptKeysAndArgsListSha() {
exec(commandObjects.set("readonlyKey1", "readonlyValue1"));
exec(commandObjects.set("readonlyKey2", "readonlyValue2"));
// Script to retrieve values for provided keys, concatenated
String script = "return redis.call('get', KEYS[1]) .. redis.call('get', KEYS[2])";
String sha1 = exec(commandObjects.scriptLoad(script));
assertThat(sha1, notNullValue());
Object eval = exec(commandObjects.evalshaReadonly(
sha1,
Arrays.asList("readonlyKey1", "readonlyKey2"),
Collections.emptyList()));
assertThat(eval, equalTo("readonlyValue1readonlyValue2"));
Object evalBinary = exec(commandObjects.evalshaReadonly(
sha1.getBytes(),
Arrays.asList("readonlyKey1".getBytes(), "readonlyKey2".getBytes()),
Collections.emptyList()));
assertThat(evalBinary, equalTo("readonlyValue1readonlyValue2".getBytes()));
}
@Test
public void testScriptExists() {
String script = "return 'test script'";
String sha1 = exec(commandObjects.scriptLoad(script));
assertThat(sha1, notNullValue());
List<Boolean> exists = exec(commandObjects.scriptExists(Collections.singletonList(sha1)));
assertThat(exists, contains(true));
// Load another script to test with multiple SHA1 hashes
String anotherScript = "return 'another test script'";
String anotherSha1 = exec(commandObjects.scriptLoad(anotherScript));
assertThat(anotherSha1, notNullValue());
String nonExistingSha1 = "nonexistentsha1";
List<Boolean> existsMultiple = exec(commandObjects.scriptExists(
"sampleKey", sha1, anotherSha1, nonExistingSha1));
assertThat(existsMultiple, contains(true, true, false));
List<Boolean> existsMultipleBinary = exec(commandObjects.scriptExists(
"sampleKey".getBytes(), sha1.getBytes(), anotherSha1.getBytes(), nonExistingSha1.getBytes()));
assertThat(existsMultipleBinary, contains(true, true, false));
}
@Test
public void testScriptLoadAndRun() {
String script = "return 'Hello, Redis!'";
String sha1 = exec(commandObjects.scriptLoad(script));
assertThat(sha1, notNullValue());
Object scriptResponse1 = exec(commandObjects.evalsha(sha1));
assertThat(scriptResponse1, equalTo("Hello, Redis!"));
}
@Test
public void testScriptLoadAndRunSampleKey() {
String anotherScript = "return redis.call('get', 'testKey')";
String sampleKey = "testKey";
exec(commandObjects.set(sampleKey, "sampleValue")); // Set a value for the sampleKey
String anotherSha1 = exec(commandObjects.scriptLoad(anotherScript, sampleKey));
assertThat(anotherSha1, notNullValue());
Object scriptResponse2 = exec(commandObjects.evalsha(anotherSha1, sampleKey));
assertThat(scriptResponse2, equalTo("sampleValue"));
}
@Test
public void testScriptLoadAndRunSampleKeyBinary() {
String anotherScript = "return redis.call('get', 'testKey')";
String sampleKey = "testKey";
exec(commandObjects.set(sampleKey, "sampleValue")); // Set a value for the sampleKey
byte[] anotherSha1 = exec(commandObjects.scriptLoad(anotherScript.getBytes(), sampleKey.getBytes()));
assertThat(anotherSha1, notNullValue());
Object scriptResponse2 = exec(commandObjects.evalsha(anotherSha1, sampleKey.getBytes()));
assertThat(scriptResponse2, equalTo("sampleValue".getBytes()));
}
@Test
public void testScriptFlush() {
String script = "return 'test script flush'";
String sha1 = exec(commandObjects.scriptLoad(script));
assertThat(sha1, notNullValue());
List<Boolean> existsBefore = exec(commandObjects.scriptExists(Collections.singletonList(sha1)));
assertThat(existsBefore, contains(true));
String flush = exec(commandObjects.scriptFlush());
assertThat(flush, equalTo("OK"));
List<Boolean> existsAfter = exec(commandObjects.scriptExists(Collections.singletonList(sha1)));
assertThat(existsAfter, contains(false));
}
@Test
public void testScriptFlushSampleKeyAndMode() {
String script = "return 'test script flush'";
String sha1 = exec(commandObjects.scriptLoad(script));
assertThat(sha1, notNullValue());
List<Boolean> existsBefore = exec(commandObjects.scriptExists(Collections.singletonList(sha1)));
assertThat(existsBefore, contains(true));
String flush = exec(commandObjects.scriptFlush("anyKey", FlushMode.SYNC));
assertThat(flush, equalTo("OK"));
List<Boolean> existsAfter = exec(commandObjects.scriptExists(Collections.singletonList(sha1)));
assertThat(existsAfter, contains(false));
}
@Test
public void testScriptFlushSampleKey() {
String script = "return 'test script flush'";
String sha1 = exec(commandObjects.scriptLoad(script));
assertThat(sha1, notNullValue());
List<Boolean> existsBefore = exec(commandObjects.scriptExists(Collections.singletonList(sha1)));
assertThat(existsBefore, contains(true));
String flush = exec(commandObjects.scriptFlush("anyKey"));
assertThat(flush, equalTo("OK"));
List<Boolean> existsAfter = exec(commandObjects.scriptExists(Collections.singletonList(sha1)));
assertThat(existsAfter, contains(false));
}
@Test
public void testScriptFlushBinary() {
String script = "return 'test script flush'";
String sha1 = exec(commandObjects.scriptLoad(script));
assertThat(sha1, notNullValue());
List<Boolean> existsBefore = exec(commandObjects.scriptExists(Collections.singletonList(sha1)));
assertThat(existsBefore, contains(true));
String flush = exec(commandObjects.scriptFlush("anyKey".getBytes()));
assertThat(flush, equalTo("OK"));
List<Boolean> existsAfter = exec(commandObjects.scriptExists(Collections.singletonList(sha1)));
assertThat(existsAfter, contains(false));
}
@Test
public void testScriptFlushSampleKeyAndModeBinary() {
String script = "return 'test script flush'";
String sha1 = exec(commandObjects.scriptLoad(script));
assertThat(sha1, notNullValue());
List<Boolean> existsBefore = exec(commandObjects.scriptExists(Collections.singletonList(sha1)));
assertThat(existsBefore, contains(true));
String flush = exec(commandObjects.scriptFlush("anyKey".getBytes(), FlushMode.SYNC));
assertThat(flush, equalTo("OK"));
List<Boolean> existsAfter = exec(commandObjects.scriptExists(Collections.singletonList(sha1)));
assertThat(existsAfter, contains(false));
}
@Test
public void testScriptKill() {
JedisException e = assertThrows(JedisException.class,
() -> exec(commandObjects.scriptKill()));
assertThat(e.getMessage(), containsString("No scripts in execution right now."));
e = assertThrows(JedisException.class,
() -> exec(commandObjects.scriptKill("anyKey")));
assertThat(e.getMessage(), containsString("No scripts in execution right now."));
e = assertThrows(JedisException.class,
() -> exec(commandObjects.scriptKill("anyKey".getBytes())));
assertThat(e.getMessage(), containsString("No scripts in execution right now."));
}
@Test
@SinceRedisVersion(value = "7.0.0")
public void testSumValuesFunction() {
String luaScript = "#!lua name=mylib\n" +
"redis.register_function('sumValues', function(keys, args)\n" +
"local sum = 0\n" +
"for _, key in ipairs(keys) do\n" +
"local val = redis.call('GET', key)\n" +
"if val then sum = sum + tonumber(val) end\n" +
"end\n" +
"redis.call('SET', 'total', sum)\n" +
"return sum\n" +
"end)";
String functionLoad = exec(commandObjects.functionLoad(luaScript));
assertThat(functionLoad, equalTo("mylib"));
exec(commandObjects.set("key1", "10"));
exec(commandObjects.set("key2", "20"));
exec(commandObjects.set("key3", "30"));
String initialTotal = exec(commandObjects.get("total"));
assertThat(initialTotal, nullValue());
Object fcall = exec(commandObjects.fcall(
"sumValues",
Arrays.asList("key1", "key2", "key3"),
new ArrayList<>()));
assertThat(fcall, equalTo(60L));
String totalAfterFcall = exec(commandObjects.get("total"));
assertThat(totalAfterFcall, equalTo("60"));
// reset
exec(commandObjects.del("total"));
String totalAfterRest = exec(commandObjects.get("total"));
assertThat(totalAfterRest, nullValue());
Object fcallBinary = exec(commandObjects.fcall(
"sumValues".getBytes(),
Arrays.asList("key1".getBytes(), "key2".getBytes(), "key3".getBytes()),
new ArrayList<>()));
assertThat(fcallBinary, equalTo(60L));
String totalAfterFcallBinary = exec(commandObjects.get("total"));
assertThat(totalAfterFcallBinary, equalTo("60"));
}
@Test
@SinceRedisVersion(value = "7.0.0")
public void testSumValuesFunctionReadonly() {
String luaScript = "#!lua name=mylib\n" +
"redis.register_function{function_name='sumValues', callback=function(keys, args)\n" +
"local sum = 0\n" +
"for _, key in ipairs(keys) do\n" +
"local val = redis.call('GET', key)\n" +
"if val then sum = sum + tonumber(val) end\n" +
"end\n" +
"return sum\n" +
"end, flags={'no-writes'}}";
String functionLoad = exec(commandObjects.functionLoad(luaScript));
assertThat(functionLoad, equalTo("mylib"));
exec(commandObjects.set("key1", "10"));
exec(commandObjects.set("key2", "20"));
exec(commandObjects.set("key3", "30"));
Object fcall = exec(commandObjects.fcallReadonly(
"sumValues",
Arrays.asList("key1", "key2", "key3"),
new ArrayList<>()));
assertThat(fcall, equalTo(60L));
Object fcallBinary = exec(commandObjects.fcallReadonly(
"sumValues".getBytes(),
Arrays.asList("key1".getBytes(), "key2".getBytes(), "key3".getBytes()),
new ArrayList<>()));
assertThat(fcallBinary, equalTo(60L));
}
@Test
@SinceRedisVersion(value = "7.0.0")
public void testFunctionDeletion() {
String luaScript = "#!lua name=mylib\n" +
"redis.register_function('sumValues', function(keys, args) return 42 end)";
exec(commandObjects.functionLoad(luaScript));
String libraryName = "mylib";
List<LibraryInfo> listResponse = exec(commandObjects.functionList());
assertThat(listResponse, hasSize(1));
assertThat(listResponse.get(0).getLibraryName(), equalTo(libraryName));
assertThat(listResponse.get(0).getFunctions(), hasSize(1));
assertThat(listResponse.get(0).getFunctions().get(0), hasEntry("name", "sumValues"));
String delete = exec(commandObjects.functionDelete(libraryName));
assertThat(delete, equalTo("OK"));
listResponse = exec(commandObjects.functionList());
assertThat(listResponse, empty());
}
@Test
@SinceRedisVersion(value = "7.0.0")
public void testFunctionDeletionBinary() {
String luaScript = "#!lua name=mylib\n" +
"redis.register_function('sumValues', function(keys, args) return 42 end)";
exec(commandObjects.functionLoad(luaScript));
String libraryName = "mylib";
List<LibraryInfo> listResponse = exec(commandObjects.functionList());
assertThat(listResponse, hasSize(1));
assertThat(listResponse.get(0).getLibraryName(), equalTo(libraryName));
assertThat(listResponse.get(0).getFunctions(), hasSize(1));
assertThat(listResponse.get(0).getFunctions().get(0), hasEntry("name", "sumValues"));
String deleteBinary = exec(commandObjects.functionDelete(libraryName.getBytes()));
assertThat(deleteBinary, equalTo("OK"));
listResponse = exec(commandObjects.functionList());
assertThat(listResponse, empty());
}
@Test
@SinceRedisVersion(value = "7.0.0")
public void testFunctionListing() {
String luaScript = "#!lua name=mylib\n" +
"redis.register_function('sumValues', function(keys, args) return 42 end)";
exec(commandObjects.functionLoad(luaScript));
String libraryName = "mylib";
List<LibraryInfo> list = exec(commandObjects.functionList());
assertThat(list, hasSize(1));
assertThat(list.get(0).getLibraryName(), equalTo(libraryName));
assertThat(list.get(0).getFunctions(), hasSize(1));
assertThat(list.get(0).getFunctions().get(0), hasEntry("name", "sumValues"));
assertThat(list.get(0).getLibraryCode(), nullValue());
List<Object> listBinary = exec(commandObjects.functionListBinary());
assertThat(listBinary, hasSize(1));
List<LibraryInfo> listLibrary = exec(commandObjects.functionList(libraryName));
assertThat(listLibrary, hasSize(1));
assertThat(listLibrary.get(0).getLibraryName(), equalTo(libraryName));
assertThat(listLibrary.get(0).getFunctions(), hasSize(1));
assertThat(listLibrary.get(0).getFunctions().get(0), hasEntry("name", "sumValues"));
assertThat(listLibrary.get(0).getLibraryCode(), nullValue());
List<Object> listLibraryBinary = exec(commandObjects.functionList(libraryName.getBytes()));
assertThat(listLibraryBinary, hasSize(1));
List<LibraryInfo> listWithCode = exec(commandObjects.functionListWithCode());
assertThat(listWithCode, hasSize(1));
assertThat(listWithCode.get(0).getLibraryName(), equalTo(libraryName));
assertThat(listWithCode.get(0).getFunctions(), hasSize(1));
assertThat(listWithCode.get(0).getFunctions().get(0), hasEntry("name", "sumValues"));
assertThat(listWithCode.get(0).getLibraryCode(), notNullValue());
List<Object> listWithCodeBinary = exec(commandObjects.functionListWithCodeBinary());
assertThat(listWithCodeBinary, hasSize(1));
List<LibraryInfo> listWithCodeLibrary = exec(commandObjects.functionListWithCode(libraryName));
assertThat(listWithCodeLibrary, hasSize(1));
assertThat(listWithCodeLibrary.get(0).getLibraryName(), equalTo(libraryName));
assertThat(listWithCodeLibrary.get(0).getFunctions(), hasSize(1));
assertThat(listWithCodeLibrary.get(0).getFunctions().get(0), hasEntry("name", "sumValues"));
assertThat(listWithCodeLibrary.get(0).getLibraryCode(), notNullValue());
List<Object> listWithCodeLibraryBinary = exec(commandObjects.functionListWithCode(libraryName.getBytes()));
assertThat(listWithCodeLibraryBinary, hasSize(1));
}
@Test
@SinceRedisVersion(value = "7.0.0")
public void testFunctionReload() {
String luaScript = "#!lua name=mylib\n" +
"redis.register_function('dummy', function(keys, args) return 42 end)";
String loadResult = exec(commandObjects.functionLoad(luaScript));
assertThat(loadResult, equalTo("mylib"));
Object result = exec(commandObjects.fcall(
"dummy".getBytes(), new ArrayList<>(), new ArrayList<>()));
assertThat(result, equalTo(42L));
String luaScriptChanged = "#!lua name=mylib\n" +
"redis.register_function('dummy', function(keys, args) return 52 end)";
String replaceResult = exec(commandObjects.functionLoadReplace(luaScriptChanged));
assertThat(replaceResult, equalTo("mylib"));
Object resultAfter = exec(commandObjects.fcall(
"dummy".getBytes(), new ArrayList<>(), new ArrayList<>()));
assertThat(resultAfter, equalTo(52L));
}
@Test
@SinceRedisVersion(value = "7.0.0")
public void testFunctionReloadBinary() {
String luaScript = "#!lua name=mylib\n" +
"redis.register_function('dummy', function(keys, args) return 42 end)";
String loadResult = exec(commandObjects.functionLoad(luaScript.getBytes()));
assertThat(loadResult, equalTo("mylib"));
Object result = exec(commandObjects.fcall((
"dummy").getBytes(), new ArrayList<>(), new ArrayList<>()));
assertThat(result, equalTo(42L));
String luaScriptChanged = "#!lua name=mylib\n" +
"redis.register_function('dummy', function(keys, args) return 52 end)";
String replaceResult = exec(commandObjects.functionLoadReplace(luaScriptChanged.getBytes()));
assertThat(replaceResult, equalTo("mylib"));
Object resultAfter = exec(commandObjects.fcall(
"dummy".getBytes(), new ArrayList<>(), new ArrayList<>()));
assertThat(resultAfter, equalTo(52L));
}
@Test
@SinceRedisVersion(value = "7.0.0")
public void testFunctionStats() {
String luaScript = "#!lua name=mylib\n" +
"redis.register_function('dummy', function(keys, args) return 42 end)";
String loadResult = exec(commandObjects.functionLoad(luaScript));
assertThat(loadResult, equalTo("mylib"));
for (int i = 0; i < 5; i++) {
Object result = exec(commandObjects.fcall(
"dummy".getBytes(), new ArrayList<>(), new ArrayList<>()));
assertThat(result, equalTo(42L));
}
FunctionStats stats = exec(commandObjects.functionStats());
assertThat(stats, notNullValue());
assertThat(stats.getEngines(), hasKey("LUA"));
Map<String, Object> luaStats = stats.getEngines().get("LUA");
assertThat(luaStats, hasEntry("libraries_count", 1L));
assertThat(luaStats, hasEntry("functions_count", 1L));
Object statsBinary = exec(commandObjects.functionStatsBinary());
assertThat(statsBinary, notNullValue());
}
@Test
@SinceRedisVersion(value = "7.0.0")
public void testFunctionDumpFlushRestore() {
String luaScript = "#!lua name=mylib\n" +
"redis.register_function('sumValues', function(keys, args) return 42 end)";
exec(commandObjects.functionLoad(luaScript));
String libraryName = "mylib";
List<LibraryInfo> list = exec(commandObjects.functionList());
assertThat(list, hasSize(1));
assertThat(list.get(0).getLibraryName(), equalTo(libraryName));
assertThat(list.get(0).getFunctions(), hasSize(1));
assertThat(list.get(0).getFunctions().get(0), hasEntry("name", "sumValues"));
byte[] dump = exec(commandObjects.functionDump());
assertThat(dump, notNullValue());
String flush = exec(commandObjects.functionFlush());
assertThat(flush, equalTo("OK"));
list = exec(commandObjects.functionList());
assertThat(list, empty());
String restore = exec(commandObjects.functionRestore(dump));
assertThat(restore, equalTo("OK"));
list = exec(commandObjects.functionList());
assertThat(list, hasSize(1));
assertThat(list.get(0).getLibraryName(), equalTo(libraryName));
assertThat(list.get(0).getFunctions(), hasSize(1));
assertThat(list.get(0).getFunctions().get(0), hasEntry("name", "sumValues"));
}
@Test
@SinceRedisVersion(value = "7.0.0")
public void testFunctionDumpFlushRestoreWithPolicy() {
String luaScript = "#!lua name=mylib\n" +
"redis.register_function('sumValues', function(keys, args) return 42 end)";
exec(commandObjects.functionLoad(luaScript));
String libraryName = "mylib";
List<LibraryInfo> list = exec(commandObjects.functionList());
assertThat(list, hasSize(1));
assertThat(list.get(0).getLibraryName(), equalTo(libraryName));
assertThat(list.get(0).getFunctions(), hasSize(1));
assertThat(list.get(0).getFunctions().get(0), hasEntry("name", "sumValues"));
byte[] dump = exec(commandObjects.functionDump());
assertThat(dump, notNullValue());
String flush = exec(commandObjects.functionFlush());
assertThat(flush, equalTo("OK"));
list = exec(commandObjects.functionList());
assertThat(list, empty());
String restore = exec(commandObjects.functionRestore(dump, FunctionRestorePolicy.REPLACE));
assertThat(restore, equalTo("OK"));
list = exec(commandObjects.functionList());
assertThat(list, hasSize(1));
assertThat(list.get(0).getLibraryName(), equalTo(libraryName));
assertThat(list.get(0).getFunctions(), hasSize(1));
assertThat(list.get(0).getFunctions().get(0), hasEntry("name", "sumValues"));
}
@Test
@SinceRedisVersion(value = "7.0.0")
public void testFunctionFlushWithMode() {
String luaScript = "#!lua name=mylib\n" +
"redis.register_function('sumValues', function(keys, args) return 42 end)";
exec(commandObjects.functionLoad(luaScript));
String libraryName = "mylib";
List<LibraryInfo> list = exec(commandObjects.functionList());
assertThat(list, hasSize(1));
assertThat(list.get(0).getLibraryName(), equalTo(libraryName));
assertThat(list.get(0).getFunctions(), hasSize(1));
assertThat(list.get(0).getFunctions().get(0), hasEntry("name", "sumValues"));
String flush = exec(commandObjects.functionFlush(FlushMode.SYNC));
assertThat(flush, equalTo("OK"));
list = exec(commandObjects.functionList());
assertThat(list, empty());
}
@Test
@SinceRedisVersion(value = "7.0.0")
public void testFunctionKill() {
JedisException e = assertThrows(JedisException.class,
() -> exec(commandObjects.functionKill()));
assertThat(e.getMessage(), containsString("No scripts in execution right now"));
}
}