Add Redis 2.6 scripting commands to Connections

DATAREDIS-180
This commit is contained in:
Jennifer Hickey
2013-06-19 18:50:51 -07:00
parent 844782384d
commit 2c9ba9a5ed
26 changed files with 1266 additions and 39 deletions

View File

@@ -22,6 +22,7 @@ import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.junit.Assume.assumeTrue;
import static org.springframework.data.redis.SpinBarrier.waitFor;
import java.util.ArrayList;
@@ -33,10 +34,12 @@ import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.BlockingDeque;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import org.junit.After;
import org.junit.Before;
@@ -47,6 +50,7 @@ import org.springframework.data.redis.Address;
import org.springframework.data.redis.Person;
import org.springframework.data.redis.RedisSystemException;
import org.springframework.data.redis.RedisTestProfileValueSource;
import org.springframework.data.redis.RedisVersionUtils;
import org.springframework.data.redis.TestCondition;
import org.springframework.data.redis.connection.RedisListCommands.Position;
import org.springframework.data.redis.connection.RedisStringCommands.BitOperation;
@@ -147,6 +151,152 @@ public abstract class AbstractConnectionIntegrationTests {
assertFalse(connection.pExpireAt("nonexistent", System.currentTimeMillis() + 200));
}
@Test
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testScriptLoadEvalSha() {
String sha1 = connection.scriptLoad("return KEYS[1]");
actual.add(connection.evalSha(sha1, ReturnType.VALUE, 2, "key1", "key2"));
verifyResults(Arrays.asList(new Object[] {"key1"}), actual);
}
@Test
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testEvalShaArrayStrings() {
String sha1 = connection.scriptLoad("return {KEYS[1],ARGV[1]}");
actual.add(connection.evalSha(sha1, ReturnType.MULTI, 1, "key1", "arg1"));
verifyResults(Arrays.asList(new Object[] {Arrays.asList(new Object[] {"key1", "arg1"} )}), actual);
}
@Test(expected=RedisSystemException.class)
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testEvalShaNotFound() {
connection.evalSha("somefakesha", ReturnType.VALUE, 2, "key1", "key2");
}
@Test
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testEvalReturnString() {
actual.add(connection.eval("return KEYS[1]", ReturnType.VALUE, 1, "foo"));
verifyResults(Arrays.asList(new Object[] {"foo"}), actual);
}
@Test
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testEvalReturnNumber() {
actual.add(connection.eval("return 10", ReturnType.INTEGER, 0));
verifyResults(Arrays.asList(new Object[] {10l}), actual);
}
@Test
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testEvalReturnSingleOK() {
actual.add(connection.eval("return redis.call('set','abc','ghk')", ReturnType.STATUS, 0));
assertEquals(Arrays.asList(new Object[] { "OK" }), convertResults(false));
}
@Test(expected=RedisSystemException.class)
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testEvalReturnSingleError() {
connection.eval("return redis.call('expire','foo')", ReturnType.BOOLEAN, 0);
}
@Test
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testEvalReturnFalse() {
actual.add(connection.eval("return false", ReturnType.BOOLEAN, 0));
verifyResults(Arrays.asList(new Object[] { false }), actual);
}
@Test
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testEvalReturnTrue() {
actual.add(connection.eval("return true", ReturnType.BOOLEAN, 0));
verifyResults(Arrays.asList(new Object[] { true }), actual);
}
@Test
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testEvalReturnArrayStrings() {
actual.add(connection.eval("return {KEYS[1],ARGV[1]}", ReturnType.MULTI, 1, "foo", "bar"));
verifyResults(Arrays.asList(new Object[] {Arrays.asList(new Object[] {"foo", "bar"} )}), actual);
}
@Test
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testEvalReturnArrayNumbers() {
actual.add(connection.eval("return {1,2}", ReturnType.MULTI, 1, "foo", "bar"));
verifyResults(Arrays.asList(new Object[] {Arrays.asList(new Object[] {1l, 2l} )}), actual);
}
@Test
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testEvalReturnArrayOKs() {
actual.add(connection.eval("return { redis.call('set','abc','ghk'), redis.call('set','abc','lfdf')}",
ReturnType.MULTI, 0));
assertEquals(Arrays.asList(new Object[] {Arrays.asList(new Object[] {"OK", "OK"} )}), convertResults(false));
}
@Test
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testEvalReturnArrayFalses() {
actual.add(connection.eval("return { false, false}", ReturnType.MULTI, 0));
verifyResults(Arrays.asList(new Object[] {Arrays.asList(new Object[] {null, null} )}), actual);
}
@Test
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testEvalReturnArrayTrues() {
actual.add(connection.eval("return { true, true}", ReturnType.MULTI,0));
verifyResults(Arrays.asList(new Object[] {Arrays.asList(new Object[] {1l, 1l} )}), actual);
}
@Test
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testScriptExists() {
String sha1 = connection.scriptLoad("return 'foo'");
actual.add(connection.scriptExists(sha1, "98777234"));
verifyResults(Arrays.asList(new Object[] {Arrays.asList(new Object[] {true, false})}), actual);
}
@Test
@IfProfileValue(name = "runLongTests", value = "true")
public void testScriptKill() throws Exception{
getResults();
assumeTrue(RedisVersionUtils.atLeast("2.6", byteConnection));
initConnection();
final AtomicBoolean scriptDead = new AtomicBoolean(false);
Thread th = new Thread(new Runnable() {
public void run() {
DefaultStringRedisConnection conn2 = new DefaultStringRedisConnection(
connectionFactory.getConnection());
try {
conn2.eval("local time=1 while time < 10000000000 do time=time+1 end", ReturnType.BOOLEAN, 0);
}catch(DataAccessException e) {
scriptDead.set(true);
}
conn2.close();
}
});
th.start();
Thread.sleep(1000);
connection.scriptKill();
getResults();
assertTrue(waitFor(new TestCondition() {
public boolean passes() {
return scriptDead.get();
}
}, 3000l));
}
@Test
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testScriptFlush() {
String sha1 = connection.scriptLoad("return KEYS[1]");
connection.scriptFlush();
actual.add(connection.scriptExists(sha1));
verifyResults(Arrays.asList(new Object[] {Arrays.asList(new Object[] { false })}), actual);
}
@Test
@IfProfileValue(name = "runLongTests", value = "true")
public void testPersist() throws Exception {
@@ -1394,7 +1544,51 @@ public abstract class AbstractConnectionIntegrationTests {
}
protected void verifyResults(List<Object> expected, List<Object> actual) {
assertEquals(expected, actual);
assertEquals(expected, convertResults(true));
}
protected List<Object> convertResults() {
return convertResults(true);
}
protected List<Object> convertResults(boolean filterStatus) {
List<Object> actual = getResults();
List<Object> serializedResults = new ArrayList<Object>();
for (Object result : actual) {
Object convertedResult = convertResult(result);
if (filterStatus) {
if(!"OK".equals(convertedResult) && !"QUEUED".equals(convertedResult)) {
serializedResults.add(convertedResult);
}
}else {
serializedResults.add(convertedResult);
}
}
return serializedResults;
}
protected List<Object> getResults() {
return actual;
}
@SuppressWarnings({ "rawtypes", "unchecked" })
protected Object convertResult(Object result) {
if (result instanceof List && !(((List) result).isEmpty())
&& ((List) result).get(0) instanceof byte[]) {
return (SerializationUtils.deserialize((List<byte[]>) result, stringSerializer));
} else if (result instanceof byte[]) {
return (stringSerializer.deserialize((byte[]) result));
} else if (result instanceof Map
&& ((Map) result).keySet().iterator().next() instanceof byte[]) {
return (SerializationUtils.deserialize((Map) result, stringSerializer));
} else if (result instanceof Set && !(((Set) result).isEmpty())
&& ((Set) result).iterator().next() instanceof byte[]) {
return (SerializationUtils.deserialize((Set) result, stringSerializer));
}
return result;
}
protected void initConnection() {
}
protected class KeyExpired implements TestCondition {

View File

@@ -31,7 +31,6 @@ import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import org.junit.Before;
@@ -42,7 +41,6 @@ import org.springframework.data.redis.connection.RedisStringCommands.BitOperatio
import org.springframework.data.redis.connection.RedisZSetCommands.Aggregate;
import org.springframework.data.redis.connection.RedisZSetCommands.Tuple;
import org.springframework.data.redis.connection.StringRedisConnection.StringTuple;
import org.springframework.data.redis.serializer.SerializationUtils;
import org.springframework.test.annotation.IfProfileValue;
/**
@@ -960,6 +958,79 @@ abstract public class AbstractConnectionPipelineIntegrationTests extends
Arrays.asList(new String[] { "foo", "bar" }) }), actual);
}
@Test
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testScriptLoadEvalSha() {
// close the pipeline to get the return value of script load
getResults();
String sha1 = connection.scriptLoad("return KEYS[1]");
initConnection();
actual.add(connection.evalSha(sha1, ReturnType.VALUE, 2, "key1", "key2"));
verifyResults(Arrays.asList(new Object[] {"key1"}), actual);
}
@Test
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testEvalShaArrayStrings() {
// close the pipeline to get the return value of script load
getResults();
String sha1 = connection.scriptLoad("return {KEYS[1],ARGV[1]}");
initConnection();
actual.add(connection.evalSha(sha1, ReturnType.MULTI, 1, "key1", "arg1"));
verifyResults(Arrays.asList(new Object[] { Arrays.asList(new Object[] {"key1", "arg1"})}), actual);
}
@Test(expected=RedisPipelineException.class)
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testEvalShaNotFound() {
connection.evalSha("somefakesha", ReturnType.VALUE, 2, "key1", "key2");
getResults();
}
@Test(expected=RedisPipelineException.class)
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testEvalReturnSingleError() {
connection.eval("return redis.call('expire','foo')", ReturnType.BOOLEAN, 0);
getResults();
}
@Test
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testEvalReturnFalse() {
// pipelined results don't get converted to Booleans
actual.add(connection.eval("return false", ReturnType.BOOLEAN, 0));
verifyResults(Arrays.asList(new Object[] { null }), actual);
}
@Test
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testEvalReturnTrue() {
// pipelined results don't get converted to Booleans
actual.add(connection.eval("return true", ReturnType.BOOLEAN, 0));
verifyResults(Arrays.asList(new Object[] { 1l }), actual);
}
@Test
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testScriptExists() {
getResults();
String sha1 = connection.scriptLoad("return 'foo'");
initConnection();
actual.add(connection.scriptExists(sha1, "98777234"));
verifyResults(Arrays.asList(new Object[] {Arrays.asList(new Object[] {true, false})}), actual);
}
@Test
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testScriptFlush() {
getResults();
String sha1 = connection.scriptLoad("return KEYS[1]");
connection.scriptFlush();
initConnection();
actual.add(connection.scriptExists(sha1));
verifyResults(Arrays.asList(new Object[] {Arrays.asList(new Object[] { 0l })}), actual);
}
protected void initConnection() {
connection.openPipeline();
}
@@ -976,33 +1047,4 @@ abstract public class AbstractConnectionPipelineIntegrationTests extends
protected List<Object> getResults() {
return connection.closePipeline();
}
protected List<Object> convertResults() {
List<Object> pipelinedResults = getResults();
List<Object> serializedResults = new ArrayList<Object>();
for (Object result : pipelinedResults) {
Object convertedResult = convertResult(result);
if (!"OK".equals(convertedResult) && !"QUEUED".equals(convertedResult)) {
serializedResults.add(convertedResult);
}
}
return serializedResults;
}
@SuppressWarnings({ "rawtypes", "unchecked" })
protected Object convertResult(Object result) {
if (result instanceof List && !(((List) result).isEmpty())
&& ((List) result).get(0) instanceof byte[]) {
return (SerializationUtils.deserialize((List<byte[]>) result, stringSerializer));
} else if (result instanceof byte[]) {
return (stringSerializer.deserialize((byte[]) result));
} else if (result instanceof Map
&& ((Map) result).keySet().iterator().next() instanceof byte[]) {
return (SerializationUtils.deserialize((Map) result, stringSerializer));
} else if (result instanceof Set && !(((Set) result).isEmpty())
&& ((Set) result).iterator().next() instanceof byte[]) {
return (SerializationUtils.deserialize((Set) result, stringSerializer));
}
return result;
}
}

View File

@@ -21,7 +21,10 @@ import static org.junit.Assert.assertEquals;
import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.data.redis.connection.AbstractConnectionIntegrationTests;
import org.springframework.data.redis.connection.ReturnType;
import org.springframework.test.annotation.IfProfileValue;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@@ -180,4 +183,16 @@ public class JedisConnectionIntegrationTests extends AbstractConnectionIntegrati
connection.hIncrBy(key, hkey, -2 * largeNumber);
assertEquals(-largeNumber, Long.valueOf(connection.hGet(key, hkey)).longValue());
}
@Test(expected=InvalidDataAccessApiUsageException.class)
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testEvalReturnSingleError() {
connection.eval("return redis.call('expire','foo')", ReturnType.BOOLEAN, 0);
}
@Test(expected=InvalidDataAccessApiUsageException.class)
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testEvalShaNotFound() {
connection.evalSha("somefakesha", ReturnType.VALUE, 2, "key1", "key2");
}
}

View File

@@ -31,6 +31,7 @@ import org.springframework.data.redis.RedisSystemException;
import org.springframework.data.redis.connection.AbstractConnectionPipelineIntegrationTests;
import org.springframework.data.redis.connection.DefaultStringTuple;
import org.springframework.data.redis.connection.StringRedisConnection.StringTuple;
import org.springframework.test.annotation.IfProfileValue;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@@ -242,6 +243,108 @@ public class JedisConnectionPipelineIntegrationTests extends
super.testIncrByDouble();
}
@Test(expected=UnsupportedOperationException.class)
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testScriptLoadEvalSha() {
super.testScriptLoadEvalSha();
}
@Test(expected=UnsupportedOperationException.class)
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testEvalShaArrayStrings() {
super.testEvalShaArrayStrings();
}
@Test(expected=UnsupportedOperationException.class)
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testEvalShaNotFound() {
super.testEvalShaNotFound();
}
@Test(expected=UnsupportedOperationException.class)
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testEvalReturnString() {
super.testEvalReturnString();
}
@Test(expected=UnsupportedOperationException.class)
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testEvalReturnNumber() {
super.testEvalReturnNumber();
}
@Test(expected=UnsupportedOperationException.class)
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testEvalReturnSingleOK() {
super.testEvalReturnSingleOK();
}
@Test(expected=UnsupportedOperationException.class)
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testEvalReturnSingleError() {
super.testEvalReturnSingleError();
}
@Test(expected=UnsupportedOperationException.class)
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testEvalReturnFalse() {
super.testEvalReturnFalse();
}
@Test(expected=UnsupportedOperationException.class)
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testEvalReturnTrue() {
super.testEvalReturnTrue();
}
@Test(expected=UnsupportedOperationException.class)
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testEvalReturnArrayStrings() {
super.testEvalReturnArrayStrings();
}
@Test(expected=UnsupportedOperationException.class)
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testEvalReturnArrayNumbers() {
super.testEvalReturnArrayNumbers();
}
@Test(expected=UnsupportedOperationException.class)
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testEvalReturnArrayOKs() {
super.testEvalReturnArrayOKs();
}
@Test(expected=UnsupportedOperationException.class)
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testEvalReturnArrayFalses() {
super.testEvalReturnArrayFalses();
}
@Test(expected=UnsupportedOperationException.class)
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testEvalReturnArrayTrues() {
super.testEvalReturnArrayTrues();
}
@Test(expected=UnsupportedOperationException.class)
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testScriptExists() {
super.testScriptExists();
}
@IfProfileValue(name = "redisVersion", value = "2.6")
@Test(expected=UnsupportedOperationException.class)
public void testScriptKill() throws Exception{
connection.scriptKill();
}
@Test(expected=UnsupportedOperationException.class)
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testScriptFlush() {
super.testScriptFlush();
}
// Overrides, usually due to return values being Long vs Boolean or Set vs
// List

View File

@@ -21,6 +21,7 @@ import static org.junit.Assert.fail;
import java.util.Arrays;
import org.apache.commons.pool.impl.GenericObjectPool.Config;
import org.jredis.JRedis;
import org.jredis.protocol.BulkResponse;
import org.junit.After;
@@ -34,9 +35,9 @@ import org.springframework.data.redis.connection.AbstractConnectionIntegrationTe
import org.springframework.data.redis.connection.DefaultSortParameters;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.SortParameters.Order;
import org.springframework.test.annotation.IfProfileValue;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.apache.commons.pool.impl.GenericObjectPool.Config;
/**
* Integration test of {@link JredisConnection}
@@ -393,6 +394,107 @@ public class JRedisConnectionIntegrationTests extends AbstractConnectionIntegrat
super.testIncrByDouble();
}
@Test(expected=UnsupportedOperationException.class)
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testScriptLoadEvalSha() {
super.testScriptLoadEvalSha();
}
@Test(expected=UnsupportedOperationException.class)
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testEvalShaArrayStrings() {
super.testEvalShaArrayStrings();
}
@Test(expected=UnsupportedOperationException.class)
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testEvalShaNotFound() {
super.testEvalShaNotFound();
}
@Test(expected=UnsupportedOperationException.class)
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testEvalReturnString() {
super.testEvalReturnString();
}
@Test(expected=UnsupportedOperationException.class)
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testEvalReturnNumber() {
super.testEvalReturnNumber();
}
@Test(expected=UnsupportedOperationException.class)
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testEvalReturnSingleOK() {
super.testEvalReturnSingleOK();
}
@Test(expected=UnsupportedOperationException.class)
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testEvalReturnSingleError() {
super.testEvalReturnSingleError();
}
@Test(expected=UnsupportedOperationException.class)
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testEvalReturnFalse() {
super.testEvalReturnFalse();
}
@Test(expected=UnsupportedOperationException.class)
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testEvalReturnTrue() {
super.testEvalReturnTrue();
}
@Test(expected=UnsupportedOperationException.class)
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testEvalReturnArrayStrings() {
super.testEvalReturnArrayStrings();
}
@Test(expected=UnsupportedOperationException.class)
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testEvalReturnArrayNumbers() {
super.testEvalReturnArrayNumbers();
}
@Test(expected=UnsupportedOperationException.class)
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testEvalReturnArrayOKs() {
super.testEvalReturnArrayOKs();
}
@Test(expected=UnsupportedOperationException.class)
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testEvalReturnArrayFalses() {
super.testEvalReturnArrayFalses();
}
@Test(expected=UnsupportedOperationException.class)
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testEvalReturnArrayTrues() {
super.testEvalReturnArrayTrues();
}
@Test(expected=UnsupportedOperationException.class)
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testScriptExists() {
super.testScriptExists();
}
@Test(expected=UnsupportedOperationException.class)
public void testScriptKill() throws Exception{
connection.scriptKill();
}
@Test(expected=UnsupportedOperationException.class)
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testScriptFlush() {
super.testScriptFlush();
}
// Jredis returns null for rPush
@Test
public void testSort() {

View File

@@ -16,17 +16,26 @@
package org.springframework.data.redis.connection.lettuce;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import static org.junit.Assume.assumeTrue;
import static org.springframework.data.redis.SpinBarrier.waitFor;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.RedisSystemException;
import org.springframework.data.redis.RedisVersionUtils;
import org.springframework.data.redis.SettingsUtils;
import org.springframework.data.redis.TestCondition;
import org.springframework.data.redis.connection.AbstractConnectionIntegrationTests;
import org.springframework.data.redis.connection.DefaultStringRedisConnection;
import org.springframework.data.redis.connection.ReturnType;
import org.springframework.data.redis.connection.RedisStringCommands.BitOperation;
import org.springframework.test.annotation.IfProfileValue;
import org.springframework.test.context.ContextConfiguration;
@@ -134,4 +143,35 @@ public class LettuceConnectionIntegrationTests extends AbstractConnectionIntegra
connection.set("key2", "efgh");
actual.add(connection.bitOp(BitOperation.NOT, "key3", "key1", "key2"));
}
@Test
@IfProfileValue(name = "runLongTests", value = "true")
public void testScriptKill() throws Exception{
getResults();
assumeTrue(RedisVersionUtils.atLeast("2.6", byteConnection));
final AtomicBoolean scriptDead = new AtomicBoolean(false);
Thread th = new Thread(new Runnable() {
public void run() {
final LettuceConnectionFactory factory2 = new LettuceConnectionFactory(SettingsUtils.getHost(),
SettingsUtils.getPort());
factory2.afterPropertiesSet();
DefaultStringRedisConnection conn2 = new DefaultStringRedisConnection(
factory2.getConnection());
try {
conn2.eval("local time=1 while time < 10000000000 do time=time+1 end", ReturnType.BOOLEAN, 0);
}catch(DataAccessException e) {
scriptDead.set(true);
}
conn2.close();
}
});
th.start();
Thread.sleep(1000);
connection.scriptKill();
assertTrue(waitFor(new TestCondition() {
public boolean passes() {
return scriptDead.get();
}
}, 3000l));
}
}

View File

@@ -19,6 +19,7 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;
import static org.springframework.data.redis.SpinBarrier.waitFor;
import java.util.ArrayList;
@@ -29,14 +30,19 @@ import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicBoolean;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.RedisVersionUtils;
import org.springframework.data.redis.SettingsUtils;
import org.springframework.data.redis.TestCondition;
import org.springframework.data.redis.connection.AbstractConnectionPipelineIntegrationTests;
import org.springframework.data.redis.connection.DefaultStringRedisConnection;
import org.springframework.data.redis.connection.DefaultStringTuple;
import org.springframework.data.redis.connection.ReturnType;
import org.springframework.data.redis.connection.RedisStringCommands.BitOperation;
import org.springframework.data.redis.connection.StringRedisConnection.StringTuple;
import org.springframework.test.annotation.IfProfileValue;
@@ -352,6 +358,67 @@ public class LettuceConnectionPipelineIntegrationTests extends
}
}
@Test
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testEvalReturnFalse() {
// Lettuce actually returns booleans, it's not an SDR conversion
actual.add(connection.eval("return false", ReturnType.BOOLEAN, 0));
verifyResults(Arrays.asList(new Object[] { false }), actual);
}
@Test
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testEvalReturnTrue() {
// Lettuce actually returns booleans, it's not an SDR conversion
actual.add(connection.eval("return true", ReturnType.BOOLEAN, 0));
verifyResults(Arrays.asList(new Object[] { true }), actual);
}
@Test
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testScriptFlush() {
getResults();
String sha1 = connection.scriptLoad("return KEYS[1]");
connection.scriptFlush();
initConnection();
actual.add(connection.scriptExists(sha1));
// Lettuce actually returns booleans, it's not an SDR conversion
verifyResults(Arrays.asList(new Object[] {Arrays.asList(new Object[] { false })}), actual);
}
@Test
@IfProfileValue(name = "runLongTests", value = "true")
public void testScriptKill() throws Exception{
getResults();
assumeTrue(RedisVersionUtils.atLeast("2.6", byteConnection));
initConnection();
final AtomicBoolean scriptDead = new AtomicBoolean(false);
Thread th = new Thread(new Runnable() {
public void run() {
final LettuceConnectionFactory factory2 = new LettuceConnectionFactory(SettingsUtils.getHost(),
SettingsUtils.getPort());
factory2.afterPropertiesSet();
DefaultStringRedisConnection conn2 = new DefaultStringRedisConnection(
factory2.getConnection());
try {
conn2.eval("local time=1 while time < 10000000000 do time=time+1 end", ReturnType.BOOLEAN, 0);
}catch(DataAccessException e) {
scriptDead.set(true);
}
conn2.close();
}
});
th.start();
Thread.sleep(1000);
getResults();
connection.scriptKill();
assertTrue(waitFor(new TestCondition() {
public boolean passes() {
return scriptDead.get();
}
}, 3000l));
}
@SuppressWarnings({ "rawtypes", "unchecked" })
protected Object convertResult(Object result) {
Object convertedResult = super.convertResult(result);

View File

@@ -6,11 +6,13 @@ import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;
import org.junit.Test;
import org.springframework.data.redis.connection.RedisPipelineException;
import org.springframework.data.redis.connection.ReturnType;
import org.springframework.test.annotation.IfProfileValue;
/**
@@ -71,6 +73,37 @@ public class LettuceConnectionPipelineTxIntegrationTests extends
}
}
@Test(expected=RedisPipelineException.class)
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testEvalShaNotFound() {
connection.evalSha("somefakesha", ReturnType.VALUE, 2, "key1", "key2");
getResults();
}
@Test(expected=RedisPipelineException.class)
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testEvalReturnSingleError() {
connection.eval("return redis.call('expire','foo')", ReturnType.BOOLEAN, 0);
getResults();
}
@Test
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testEvalReturnSingleOK() {
actual.add(connection.eval("return redis.call('set','abc','ghk')", ReturnType.STATUS, 0));
// We pipeline the result of multi, so add an extra OK here
assertEquals(Arrays.asList(new Object[] { "OK", "OK" }), convertResults(false));
}
@Test
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testEvalReturnArrayOKs() {
actual.add(connection.eval("return { redis.call('set','abc','ghk'), redis.call('set','abc','lfdf')}",
ReturnType.MULTI, 0));
// We pipeline the result of multi, so add an extra OK here
assertEquals(Arrays.asList(new Object[] {"OK", Arrays.asList(new Object[] {"OK", "OK"} )}), convertResults(false));
}
protected void initConnection() {
connection.openPipeline();
connection.multi();

View File

@@ -23,6 +23,7 @@ import java.util.List;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.data.redis.connection.ReturnType;
import org.springframework.test.annotation.IfProfileValue;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@@ -118,6 +119,30 @@ public class LettuceConnectionTransactionIntegrationTests extends
assertTrue(restoreResults.get(0) instanceof RedisException);
}
@Test
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testEvalShaNotFound() {
connection.evalSha("somefakesha", ReturnType.VALUE, 2, "key1", "key2");
List<Object> results = getResults();
assertTrue(results.get(0) instanceof RedisException);
}
@Test
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testEvalReturnSingleError() {
connection.eval("return redis.call('expire','foo')", ReturnType.BOOLEAN, 0);
List<Object> results = getResults();
assertTrue(results.get(0) instanceof RedisException);
}
@Test(expected = UnsupportedOperationException.class)
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testScriptKill() {
// Impossible to call script kill in a tx because you can't issue the
// exec command while Redis is running a script
connection.scriptKill();
}
protected void initConnection() {
connection.multi();
}

View File

@@ -18,10 +18,14 @@ package org.springframework.data.redis.connection.srp;
import static org.junit.Assert.assertEquals;
import java.util.Arrays;
import org.junit.After;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.data.redis.connection.AbstractConnectionIntegrationTests;
import org.springframework.data.redis.connection.ReturnType;
import org.springframework.test.annotation.IfProfileValue;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@@ -74,4 +78,18 @@ public class SrpConnectionIntegrationTests extends AbstractConnectionIntegration
BulkReply reply = (BulkReply) connection.execute("GET", "foo");
assertEquals("bar", stringSerializer.deserialize(reply.data()));
}
@Test
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testEvalReturnArrayOKs() {
// SRP returns the Strings from individual StatusReplys in a MultiBulkReply, while other clients return as byte[]
actual.add(connection.eval("return { redis.call('set','abc','ghk'), redis.call('set','abc','lfdf')}",
ReturnType.MULTI, 0));
verifyResults(Arrays.asList(new Object[] {Arrays.asList(new Object[] {"OK", "OK"} )}), actual);
}
@Ignore("https://github.com/spullara/redis-protocol/issues/25")
public void testScriptExists() {
//script_exists only returns one result and it's false
}
}

View File

@@ -28,6 +28,7 @@ import java.util.List;
import java.util.Properties;
import java.util.Set;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.data.redis.connection.AbstractConnectionPipelineIntegrationTests;
@@ -42,7 +43,9 @@ import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import redis.reply.BulkReply;
import redis.reply.IntegerReply;
import redis.reply.Reply;
import redis.reply.StatusReply;
/**
* Integration test of {@link SrpConnection} pipeline functionality
@@ -190,6 +193,11 @@ public class SrpConnectionPipelineIntegrationTests extends
verifyResults(Arrays.asList(new Object[] { 1l, "6.4", "6.4" }), actual);
}
@Ignore("https://github.com/spullara/redis-protocol/issues/25")
public void testScriptExists() {
// script_exists only returns one result and it's false
}
protected Object convertResult(Object result) {
Object convertedResult = super.convertResult(result);
if (convertedResult instanceof Reply[]) {
@@ -203,7 +211,11 @@ public class SrpConnectionPipelineIntegrationTests extends
stringTuples.add(new DefaultStringTuple(tuple, new String(tuple.getValue())));
}
return stringTuples;
} else {
} else if(((Reply[]) convertedResult).length > 0 && ((Reply[])convertedResult)[0] instanceof IntegerReply) {
return SrpUtils.asIntegerList((Reply[])convertedResult);
} else if(((Reply[]) convertedResult).length > 0 && ((Reply[])convertedResult)[0] instanceof StatusReply) {
return SrpUtils.asStatusList((Reply[])convertedResult);
} else {
return SerializationUtils.deserialize(
SrpUtils.toBytesList((Reply[]) convertedResult), stringSerializer);
}

View File

@@ -17,8 +17,8 @@ package org.springframework.data.redis.connection.srp;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assume.assumeTrue;
import static org.junit.Assert.fail;
import java.util.Arrays;
import java.util.List;

View File

@@ -95,6 +95,22 @@ public class SrpConnectionTransactionIntegrationTests extends SrpConnectionPipel
verifyResults(Arrays.asList(new Object[] { "sup", 13l, "suckrcalifrag" }), actual);
}
@Ignore("https://github.com/spullara/redis-protocol/issues/24")
@Test
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testEvalReturnSingleError() {
// SRP issue exec does not report individual ErrorReplys in a MultiBulkReply
// as Exceptions
}
@Ignore("https://github.com/spullara/redis-protocol/issues/24")
@Test
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testEvalShaNotFound() {
// SRP issue exec does not report individual ErrorReplys in a MultiBulkReply
// as Exceptions
}
@Ignore("https://github.com/spullara/redis-protocol/issues/24")
@Test
@IfProfileValue(name = "redisVersion", value = "2.6")
@@ -119,6 +135,14 @@ public class SrpConnectionTransactionIntegrationTests extends SrpConnectionPipel
// as Exceptions
}
@Test(expected = UnsupportedOperationException.class)
@IfProfileValue(name = "redisVersion", value = "2.6")
public void testScriptKill() {
// Impossible to call script kill in a tx because you can't issue the
// exec command while Redis is running a script
connection.scriptKill();
}
protected void initConnection() {
connection.multi();
}