diff --git a/src/main/java/org/springframework/data/redis/connection/DefaultStringTuple.java b/src/main/java/org/springframework/data/redis/connection/DefaultStringTuple.java index bc527e9a9..acbe48792 100644 --- a/src/main/java/org/springframework/data/redis/connection/DefaultStringTuple.java +++ b/src/main/java/org/springframework/data/redis/connection/DefaultStringTuple.java @@ -79,4 +79,8 @@ public class DefaultStringTuple extends DefaultTuple implements StringTuple { } return false; } + + public String toString() { + return "DefaultStringTuple[value=" + getValueAsString() + ", score=" + getScore() + "]"; + } } \ No newline at end of file diff --git a/src/main/java/org/springframework/data/redis/connection/srp/SrpUtils.java b/src/main/java/org/springframework/data/redis/connection/srp/SrpUtils.java index 04c433591..a57ccef5e 100644 --- a/src/main/java/org/springframework/data/redis/connection/srp/SrpUtils.java +++ b/src/main/java/org/springframework/data/redis/connection/srp/SrpUtils.java @@ -137,7 +137,10 @@ abstract class SrpUtils { } static Set convertTuple(MultiBulkReply zrange) { - Reply[] byteArrays = zrange.data(); + return convertTuple(zrange.data()); + } + + static Set convertTuple(Reply[] byteArrays) { Set tuples = new LinkedHashSet(byteArrays.length / 2 + 1); for (int i = 0; i < byteArrays.length; i++) { diff --git a/src/main/java/org/springframework/data/redis/serializer/SerializationUtils.java b/src/main/java/org/springframework/data/redis/serializer/SerializationUtils.java index 759adf2bd..b922ec0c4 100644 --- a/src/main/java/org/springframework/data/redis/serializer/SerializationUtils.java +++ b/src/main/java/org/springframework/data/redis/serializer/SerializationUtils.java @@ -17,12 +17,14 @@ package org.springframework.data.redis.serializer; import java.util.ArrayList; import java.util.Collection; +import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; +import java.util.Map; import java.util.Set; /** - * Utility class with various serialization-related methods. + * Utility class with various serialization-related methods. * * @author Costin Leau */ @@ -65,4 +67,17 @@ public abstract class SerializationUtils { public static Collection deserialize(Collection rawValues, RedisSerializer redisSerializer) { return deserializeValues(rawValues, List.class, redisSerializer); } + + public static Map deserialize(Map rawValues, + RedisSerializer redisSerializer) { + if (rawValues == null) { + return null; + } + Map ret = new LinkedHashMap(rawValues.size()); + for (Map.Entry entry : rawValues.entrySet()) { + ret.put(redisSerializer.deserialize(entry.getKey()), + redisSerializer.deserialize(entry.getValue())); + } + return ret; + } } \ No newline at end of file diff --git a/src/test/java/org/springframework/data/redis/connection/AbstractConnectionIntegrationTests.java b/src/test/java/org/springframework/data/redis/connection/AbstractConnectionIntegrationTests.java index 4d8b25877..d0609ad71 100644 --- a/src/test/java/org/springframework/data/redis/connection/AbstractConnectionIntegrationTests.java +++ b/src/test/java/org/springframework/data/redis/connection/AbstractConnectionIntegrationTests.java @@ -16,13 +16,19 @@ package org.springframework.data.redis.connection; -import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; 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 java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Properties; @@ -38,9 +44,11 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataAccessException; import org.springframework.data.redis.Address; import org.springframework.data.redis.Person; +import org.springframework.data.redis.connection.RedisListCommands.Position; +import org.springframework.data.redis.connection.RedisZSetCommands.Aggregate; import org.springframework.data.redis.connection.SortParameters.Order; +import org.springframework.data.redis.connection.StringRedisConnection.StringTuple; import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; -import org.springframework.data.redis.connection.rjc.RjcConnectionFactory; import org.springframework.data.redis.connection.srp.SrpConnectionFactory; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer; @@ -49,6 +57,7 @@ import org.springframework.data.redis.serializer.StringRedisSerializer; /** * Base test class for AbstractConnection integration tests + * * @author Costin Leau * @author Jennifer Hickey * @@ -56,15 +65,15 @@ import org.springframework.data.redis.serializer.StringRedisSerializer; public abstract class AbstractConnectionIntegrationTests { protected StringRedisConnection connection; - protected RedisSerializer serializer = new JdkSerializationRedisSerializer(); - protected RedisSerializer stringSerializer = new StringRedisSerializer(); + protected RedisSerializer serializer = new JdkSerializationRedisSerializer(); + protected RedisSerializer stringSerializer = new StringRedisSerializer(); - private static final String listName = "test-list"; private static final byte[] EMPTY_ARRAY = new byte[0]; - @Autowired - private RedisConnectionFactory connectionFactory; + protected List actual = new ArrayList(); + @Autowired + protected RedisConnectionFactory connectionFactory; @Before public void setUp() { @@ -73,17 +82,66 @@ public abstract class AbstractConnectionIntegrationTests { @After public void tearDown() { + try { + connection.flushDb(); + } catch (Exception e) { + // Connection may be closed in certain cases, like after pub/sub + // tests + } connection.close(); connection = null; } @Test - public void testLPush() throws Exception { - byte[] val = "bar".getBytes(); - Long index = connection.lPush(listName.getBytes(), val); - if (index != null) { - assertEquals((Long) (index + 1), connection.lPush(listName.getBytes(), val)); - } + public void testExpire() throws Exception { + connection.set("exp", "true"); + assertTrue(connection.expire("exp", 1)); + assertFalse(exists("exp", 2000l)); + } + + @Test + public void testExpireAt() throws Exception { + connection.set("exp2", "true"); + assertTrue(connection.expireAt("exp2", System.currentTimeMillis() / 1000 + 1)); + assertFalse(exists("exp2", 2000l)); + } + + @Test + public void testPersist() throws Exception { + connection.set("exp3", "true"); + actual.add(connection.expire("exp3", 1)); + actual.add(connection.persist("exp3")); + Thread.sleep(1500); + actual.add(connection.exists("exp3")); + verifyResults(Arrays.asList(new Object[] { true, true, true }), actual); + } + + @Test + public void testSetEx() throws Exception { + connection.setEx("expy", 1l, "yep"); + assertEquals("yep", connection.get("expy")); + assertFalse(exists("expy", 2000l)); + } + + @Test + public void testBRPopTimeout() throws Exception { + actual.add(connection.bRPop(1, "alist")); + Thread.sleep(1500l); + verifyResults(Arrays.asList(new Object[] { null }), actual); + } + + @Test + public void testBLPopTimeout() throws Exception { + actual.add(connection.bLPop(1, "alist")); + Thread.sleep(1500l); + verifyResults(Arrays.asList(new Object[] { null }), actual); + } + + @Test + public void testBRPopLPushTimeout() throws Exception { + actual.add(connection.bRPopLPush(1, "alist", "foo")); + Thread.sleep(1500l); + verifyResults(Arrays.asList(new Object[] { null }), actual); } @Test @@ -91,14 +149,10 @@ public abstract class AbstractConnectionIntegrationTests { String key = "foo"; String value = "blabla"; connection.set(key.getBytes(), value.getBytes()); - assertEquals(value, new String(connection.get(key.getBytes()))); + actual.add(connection.get(key)); + verifyResults(new ArrayList(Collections.singletonList(value)), actual); } - private boolean isJredis() { - return connection.getClass().getSimpleName().startsWith("Jredis"); - } - - @Test public void testByteValue() { String value = UUID.randomUUID().toString(); @@ -114,7 +168,8 @@ public abstract class AbstractConnectionIntegrationTests { @Test public void testPingPong() throws Exception { - assertEquals("PONG", connection.ping()); + actual.add(connection.ping()); + verifyResults(new ArrayList(Collections.singletonList("PONG")), actual); } @Test @@ -122,8 +177,9 @@ public abstract class AbstractConnectionIntegrationTests { String key = "bitset-test"; connection.setBit(key, 0, false); connection.setBit(key, 1, true); - assertTrue(!connection.getBit(key, 0)); - assertTrue(connection.getBit(key, 1)); + actual.add(connection.getBit(key, 0)); + actual.add(connection.getBit(key, 1)); + verifyResults(Arrays.asList(new Object[] { false, true }), actual); } @Test @@ -133,7 +189,6 @@ public abstract class AbstractConnectionIntegrationTests { assertTrue("at least 5 settings should be present", info.size() >= 5); String version = info.getProperty("redis_version"); assertNotNull(version); - System.out.println(info); } @Test @@ -141,6 +196,7 @@ public abstract class AbstractConnectionIntegrationTests { connection.decr(EMPTY_ARRAY); try { connection.decr((String) null); + fail("Decrement should fail with null key"); } catch (Exception ex) { // expected } @@ -152,6 +208,7 @@ public abstract class AbstractConnectionIntegrationTests { connection.append(key, EMPTY_ARRAY); try { connection.append(key, null); + fail("Append should fail with null value"); } catch (DataAccessException ex) { // expected } @@ -163,6 +220,7 @@ public abstract class AbstractConnectionIntegrationTests { connection.hExists(key, EMPTY_ARRAY); try { connection.hExists(key, null); + fail("hExists should fail with null key"); } catch (DataAccessException ex) { // expected } @@ -176,6 +234,7 @@ public abstract class AbstractConnectionIntegrationTests { connection.hSet(key, field, EMPTY_ARRAY); try { connection.hSet(key, field, null); + fail("hSet should fail with null value"); } catch (DataAccessException ex) { // expected } @@ -184,24 +243,13 @@ public abstract class AbstractConnectionIntegrationTests { @Test public void testNullSerialization() throws Exception { String[] keys = new String[] { "~", "[" }; - List mGet = connection.mGet(keys); - assertEquals(2, mGet.size()); - assertNull(mGet.get(0)); - assertNull(mGet.get(1)); + actual.add(connection.mGet(keys)); + verifyResults(Arrays.asList(new Object[] { Arrays.asList(new String[] { null, null }) }), + actual); StringRedisTemplate stringTemplate = new StringRedisTemplate(connectionFactory); List multiGet = stringTemplate.opsForValue().multiGet(Arrays.asList(keys)); - assertEquals(2, multiGet.size()); - assertNull(multiGet.get(0)); - assertNull(multiGet.get(1)); - } - - @Test - public void testNullCollections() throws Exception { - connection.openPipeline(); - assertNull(connection.keys("~*")); - assertNull(connection.hKeys("~")); - connection.closePipeline(); + assertEquals(Arrays.asList(new String[] { null, null }), multiGet); } @Test @@ -219,9 +267,9 @@ public abstract class AbstractConnectionIntegrationTests { Thread th = new Thread(new Runnable() { public void run() { - // sleep 1 second to let the registration happen + // sleep 1/2 second to let the registration happen try { - Thread.currentThread().sleep(2000); + Thread.sleep(500); } catch (InterruptedException ex) { throw new RuntimeException(ex); } @@ -230,18 +278,21 @@ public abstract class AbstractConnectionIntegrationTests { RedisConnection connection2 = connectionFactory.getConnection(); connection2.publish(expectedChannel.getBytes(), expectedMessage.getBytes()); connection2.close(); - // In some clients, unsubscribe happens async of message receipt, so not all - // messages may be received if unsubscribing now. Connection.close in teardown + // In some clients, unsubscribe happens async of message + // receipt, so not all + // messages may be received if unsubscribing now. + // Connection.close in teardown // will take care of unsubscribing. - if(!(isAsync())) { - connection.getSubscription().unsubscribe(); + if (!(isAsync())) { + connection.getSubscription().unsubscribe(); } } }); th.start(); connection.subscribe(listener, expectedChannel.getBytes()); - // Not all providers block on subscribe, give some time for messages to be received + // Not all providers block on subscribe, give some time for messages to + // be received Message message = messages.poll(5, TimeUnit.SECONDS); assertNotNull(message); assertEquals(expectedMessage, new String(message.getBody())); @@ -250,10 +301,6 @@ public abstract class AbstractConnectionIntegrationTests { @Test public void testPubSubWithPatterns() throws Exception { - if(isRjc()) { - // TODO Pattern matching currently broken in RJC, see DATAREDIS-120 - return; - } final String expectedPattern = "channel*"; final String expectedMessage = "msg"; final BlockingDeque messages = new LinkedBlockingDeque(); @@ -268,9 +315,9 @@ public abstract class AbstractConnectionIntegrationTests { Thread th = new Thread(new Runnable() { public void run() { - // sleep 1 second to let the registration happen + // sleep 1/2 second to let the registration happen try { - Thread.currentThread().sleep(1500); + Thread.sleep(500); } catch (InterruptedException ex) { throw new RuntimeException(ex); } @@ -280,18 +327,21 @@ public abstract class AbstractConnectionIntegrationTests { connection2.publish("channel1".getBytes(), expectedMessage.getBytes()); connection2.publish("channel2".getBytes(), expectedMessage.getBytes()); connection2.close(); - // In some clients, unsubscribe happens async of message receipt, so not all - // messages may be received if unsubscribing now. Connection.close in teardown + // In some clients, unsubscribe happens async of message + // receipt, so not all + // messages may be received if unsubscribing now. + // Connection.close in teardown // will take care of unsubscribing. - if(!(isAsync())) { - connection.getSubscription().pUnsubscribe(expectedPattern.getBytes()); + if (!(isAsync())) { + connection.getSubscription().pUnsubscribe(expectedPattern.getBytes()); } } }); th.start(); connection.pSubscribe(listener, expectedPattern); - // Not all providers block on subscribe (Lettuce does not), give some time for messages to be received + // Not all providers block on subscribe (Lettuce does not), give some + // time for messages to be received Message message = messages.poll(5, TimeUnit.SECONDS); assertNotNull(message); assertEquals(expectedMessage, new String(message.getBody())); @@ -300,74 +350,20 @@ public abstract class AbstractConnectionIntegrationTests { assertEquals(expectedMessage, new String(message.getBody())); } - //@Test - public void testExecuteNative() throws Exception { - //connection.execute("PiNg"); - connection.execute("ZADD", getClass() + "#testExecuteNative", "0.9090", "item"); - connection.execute("iNFo"); - connection.execute("SET ", getClass() + "testSetNative", UUID.randomUUID().toString()); - } - @Test(expected = DataAccessException.class) public void exceptionExecuteNative() throws Exception { connection.execute("ZadD", getClass() + "#foo\t0.90\titem"); } - @Test(expected = RedisPipelineException.class) - public void testExceptionExecuteNativeWithPipeline() throws Exception { - connection.openPipeline(); - connection.execute("iNFo"); - connection.execute("SET ", getClass() + "testSetNative", UUID.randomUUID().toString()); - connection.execute("ZadD", getClass() + "#foo\t0.90\titem"); - connection.closePipeline(); - } - - @Test - public void testExecuteNativeWithPipeline() throws Exception { - String key1 = getClass() + "#ExecuteNativeWithPipeline#1"; - String value1 = UUID.randomUUID().toString(); - String key2 = getClass() + "#ExecuteNativeWithPipeline#2"; - String value2 = UUID.randomUUID().toString(); - - connection.openPipeline(); - connection.execute("SET", key1, value1); - connection.execute("SET", key2, value2); - connection.execute("GET", key1); - connection.execute("GET", key2); - List result = connection.closePipeline(); - assertEquals(4, result.size()); - System.out.println(result.get(2)); - System.out.println(result.get(3)); - assertArrayEquals(value1.getBytes(), (byte[]) result.get(2)); - assertArrayEquals(value2.getBytes(), (byte[]) result.get(3)); - } - - @Test - public void testHashMethod() throws Exception { - String hash = getClass() + ":hashtest"; - String key1 = UUID.randomUUID().toString(); - String key2 = UUID.randomUUID().toString(); - connection.hSet(hash, key1, UUID.randomUUID().toString()); - connection.hSet(hash, key2, UUID.randomUUID().toString()); - - Map hashMap = connection.hGetAll(hash); - assertTrue(hashMap.size() >= 2); - assertTrue(hashMap.containsKey(key1)); - assertTrue(hashMap.containsKey(key2)); - } - @Test public void testMultiExec() throws Exception { - byte[] key = "key".getBytes(); - byte[] value = "value".getBytes(); - connection.multi(); - connection.set(key, value); - assertNull(connection.get(key)); + connection.set("key", "value"); + assertNull(connection.get("key")); List results = connection.exec(); assertEquals(2, results.size()); - assertEquals("OK", new String((byte[])results.get(0))); - assertEquals(new String(value), new String((byte[])results.get(1))); + assertEquals("value", new String((byte[]) results.get(1))); + assertEquals("value", connection.get("key")); } @Test @@ -381,48 +377,792 @@ public abstract class AbstractConnectionIntegrationTests { testMultiExec(); } - @Test - public void testBlPopTimeout() { - assertNull(connection.bLPop(1, "lclist")); + public void testWatch() throws Exception { + connection.set("testitnow", "willdo"); + connection.watch("testitnow".getBytes()); + connection.get("testitnow"); + DefaultStringRedisConnection conn2 = new DefaultStringRedisConnection( + connectionFactory.getConnection()); + conn2.set("testitnow", "something"); + conn2.close(); + connection.multi(); + connection.set("testitnow", "somethingelse"); + actual.add(connection.exec()); + actual.add(connection.get("testitnow")); + verifyResults(Arrays.asList(new Object[] { null, "something" }), actual); } @Test - public void testBlPop() { - connection.lPush("poplist", "foo"); - connection.lPush("poplist", "bar"); - assertEquals(Arrays.asList(new String[] {"poplist", "bar"}), connection.bLPop(1, "poplist", "otherlist")); + public void testUnwatch() throws Exception { + connection.set("testitnow", "willdo"); + connection.watch("testitnow".getBytes()); + connection.unwatch(); + connection.multi(); + DefaultStringRedisConnection conn2 = new DefaultStringRedisConnection( + connectionFactory.getConnection()); + conn2.set("testitnow", "something"); + connection.set("testitnow", "somethingelse"); + assertNotNull(connection.exec()); + assertEquals("somethingelse", connection.get("testitnow")); } @Test - public void testBRPop() { - connection.rPush("rpoplist", "bar"); - connection.rPush("rpoplist", "foo"); - assertEquals(Arrays.asList(new String[] {"rpoplist", "foo"}), connection.bRPop(1, "rpoplist")); - } - - @Test - public void testBRPopTimeout() { - assertNull(connection.bRPop(1, "rclist")); + public void testSort() { + actual.add(connection.rPush("sortlist", "foo")); + actual.add(connection.rPush("sortlist", "bar")); + actual.add(connection.rPush("sortlist", "baz")); + actual.add(connection.sort("sortlist", new DefaultSortParameters(null, Order.ASC, true))); + verifyResults( + Arrays.asList(new Object[] { 1l, 2l, 3l, + Arrays.asList(new String[] { "bar", "baz", "foo" }) }), actual); } @Test public void testSortStore() { - connection.del("sortlist"); - connection.rPush("sortlist", "foo"); - connection.rPush("sortlist", "bar"); - connection.rPush("sortlist", "baz"); - assertEquals(Long.valueOf(3), - connection.sort("sortlist", new DefaultSortParameters(null, Order.ASC, true), "newlist")); - assertEquals(Arrays.asList(new String[] {"bar", "baz", "foo"}), connection.lRange("newlist", 0, 9)); + actual.add(connection.rPush("sortlist", "foo")); + actual.add(connection.rPush("sortlist", "bar")); + actual.add(connection.rPush("sortlist", "baz")); + actual.add(connection.sort("sortlist", new DefaultSortParameters(null, Order.ASC, true), + "newlist")); + actual.add(connection.lRange("newlist", 0, 9)); + verifyResults( + Arrays.asList(new Object[] { 1l, 2l, 3l, 3l, + Arrays.asList(new String[] { "bar", "baz", "foo" }) }), actual); + } + + @Test + public void testDbSize() { + connection.set("dbparam", "foo"); + assertTrue(connection.dbSize() > 0); + } + + @Test + public void testFlushDb() { + connection.flushDb(); + actual.add(connection.dbSize()); + verifyResults(Arrays.asList(new Object[] { 0l }), actual); + } + + @Test + public void testGetConfig() { + List config = connection.getConfig("*"); + assertTrue(!config.isEmpty()); + } + + @Test + public void testEcho() { + actual.add(connection.echo("Hello World")); + verifyResults(Arrays.asList(new Object[] { "Hello World" }), actual); + } + + @Test + public void testExists() { + connection.set("existent", "true"); + actual.add(connection.exists("existent")); + actual.add(connection.exists("nonexistent")); + verifyResults(Arrays.asList(new Object[] { true, false }), actual); + } + + @Test + public void testKeys() throws Exception { + connection.set("keytest", "true"); + assertTrue(connection.keys("key*").contains("keytest")); + } + + @Test + public void testRandomKey() { + connection.set("some", "thing"); + assertNotNull(connection.randomKey()); + } + + @Test + public void testRename() { + connection.set("renametest", "testit"); + connection.rename("renametest", "newrenametest"); + actual.add(connection.get("newrenametest")); + actual.add(connection.exists("renametest")); + verifyResults(Arrays.asList(new Object[] { "testit", false }), actual); + } + + @Test + public void testRenameNx() { + connection.set("nxtest", "testit"); + actual.add(connection.renameNX("nxtest", "newnxtest")); + actual.add(connection.get("newnxtest")); + actual.add(connection.exists("nxtest")); + verifyResults(Arrays.asList(new Object[] { true, "testit", false }), actual); + } + + @Test + public void testTtl() { + connection.set("whatup", "yo"); + actual.add(connection.ttl("whatup")); + verifyResults(Arrays.asList(new Object[] { -1L }), actual); + } + + @Test + public void testType() { + connection.set("something", "yo"); + assertEquals(DataType.STRING, connection.type("something")); + } + + @Test + public void testGetSet() { + connection.set("testGS", "1"); + actual.add(connection.getSet("testGS", "2")); + actual.add(connection.get("testGS")); + verifyResults(Arrays.asList(new Object[] { "1", "2" }), actual); + } + + @Test + public void testMSet() { + Map vals = new HashMap(); + vals.put("color", "orange"); + vals.put("size", "1"); + connection.mSetString(vals); + actual.add(connection.mGet("color", "size")); + verifyResults( + Arrays.asList(new Object[] { Arrays.asList(new String[] { "orange", "1" }) }), + actual); + } + + @Test + public void testMSetNx() { + Map vals = new HashMap(); + vals.put("height", "5"); + vals.put("width", "1"); + connection.mSetNXString(vals); + actual.add(connection.mGet("height", "width")); + verifyResults(Arrays.asList(new Object[] { Arrays.asList(new String[] { "5", "1" }) }), + actual); + } + + @Test + public void testSetNx() { + actual.add(connection.setNX("notaround", "54")); + actual.add(connection.get("notaround")); + actual.add(connection.setNX("notaround", "55")); + actual.add(connection.get("notaround")); + verifyResults(Arrays.asList(new Object[] { true, "54", false, "54" }), actual); + } + + @Test + public void testGetRangeSetRange() { + connection.set("rangekey", "supercalifrag"); + actual.add(connection.getRange("rangekey", 0l, 2l)); + connection.setRange("rangekey", "ck", 2); + actual.add(connection.get("rangekey")); + verifyResults(Arrays.asList(new Object[] { "sup", "suckrcalifrag" }), actual); + } + + @Test + public void testDecrByIncrBy() { + connection.set("tdb", "4"); + actual.add(connection.decrBy("tdb", 3l)); + actual.add(connection.incrBy("tdb", 7l)); + verifyResults(Arrays.asList(new Object[] { 1l, 8l }), actual); + } + + @Test + public void testIncDecr() { + connection.set("incrtest", "0"); + actual.add(connection.incr("incrtest")); + actual.add(connection.get("incrtest")); + actual.add(connection.decr("incrtest")); + actual.add(connection.get("incrtest")); + verifyResults(Arrays.asList(new Object[] { 1l, "1", 0l, "0" }), actual); + } + + @Test + public void testStrLen() { + connection.set("strlentest", "cat"); + actual.add(connection.strLen("strlentest")); + verifyResults(Arrays.asList(new Object[] { 3l }), actual); + } + + // List operations + + @Test + public void testBLPop() { + actual.add(connection.lPush("poplist", "foo")); + actual.add(connection.lPush("poplist", "bar")); + actual.add(connection.bLPop(100, "poplist", "otherlist")); + verifyResults( + Arrays.asList(new Object[] { 1l, 2l, + Arrays.asList(new String[] { "poplist", "bar" }) }), actual); + } + + @Test + public void testBRPop() { + actual.add(connection.rPush("rpoplist", "bar")); + actual.add(connection.rPush("rpoplist", "foo")); + actual.add(connection.bRPop(1, "rpoplist")); + verifyResults( + Arrays.asList(new Object[] { 1l, 2l, + Arrays.asList(new String[] { "rpoplist", "foo" }) }), actual); + } + + @Test + public void testLInsert() { + actual.add(connection.rPush("MyList", "hello")); + actual.add(connection.rPush("MyList", "world")); + actual.add(connection.lInsert("MyList", Position.AFTER, "hello", "big")); + actual.add(connection.lRange("MyList", 0, -1)); + actual.add(connection.lInsert("MyList", Position.BEFORE, "big", "very")); + actual.add(connection.lRange("MyList", 0, -1)); + verifyResults( + Arrays.asList(new Object[] { 1l, 2l, 3l, + Arrays.asList(new String[] { "hello", "big", "world" }), 4l, + Arrays.asList(new String[] { "hello", "very", "big", "world" }) }), actual); + } + + @Test + public void testLPop() { + actual.add(connection.rPush("PopList", "hello")); + actual.add(connection.rPush("PopList", "world")); + actual.add(connection.lPop("PopList")); + verifyResults(Arrays.asList(new Object[] { 1l, 2l, "hello" }), actual); + } + + @Test + public void testLRem() { + actual.add(connection.rPush("PopList", "hello")); + actual.add(connection.rPush("PopList", "big")); + actual.add(connection.rPush("PopList", "world")); + actual.add(connection.rPush("PopList", "hello")); + actual.add(connection.lRem("PopList", 2, "hello")); + actual.add(connection.lRange("PopList", 0, -1)); + verifyResults( + Arrays.asList(new Object[] { 1l, 2l, 3l, 4l, 2l, + Arrays.asList(new String[] { "big", "world" }) }), actual); + } + + @Test + public void testLSet() { + actual.add(connection.rPush("PopList", "hello")); + actual.add(connection.rPush("PopList", "big")); + actual.add(connection.rPush("PopList", "world")); + connection.lSet("PopList", 1, "cruel"); + actual.add(connection.lRange("PopList", 0, -1)); + verifyResults( + Arrays.asList(new Object[] { 1l, 2l, 3l, + Arrays.asList(new String[] { "hello", "cruel", "world" }) }), actual); + } + + @Test + public void testLTrim() { + actual.add(connection.rPush("PopList", "hello")); + actual.add(connection.rPush("PopList", "big")); + actual.add(connection.rPush("PopList", "world")); + connection.lTrim("PopList", 1, -1); + actual.add(connection.lRange("PopList", 0, -1)); + verifyResults( + Arrays.asList(new Object[] { 1l, 2l, 3l, + Arrays.asList(new String[] { "big", "world" }) }), actual); + } + + @Test + public void testRPop() { + actual.add(connection.rPush("PopList", "hello")); + actual.add(connection.rPush("PopList", "world")); + actual.add(connection.rPop("PopList")); + verifyResults(Arrays.asList(new Object[] { 1l, 2l, "world" }), actual); + } + + @Test + public void testRPopLPush() { + actual.add(connection.rPush("PopList", "hello")); + actual.add(connection.rPush("PopList", "world")); + actual.add(connection.rPush("pop2", "hey")); + actual.add(connection.rPopLPush("PopList", "pop2")); + actual.add(connection.lRange("PopList", 0, -1)); + actual.add(connection.lRange("pop2", 0, -1)); + verifyResults( + Arrays.asList(new Object[] { 1l, 2l, 1l, "world", + Arrays.asList(new String[] { "hello" }), + Arrays.asList(new String[] { "world", "hey" }) }), actual); + + } + + @Test + public void testBRPopLPush() { + actual.add(connection.rPush("PopList", "hello")); + actual.add(connection.rPush("PopList", "world")); + actual.add(connection.rPush("pop2", "hey")); + actual.add(connection.bRPopLPush(1, "PopList", "pop2")); + actual.add(connection.lRange("PopList", 0, -1)); + actual.add(connection.lRange("pop2", 0, -1)); + verifyResults( + Arrays.asList(new Object[] { 1l, 2l, 1l, "world", + Arrays.asList(new String[] { "hello" }), + Arrays.asList(new String[] { "world", "hey" }) }), actual); + } + + @Test + public void testLPushX() { + actual.add(connection.rPush("mylist", "hi")); + actual.add(connection.lPushX("mylist", "foo")); + actual.add(connection.lRange("mylist", 0, -1)); + verifyResults( + Arrays.asList(new Object[] { 1l, 2l, Arrays.asList(new String[] { "foo", "hi" }) }), + actual); + } + + @Test + public void testRPushX() { + actual.add(connection.rPush("mylist", "hi")); + actual.add(connection.rPushX("mylist", "foo")); + actual.add(connection.lRange("mylist", 0, -1)); + verifyResults( + Arrays.asList(new Object[] { 1l, 2l, Arrays.asList(new String[] { "hi", "foo" }) }), + actual); + } + + @Test + public void testLIndex() { + actual.add(connection.lPush("testylist", "foo")); + actual.add(connection.lIndex("testylist", 0)); + verifyResults(Arrays.asList(new Object[] { 1l, "foo" }), actual); + } + + @Test + public void testLPush() throws Exception { + actual.add(connection.lPush("testlist", "bar")); + actual.add(connection.lPush("testlist", "baz")); + actual.add(connection.lRange("testlist", 0, -1)); + verifyResults(Arrays.asList(new Object[] { 1l, 2l, + Arrays.asList(new String[] { "baz", "bar" }) }), actual); + } + + // Set operations + + @Test + public void testSAdd() { + connection.sAdd("myset", "foo"); + connection.sAdd("myset", "bar"); + assertEquals(new HashSet(Arrays.asList(new String[] { "foo", "bar" })), + connection.sMembers("myset")); + } + + @Test + public void testSCard() { + connection.sAdd("myset", "foo"); + connection.sAdd("myset", "bar"); + assertEquals(Long.valueOf(2), connection.sCard("myset")); + } + + @Test + public void testSDiff() { + connection.sAdd("myset", "foo"); + connection.sAdd("myset", "bar"); + connection.sAdd("otherset", "bar"); + assertEquals(new HashSet(Collections.singletonList("foo")), + connection.sDiff("myset", "otherset")); + } + + @Test + public void testSDiffStore() { + connection.sAdd("myset", "foo"); + connection.sAdd("myset", "bar"); + connection.sAdd("otherset", "bar"); + connection.sDiffStore("thirdset", "myset", "otherset"); + assertEquals(new HashSet(Collections.singletonList("foo")), + connection.sMembers("thirdset")); + } + + @Test + public void testSInter() { + connection.sAdd("myset", "foo"); + connection.sAdd("myset", "bar"); + connection.sAdd("otherset", "bar"); + assertEquals(new HashSet(Collections.singletonList("bar")), + connection.sInter("myset", "otherset")); + } + + @Test + public void testSInterStore() { + connection.sAdd("myset", "foo"); + connection.sAdd("myset", "bar"); + connection.sAdd("otherset", "bar"); + connection.sInterStore("thirdset", "myset", "otherset"); + assertEquals(new HashSet(Collections.singletonList("bar")), + connection.sMembers("thirdset")); + } + + @Test + public void testSIsMember() { + connection.sAdd("myset", "foo"); + connection.sAdd("myset", "bar"); + assertTrue(connection.sIsMember("myset", "foo")); + assertFalse(connection.sIsMember("myset", "baz")); + } + + @Test + public void testSMove() { + connection.sAdd("myset", "foo"); + connection.sAdd("myset", "bar"); + connection.sAdd("otherset", "bar"); + assertTrue(connection.sMove("myset", "otherset", "foo")); + assertEquals(new HashSet(Arrays.asList(new String[] { "foo", "bar" })), + connection.sMembers("otherset")); + } + + @Test + public void testSPop() { + connection.sAdd("myset", "foo"); + connection.sAdd("myset", "bar"); + assertTrue(new HashSet(Arrays.asList(new String[] { "foo", "bar" })) + .contains(connection.sPop("myset"))); + } + + @Test + public void testSRandMember() { + connection.sAdd("myset", "foo"); + connection.sAdd("myset", "bar"); + assertTrue(new HashSet(Arrays.asList(new String[] { "foo", "bar" })) + .contains(connection.sRandMember("myset"))); + } + + @Test + public void testSRem() { + connection.sAdd("myset", "foo"); + connection.sAdd("myset", "bar"); + assertTrue(connection.sRem("myset", "foo")); + assertFalse(connection.sRem("myset", "baz")); + assertEquals(new HashSet(Collections.singletonList("bar")), + connection.sMembers("myset")); + } + + @Test + public void testSUnion() { + connection.sAdd("myset", "foo"); + connection.sAdd("myset", "bar"); + connection.sAdd("otherset", "bar"); + connection.sAdd("otherset", "baz"); + assertEquals(new HashSet(Arrays.asList(new String[] { "foo", "bar", "baz" })), + connection.sUnion("myset", "otherset")); + } + + @Test + public void testSUnionStore() { + connection.sAdd("myset", "foo"); + connection.sAdd("myset", "bar"); + connection.sAdd("otherset", "bar"); + connection.sAdd("otherset", "baz"); + connection.sUnionStore("thirdset", "myset", "otherset"); + assertEquals(new HashSet(Arrays.asList(new String[] { "foo", "bar", "baz" })), + connection.sMembers("thirdset")); + } + + // ZSet + + @Test + public void testZAddAndZRange() { + connection.zAdd("myset", 2, "Bob"); + connection.zAdd("myset", 1, "James"); + assertEquals(new LinkedHashSet(Arrays.asList(new String[] { "James", "Bob" })), + connection.zRange("myset", 0, -1)); + } + + @Test + public void testZCard() { + connection.zAdd("myset", 2, "Bob"); + connection.zAdd("myset", 1, "James"); + assertEquals(Long.valueOf(2), connection.zCard("myset")); + } + + @Test + public void testZCount() { + connection.zAdd("myset", 2, "Bob"); + connection.zAdd("myset", 1, "James"); + connection.zAdd("myset", 4, "Joe"); + assertEquals(Long.valueOf(2), connection.zCount("myset", 1, 2)); + } + + @Test + public void testZIncrBy() { + connection.zAdd("myset", 2, "Bob"); + connection.zAdd("myset", 1, "James"); + connection.zAdd("myset", 4, "Joe"); + connection.zIncrBy("myset", 2, "Joe"); + assertEquals(new LinkedHashSet(Collections.singletonList("Joe")), + connection.zRangeByScore("myset", 6, 6)); + } + + @Test + public void testZInterStore() { + connection.zAdd("myset", 2, "Bob"); + connection.zAdd("myset", 1, "James"); + connection.zAdd("myset", 4, "Joe"); + connection.zAdd("otherset", 1, "Bob"); + connection.zAdd("otherset", 4, "James"); + assertEquals(Long.valueOf(2), connection.zInterStore("thirdset", "myset", "otherset")); + assertEquals(new LinkedHashSet(Arrays.asList(new String[] { "Bob", "James" })), + connection.zRange("thirdset", 0, -1)); + } + + @Test + public void testZInterStoreAggWeights() { + connection.zAdd("myset", 2, "Bob"); + connection.zAdd("myset", 1, "James"); + connection.zAdd("myset", 4, "Joe"); + connection.zAdd("otherset", 1, "Bob"); + connection.zAdd("otherset", 4, "James"); + assertEquals(Long.valueOf(2), connection.zInterStore("thirdset", Aggregate.MAX, new int[] { + 2, 3 }, "myset", "otherset")); + assertEquals( + new LinkedHashSet(Arrays.asList(new StringTuple[] { + new DefaultStringTuple("Bob".getBytes(), "Bob", 4d), + new DefaultStringTuple("James".getBytes(), "James", 12d) })), + connection.zRangeWithScores("thirdset", 0, -1)); + } + + @Test + public void testZRangeWithScores() { + connection.zAdd("myset", 2, "Bob"); + connection.zAdd("myset", 1, "James"); + assertEquals( + new LinkedHashSet(Arrays.asList(new StringTuple[] { + new DefaultStringTuple("James".getBytes(), "James", 1d), + new DefaultStringTuple("Bob".getBytes(), "Bob", 2d) })), + connection.zRangeWithScores("myset", 0, -1)); + } + + @Test + public void testZRangeByScore() { + connection.zAdd("myset", 2, "Bob"); + connection.zAdd("myset", 1, "James"); + assertEquals(new LinkedHashSet(Arrays.asList(new String[] { "James" })), + connection.zRangeByScore("myset", 1, 1)); + } + + @Test + public void testZRangeByScoreOffsetCount() { + connection.zAdd("myset", 2, "Bob"); + connection.zAdd("myset", 1, "James"); + assertEquals(new LinkedHashSet(Arrays.asList(new String[] { "Bob" })), + connection.zRangeByScore("myset", 1d, 3d, 1, -1)); + } + + @Test + public void testZRangeByScoreWithScores() { + connection.zAdd("myset", 2, "Bob"); + connection.zAdd("myset", 1, "James"); + assertEquals( + new LinkedHashSet( + Arrays.asList(new StringTuple[] { new DefaultStringTuple("Bob".getBytes(), + "Bob", 2d) })), connection.zRangeByScoreWithScores("myset", 2d, 5d)); + } + + @Test + public void testZRangeByScoreWithScoresOffsetCount() { + connection.zAdd("myset", 2, "Bob"); + connection.zAdd("myset", 1, "James"); + assertEquals( + new LinkedHashSet( + Arrays.asList(new StringTuple[] { new DefaultStringTuple( + "James".getBytes(), "James", 1d) })), + connection.zRangeByScoreWithScores("myset", 1d, 5d, 0, 1)); + } + + @Test + public void testZRevRange() { + connection.zAdd("myset", 2, "Bob"); + connection.zAdd("myset", 1, "James"); + assertEquals(new LinkedHashSet(Arrays.asList(new String[] { "Bob", "James" })), + connection.zRevRange("myset", 0, -1)); + } + + @Test + public void testZRevRangeWithScores() { + connection.zAdd("myset", 2, "Bob"); + connection.zAdd("myset", 1, "James"); + assertEquals( + new LinkedHashSet(Arrays.asList(new StringTuple[] { + new DefaultStringTuple("Bob".getBytes(), "Bob", 2d), + new DefaultStringTuple("James".getBytes(), "James", 1d) })), + connection.zRevRangeWithScores("myset", 0, -1)); + } + + @Test + public void testZRank() { + connection.zAdd("myset", 2, "Bob"); + connection.zAdd("myset", 1, "James"); + assertEquals(Long.valueOf(0), connection.zRank("myset", "James")); + assertEquals(Long.valueOf(1), connection.zRank("myset", "Bob")); + } + + @Test + public void testZRem() { + connection.zAdd("myset", 2, "Bob"); + connection.zAdd("myset", 1, "James"); + assertTrue(connection.zRem("myset", "James")); + assertEquals(new LinkedHashSet(Arrays.asList(new String[] { "Bob" })), + connection.zRange("myset", 0l, -1l)); + } + + @Test + public void testZRemRangeByRank() { + connection.zAdd("myset", 2, "Bob"); + connection.zAdd("myset", 1, "James"); + assertEquals(Long.valueOf(2), connection.zRemRange("myset", 0l, 3l)); + assertTrue(connection.zRange("myset", 0l, -1l).isEmpty()); + } + + @Test + public void testZRemRangeByScore() { + connection.zAdd("myset", 2, "Bob"); + connection.zAdd("myset", 1, "James"); + assertEquals(Long.valueOf(1), connection.zRemRangeByScore("myset", 0d, 1d)); + assertEquals(new LinkedHashSet(Arrays.asList(new String[] { "Bob" })), + connection.zRange("myset", 0l, -1l)); + } + + @Test + public void testZRevRank() { + connection.zAdd("myset", 2, "Bob"); + connection.zAdd("myset", 1, "James"); + connection.zAdd("myset", 3, "Joe"); + assertEquals(Long.valueOf(0), connection.zRevRank("myset", "Joe")); + } + + @Test + public void testZScore() { + connection.zAdd("myset", 2, "Bob"); + connection.zAdd("myset", 1, "James"); + connection.zAdd("myset", 3, "Joe"); + assertEquals(Double.valueOf(3d), connection.zScore("myset", "Joe")); + } + + @Test + public void testZUnionStore() { + connection.zAdd("myset", 2, "Bob"); + connection.zAdd("myset", 1, "James"); + connection.zAdd("myset", 5, "Joe"); + connection.zAdd("otherset", 1, "Bob"); + connection.zAdd("otherset", 4, "James"); + assertEquals(Long.valueOf(3), connection.zUnionStore("thirdset", "myset", "otherset")); + assertEquals( + new LinkedHashSet(Arrays.asList(new String[] { "Bob", "James", "Joe" })), + connection.zRange("thirdset", 0, -1)); + } + + @Test + public void testZUnionStoreAggWeights() { + connection.zAdd("myset", 2, "Bob"); + connection.zAdd("myset", 1, "James"); + connection.zAdd("myset", 4, "Joe"); + connection.zAdd("otherset", 1, "Bob"); + connection.zAdd("otherset", 4, "James"); + assertEquals(Long.valueOf(3), connection.zUnionStore("thirdset", Aggregate.MAX, new int[] { + 2, 3 }, "myset", "otherset")); + assertEquals( + new LinkedHashSet(Arrays.asList(new StringTuple[] { + new DefaultStringTuple("Bob".getBytes(), "Bob", 4d), + new DefaultStringTuple("Joe".getBytes(), "Joe", 8d), + new DefaultStringTuple("James".getBytes(), "James", 12d) })), + connection.zRangeWithScores("thirdset", 0, -1)); + } + + // Hash Ops + + @Test + public void testHSetGet() throws Exception { + String hash = getClass() + ":hashtest"; + String key1 = UUID.randomUUID().toString(); + String key2 = UUID.randomUUID().toString(); + String value1 = "foo"; + String value2 = "bar"; + actual.add(connection.hSet(hash, key1, value1)); + actual.add(connection.hSet(hash, key2, value2)); + actual.add(connection.hGet(hash, key1)); + actual.add(connection.hGetAll(hash)); + Map expected = new HashMap(); + expected.put(key1, value1); + expected.put(key2, value2); + verifyResults(Arrays.asList(new Object[] { true, true, value1, expected }), actual); + } + + @Test + public void testHSetNX() throws Exception { + actual.add(connection.hSetNX("myhash", "key1", "foo")); + actual.add(connection.hSetNX("myhash", "key1", "bar")); + actual.add(connection.hGet("myhash", "key1")); + verifyResults(Arrays.asList(new Object[] { true, false, "foo" }), actual); + } + + @Test + public void testHDel() throws Exception { + connection.hSet("test", "key", "val"); + assertTrue(connection.hDel("test", "key")); + assertFalse(connection.hDel("test", "foo")); + assertFalse(connection.hExists("test", "key")); + } + + @Test + public void testHIncrBy() { + actual.add(connection.hSet("test", "key", "2")); + actual.add(connection.hIncrBy("test", "key", 3l)); + actual.add(connection.hGet("test", "key")); + verifyResults(Arrays.asList(new Object[] { true, 5l, "5" }), actual); + } + + @Test + public void testHKeys() { + connection.hSet("test", "key", "2"); + connection.hSet("test", "key2", "2"); + assertEquals(new LinkedHashSet(Arrays.asList(new String[] { "key", "key2" })), + connection.hKeys("test")); + } + + @Test + public void testHLen() { + actual.add(connection.hSet("test", "key", "2")); + actual.add(connection.hSet("test", "key2", "2")); + actual.add(connection.hLen("test")); + verifyResults(Arrays.asList(new Object[] { true, true, 2l }), actual); + } + + @Test + public void testHMGetSet() { + Map tuples = new HashMap(); + tuples.put("key", "foo"); + tuples.put("key2", "bar"); + connection.hMSet("test", tuples); + actual.add(connection.hMGet("test", "key", "key2")); + verifyResults(Arrays.asList(new Object[] { Arrays.asList(new String[] { "foo", "bar" }) }), + actual); + } + + @Test + public void testHVals() { + actual.add(connection.hSet("test", "key", "foo")); + actual.add(connection.hSet("test", "key2", "bar")); + actual.add(connection.hVals("test")); + verifyResults( + Arrays.asList(new Object[] { true, true, + Arrays.asList(new String[] { "foo", "bar" }) }), actual); + } + + protected void verifyResults(List expected, List actual) { + assertEquals(expected, actual); + } + + private boolean exists(String key, long timeout) { + boolean exists = true; + for (long currentTime = System.currentTimeMillis(); System.currentTimeMillis() + - currentTime < timeout;) { + if (!connection.exists(key)) { + exists = false; + break; + } + } + return exists; } private boolean isAsync() { - return (connectionFactory instanceof LettuceConnectionFactory) || - (connectionFactory instanceof SrpConnectionFactory); - } - - private boolean isRjc() { - return (connectionFactory instanceof RjcConnectionFactory); + return (connectionFactory instanceof LettuceConnectionFactory) + || (connectionFactory instanceof SrpConnectionFactory); } } \ No newline at end of file diff --git a/src/test/java/org/springframework/data/redis/connection/AbstractConnectionPipelineIntegrationTests.java b/src/test/java/org/springframework/data/redis/connection/AbstractConnectionPipelineIntegrationTests.java new file mode 100644 index 000000000..b4e05126d --- /dev/null +++ b/src/test/java/org/springframework/data/redis/connection/AbstractConnectionPipelineIntegrationTests.java @@ -0,0 +1,800 @@ +/* + * Copyright 2011-2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.data.redis.connection; + +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 java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; +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; + +/** + * Base test class for integration tests that execute each operation of a + * Connection while a pipeline is open, verifying that the operations return + * null and the proper values are returned when closing the pipeline. + *

+ * Pipelined results are generally native to the provider and not transformed by + * our {@link RedisConnection}, so this test overrides + * {@link AbstractConnectionIntegrationTests} when result types are different + * + * @author Jennifer Hickey + * + */ +abstract public class AbstractConnectionPipelineIntegrationTests extends + AbstractConnectionIntegrationTests { + + /** + * Individual results from closePipeline should be converted from List to + * LinkedHashSet + **/ + protected boolean convertResultToSet = false; + + /** + * Individual results from closePipeline should be converted to + * {@link Tuple}s + **/ + protected boolean convertResultToTuples = false; + + @Before + public void setUp() { + super.setUp(); + connection.openPipeline(); + } + + @Ignore + public void testByteValue() { + } + + @Ignore + public void testNullKey() throws Exception { + } + + @Ignore + public void testNullValue() throws Exception { + } + + @Ignore + public void testHashNullKey() throws Exception { + } + + @Ignore + public void testHashNullValue() throws Exception { + } + + @Ignore("Pub/Sub not supported while pipelining") + public void testPubSubWithNamedChannels() throws Exception { + } + + @Ignore("Pub/Sub not supported while pipelining") + public void testPubSubWithPatterns() throws Exception { + } + + @Test(expected = RedisPipelineException.class) + public void exceptionExecuteNative() throws Exception { + connection.execute("ZadD", getClass() + "#foo\t0.90\titem"); + connection.closePipeline(); + } + + @Test + public void testExpire() throws Exception { + connection.set("exp", "true"); + actual.add(connection.expire("exp", 1)); + Thread.sleep(2000); + actual.add(connection.exists("exp")); + verifyResults(Arrays.asList(new Object[] { 1l, 0l }), actual); + } + + @Test + public void testExpireAt() throws Exception { + connection.set("exp2", "true"); + actual.add(connection.expireAt("exp2", System.currentTimeMillis() / 1000 + 1)); + Thread.sleep(2000); + actual.add(connection.exists("exp2")); + verifyResults(Arrays.asList(new Object[] { 1l, 0l }), actual); + } + + @Test + public void testPersist() throws Exception { + connection.set("exp3", "true"); + actual.add(connection.expire("exp3", 1)); + actual.add(connection.persist("exp3")); + Thread.sleep(1500); + actual.add(connection.exists("exp3")); + verifyResults(Arrays.asList(new Object[] { 1l, 1l, 1l }), actual); + } + + @Test + public void testSetEx() throws Exception { + connection.setEx("expy", 1l, "yep"); + actual.add(connection.get("expy")); + Thread.sleep(2000); + actual.add(connection.exists("expy")); + verifyResults(Arrays.asList(new Object[] { "yep", 0l }), actual); + } + + @Test + public void testBitSet() throws Exception { + String key = "bitset-test"; + connection.setBit(key, 0, false); + connection.setBit(key, 1, true); + actual.add(connection.getBit(key, 0)); + actual.add(connection.getBit(key, 1)); + verifyResults(Arrays.asList(new Object[] { 0l, 0l, 0l, 1l }), actual); + } + + @Test + public void testDbSize() { + connection.set("dbparam", "foo"); + assertNull(connection.dbSize()); + List results = connection.closePipeline(); + assertEquals(2, results.size()); + assertTrue((Long) results.get(1) > 0); + } + + @SuppressWarnings("rawtypes") + @Test + public void testGetConfig() { + assertNull(connection.getConfig("*")); + List results = convertResults(connection.closePipeline()); + assertEquals(1, results.size()); + assertTrue(!((List) results.get(0)).isEmpty()); + } + + @SuppressWarnings("rawtypes") + @Test + public void testKeys() throws Exception { + connection.set("keytest", "true"); + connection.set("keytest2", "true"); + connection.keys("key*"); + List results = convertResults(connection.closePipeline()); + assertEquals(1, results.size()); + assertTrue(((List) results.get(0)).contains("keytest")); + } + + @Test + public void testRandomKey() { + connection.set("some", "thing"); + assertNull(connection.randomKey()); + List results = convertResults(connection.closePipeline()); + assertEquals(1, results.size()); + assertNotNull(results.get(0)); + } + + @Test + public void testType() { + connection.set("something", "yo"); + assertNull(connection.type("something")); + List results = convertResults(connection.closePipeline()); + assertEquals(1, results.size()); + assertEquals("string", results.get(0)); + } + + @Test + public void testMSetNx() { + Map vals = new HashMap(); + vals.put("height", "5"); + vals.put("width", "1"); + connection.mSetNXString(vals); + assertNull(connection.mGet("height", "width")); + verifyResults(Arrays.asList(new Object[] { 1l, Arrays.asList(new String[] { "5", "1" }) }), + actual); + } + + @Test + public void testSetNx() { + actual.add(connection.setNX("notaround", "54")); + actual.add(connection.get("notaround")); + actual.add(connection.setNX("notaround", "55")); + actual.add(connection.get("notaround")); + verifyResults(Arrays.asList(new Object[] { 1l, "54", 0l, "54" }), actual); + } + + @Test + public void testRenameNx() { + connection.set("nxtest", "testit"); + actual.add(connection.renameNX("nxtest", "newnxtest")); + actual.add(connection.get("newnxtest")); + actual.add(connection.exists("nxtest")); + verifyResults(Arrays.asList(new Object[] { 1l, "testit", 0l }), actual); + } + + @Test + public void testGetRangeSetRange() { + connection.set("rangekey", "supercalifrag"); + actual.add(connection.getRange("rangekey", 0l, 2l)); + connection.setRange("rangekey", "ck", 2); + actual.add(connection.get("rangekey")); + verifyResults(Arrays.asList(new Object[] { "sup", 13l, "suckrcalifrag" }), actual); + } + + @Test + public void testMultiDiscard() throws Exception { + DefaultStringRedisConnection conn2 = new DefaultStringRedisConnection( + connectionFactory.getConnection()); + conn2.set("testitnow", "willdo"); + connection.multi(); + connection.set("testitnow2", "notok"); + connection.discard(); + connection.get("testitnow"); + List convertedResults = convertResults(connection.closePipeline()); + assertEquals(Arrays.asList(new String[] { "willdo" }), convertedResults); + connection.openPipeline(); + // Ensure we can run a new tx after discarding previous one + testMultiExec(); + } + + @Test + public void testMultiExec() throws Exception { + connection.multi(); + connection.set("key", "value"); + assertNull(connection.get("key")); + assertNull(connection.exec()); + List convertedResults = convertResults(connection.closePipeline()); + assertEquals(Arrays.asList(new Object[] { Arrays.asList(new String[] { "OK", "value" }) }), + convertedResults); + } + + @Test + public void testUnwatch() throws Exception { + connection.set("testitnow", "willdo"); + connection.watch("testitnow".getBytes()); + connection.unwatch(); + connection.multi(); + DefaultStringRedisConnection conn2 = new DefaultStringRedisConnection( + connectionFactory.getConnection()); + conn2.set("testitnow", "something"); + connection.set("testitnow", "somethingelse"); + connection.get("testitnow"); + connection.exec(); + List convertedResults = convertResults(connection.closePipeline()); + assertEquals(Arrays.asList(new Object[] { Arrays.asList(new String[] { "OK", + "somethingelse" }) }), convertedResults); + } + + @Test + public void testSAdd() { + convertResultToSet = true; + actual.add(connection.sAdd("myset", "foo")); + actual.add(connection.sAdd("myset", "bar")); + actual.add(connection.sMembers("myset")); + verifyResults( + Arrays.asList(new Object[] { 1l, 1l, + new HashSet(Arrays.asList(new String[] { "foo", "bar" })) }), + actual); + } + + @Test + public void testSCard() { + actual.add(connection.sAdd("myset", "foo")); + actual.add(connection.sAdd("myset", "bar")); + actual.add(connection.sCard("myset")); + verifyResults(Arrays.asList(new Object[] { 1l, 1l, 2l }), actual); + } + + @Test + public void testSDiff() { + convertResultToSet = true; + actual.add(connection.sAdd("myset", "foo")); + actual.add(connection.sAdd("myset", "bar")); + actual.add(connection.sAdd("otherset", "bar")); + actual.add(connection.sDiff("myset", "otherset")); + verifyResults( + Arrays.asList(new Object[] { 1l, 1l, 1l, + new HashSet(Collections.singletonList("foo")) }), actual); + } + + @Test + public void testSDiffStore() { + convertResultToSet = true; + actual.add(connection.sAdd("myset", "foo")); + actual.add(connection.sAdd("myset", "bar")); + actual.add(connection.sAdd("otherset", "bar")); + connection.sDiffStore("thirdset", "myset", "otherset"); + actual.add(connection.sMembers("thirdset")); + verifyResults( + Arrays.asList(new Object[] { 1l, 1l, 1l, 1l, + new HashSet(Collections.singletonList("foo")) }), actual); + } + + @Test + public void testSInter() { + convertResultToSet = true; + actual.add(connection.sAdd("myset", "foo")); + actual.add(connection.sAdd("myset", "bar")); + actual.add(connection.sAdd("otherset", "bar")); + actual.add(connection.sInter("myset", "otherset")); + verifyResults( + Arrays.asList(new Object[] { 1l, 1l, 1l, + new HashSet(Collections.singletonList("bar")) }), actual); + } + + @Test + public void testSInterStore() { + convertResultToSet = true; + actual.add(connection.sAdd("myset", "foo")); + actual.add(connection.sAdd("myset", "bar")); + actual.add(connection.sAdd("otherset", "bar")); + connection.sInterStore("thirdset", "myset", "otherset"); + actual.add(connection.sMembers("thirdset")); + verifyResults( + Arrays.asList(new Object[] { 1l, 1l, 1l, 1l, + new HashSet(Collections.singletonList("bar")) }), actual); + } + + @Test + public void testSIsMember() { + convertResultToSet = true; + actual.add(connection.sAdd("myset", "foo")); + actual.add(connection.sAdd("myset", "bar")); + actual.add(connection.sIsMember("myset", "foo")); + actual.add(connection.sIsMember("myset", "baz")); + verifyResults(Arrays.asList(new Object[] { 1l, 1l, true, false }), actual); + } + + @Test + public void testSMove() { + convertResultToSet = true; + actual.add(connection.sAdd("myset", "foo")); + actual.add(connection.sAdd("myset", "bar")); + actual.add(connection.sAdd("otherset", "bar")); + actual.add(connection.sMove("myset", "otherset", "foo")); + actual.add(connection.sMembers("otherset")); + verifyResults( + Arrays.asList(new Object[] { 1l, 1l, 1l, 1l, + new HashSet(Arrays.asList(new String[] { "foo", "bar" })) }), + actual); + } + + @Test + public void testSPop() { + convertResultToSet = true; + connection.sAdd("myset", "foo"); + connection.sAdd("myset", "bar"); + assertNull(connection.sPop("myset")); + List results = convertResults(connection.closePipeline()); + assertEquals(3, results.size()); + assertTrue(new HashSet(Arrays.asList(new String[] { "foo", "bar" })) + .contains(results.get(2))); + } + + @Test + public void testSRandMember() { + convertResultToSet = true; + connection.sAdd("myset", "foo"); + connection.sAdd("myset", "bar"); + assertNull(connection.sRandMember("myset")); + List results = convertResults(connection.closePipeline()); + assertEquals(3, results.size()); + assertTrue(new HashSet(Arrays.asList(new String[] { "foo", "bar" })) + .contains(results.get(2))); + } + + @Test + public void testSRem() { + convertResultToSet = true; + actual.add(connection.sAdd("myset", "foo")); + actual.add(connection.sAdd("myset", "bar")); + actual.add(connection.sRem("myset", "foo")); + actual.add(connection.sRem("myset", "baz")); + actual.add(connection.sMembers("myset")); + verifyResults( + Arrays.asList(new Object[] { 1l, 1l, 1l, 0l, + new HashSet(Arrays.asList(new String[] { "bar" })) }), actual); + } + + @Test + public void testSUnion() { + convertResultToSet = true; + actual.add(connection.sAdd("myset", "foo")); + actual.add(connection.sAdd("myset", "bar")); + actual.add(connection.sAdd("otherset", "bar")); + actual.add(connection.sAdd("otherset", "baz")); + actual.add(connection.sUnion("myset", "otherset")); + verifyResults( + Arrays.asList(new Object[] { 1l, 1l, 1l, 1l, + new HashSet(Arrays.asList(new String[] { "foo", "bar", "baz" })) }), + actual); + } + + @Test + public void testSUnionStore() { + convertResultToSet = true; + actual.add(connection.sAdd("myset", "foo")); + actual.add(connection.sAdd("myset", "bar")); + actual.add(connection.sAdd("otherset", "bar")); + actual.add(connection.sAdd("otherset", "baz")); + connection.sUnionStore("thirdset", "myset", "otherset"); + actual.add(connection.sMembers("thirdset")); + verifyResults( + Arrays.asList(new Object[] { 1l, 1l, 1l, 1l, 3l, + new HashSet(Arrays.asList(new String[] { "foo", "bar", "baz" })) }), + actual); + } + + @Test + public void testZAddAndZRange() { + actual.add(connection.zAdd("myset", 2, "Bob")); + actual.add(connection.zAdd("myset", 1, "James")); + actual.add(connection.zRange("myset", 0, -1)); + verifyResults(Arrays.asList(new Object[] { 1l, 1l, + Arrays.asList(new String[] { "James", "Bob" }) }), actual); + } + + @Test + public void testZCard() { + actual.add(connection.zAdd("myset", 2, "Bob")); + actual.add(connection.zAdd("myset", 1, "James")); + actual.add(connection.zCard("myset")); + verifyResults(Arrays.asList(new Object[] { 1l, 1l, 2l }), actual); + } + + @Test + public void testZCount() { + actual.add(connection.zAdd("myset", 2, "Bob")); + actual.add(connection.zAdd("myset", 1, "James")); + actual.add(connection.zAdd("myset", 4, "Joe")); + actual.add(connection.zCount("myset", 1, 2)); + verifyResults(Arrays.asList(new Object[] { 1l, 1l, 1l, 2l }), actual); + } + + @Test + public void testZIncrBy() { + actual.add(connection.zAdd("myset", 2, "Bob")); + actual.add(connection.zAdd("myset", 1, "James")); + actual.add(connection.zAdd("myset", 4, "Joe")); + actual.add(connection.zIncrBy("myset", 2, "Joe")); + actual.add(connection.zRangeByScore("myset", 6, 6)); + verifyResults( + Arrays.asList(new Object[] { 1l, 1l, 1l, 6d, Collections.singletonList("Joe") }), + actual); + } + + @Test + public void testZInterStore() { + actual.add(connection.zAdd("myset", 2, "Bob")); + actual.add(connection.zAdd("myset", 1, "James")); + actual.add(connection.zAdd("myset", 4, "Joe")); + actual.add(connection.zAdd("otherset", 1, "Bob")); + actual.add(connection.zAdd("otherset", 4, "James")); + actual.add(connection.zInterStore("thirdset", "myset", "otherset")); + actual.add(connection.zRange("thirdset", 0, -1)); + verifyResults( + Arrays.asList(new Object[] { 1l, 1l, 1l, 1l, 1l, 2l, + Arrays.asList(new String[] { "Bob", "James" }) }), actual); + } + + @Test + public void testZInterStoreAggWeights() { + convertResultToTuples = true; + actual.add(connection.zAdd("myset", 2, "Bob")); + actual.add(connection.zAdd("myset", 1, "James")); + actual.add(connection.zAdd("myset", 4, "Joe")); + actual.add(connection.zAdd("otherset", 1, "Bob")); + actual.add(connection.zAdd("otherset", 4, "James")); + actual.add(connection.zInterStore("thirdset", Aggregate.MAX, new int[] { 2, 3 }, "myset", + "otherset")); + actual.add(connection.zRangeWithScores("thirdset", 0, -1)); + verifyResults( + Arrays.asList(new Object[] { + 1l, + 1l, + 1l, + 1l, + 1l, + 2l, + Arrays.asList(new StringTuple[] { + new DefaultStringTuple("Bob".getBytes(), "Bob", 4d), + new DefaultStringTuple("James".getBytes(), "James", 12d) }) }), + actual); + } + + @Test + public void testZRangeWithScores() { + convertResultToTuples = true; + actual.add(connection.zAdd("myset", 2, "Bob")); + actual.add(connection.zAdd("myset", 1, "James")); + actual.add(connection.zRangeWithScores("myset", 0, -1)); + verifyResults( + Arrays.asList(new Object[] { + 1l, + 1l, + Arrays.asList(new StringTuple[] { + new DefaultStringTuple("James".getBytes(), "James", 1d), + new DefaultStringTuple("Bob".getBytes(), "Bob", 2d) }) }), actual); + } + + @Test + public void testZRangeByScore() { + actual.add(connection.zAdd("myset", 2, "Bob")); + actual.add(connection.zAdd("myset", 1, "James")); + actual.add(connection.zRangeByScore("myset", 1, 1)); + verifyResults( + Arrays.asList(new Object[] { 1l, 1l, Arrays.asList(new String[] { "James" }) }), + actual); + } + + @Test + public void testZRangeByScoreOffsetCount() { + actual.add(connection.zAdd("myset", 2, "Bob")); + actual.add(connection.zAdd("myset", 1, "James")); + actual.add(connection.zRangeByScore("myset", 1d, 3d, 1, -1)); + verifyResults( + Arrays.asList(new Object[] { 1l, 1l, Arrays.asList(new String[] { "Bob" }) }), + actual); + } + + @Test + public void testZRangeByScoreWithScores() { + convertResultToTuples = true; + actual.add(connection.zAdd("myset", 2, "Bob")); + actual.add(connection.zAdd("myset", 1, "James")); + actual.add(connection.zRangeByScoreWithScores("myset", 2d, 5d)); + verifyResults( + Arrays.asList(new Object[] { + 1l, + 1l, + Arrays.asList(new StringTuple[] { new DefaultStringTuple("Bob".getBytes(), + "Bob", 2d) }) }), actual); + } + + @Test + public void testZRangeByScoreWithScoresOffsetCount() { + convertResultToTuples = true; + actual.add(connection.zAdd("myset", 2, "Bob")); + actual.add(connection.zAdd("myset", 1, "James")); + actual.add(connection.zRangeByScoreWithScores("myset", 1d, 5d, 0, 1)); + verifyResults( + Arrays.asList(new Object[] { + 1l, + 1l, + Arrays.asList(new StringTuple[] { new DefaultStringTuple( + "James".getBytes(), "James", 1d) }) }), actual); + } + + @Test + public void testZRevRange() { + actual.add(connection.zAdd("myset", 2, "Bob")); + actual.add(connection.zAdd("myset", 1, "James")); + actual.add(connection.zRevRange("myset", 0, -1)); + verifyResults(Arrays.asList(new Object[] { 1l, 1l, + Arrays.asList(new String[] { "Bob", "James" }) }), actual); + } + + @Test + public void testZRevRangeWithScores() { + convertResultToTuples = true; + actual.add(connection.zAdd("myset", 2, "Bob")); + actual.add(connection.zAdd("myset", 1, "James")); + actual.add(connection.zRevRangeWithScores("myset", 0, -1)); + verifyResults( + Arrays.asList(new Object[] { + 1l, + 1l, + Arrays.asList(new StringTuple[] { + new DefaultStringTuple("Bob".getBytes(), "Bob", 2d), + new DefaultStringTuple("James".getBytes(), "James", 1d) }) }), + actual); + } + + @Test + public void testZRank() { + actual.add(connection.zAdd("myset", 2, "Bob")); + actual.add(connection.zAdd("myset", 1, "James")); + actual.add(connection.zRank("myset", "James")); + actual.add(connection.zRank("myset", "Bob")); + verifyResults(Arrays.asList(new Object[] { 1l, 1l, 0l, 1l }), actual); + } + + @Test + public void testZRem() { + actual.add(connection.zAdd("myset", 2, "Bob")); + actual.add(connection.zAdd("myset", 1, "James")); + actual.add(connection.zRem("myset", "James")); + actual.add(connection.zRange("myset", 0l, -1l)); + verifyResults( + Arrays.asList(new Object[] { 1l, 1l, 1l, Arrays.asList(new String[] { "Bob" }) }), + actual); + } + + @Test + public void testZRemRangeByRank() { + actual.add(connection.zAdd("myset", 2, "Bob")); + actual.add(connection.zAdd("myset", 1, "James")); + actual.add(connection.zRemRange("myset", 0l, 3l)); + actual.add(connection.zRange("myset", 0l, -1l)); + verifyResults(Arrays.asList(new Object[] { 1l, 1l, 2l, new ArrayList() }), actual); + } + + @Test + public void testZRemRangeByScore() { + actual.add(connection.zAdd("myset", 2, "Bob")); + actual.add(connection.zAdd("myset", 1, "James")); + actual.add(connection.zRemRangeByScore("myset", 0d, 1d)); + actual.add(connection.zRange("myset", 0l, -1l)); + verifyResults( + Arrays.asList(new Object[] { 1l, 1l, 1l, Arrays.asList(new String[] { "Bob" }) }), + actual); + } + + @Test + public void testZRevRank() { + actual.add(connection.zAdd("myset", 2, "Bob")); + actual.add(connection.zAdd("myset", 1, "James")); + actual.add(connection.zAdd("myset", 3, "Joe")); + actual.add(connection.zRevRank("myset", "Joe")); + verifyResults(Arrays.asList(new Object[] { 1l, 1l, 1l, 0l }), actual); + } + + @Test + public void testZScore() { + actual.add(connection.zAdd("myset", 2, "Bob")); + actual.add(connection.zAdd("myset", 1, "James")); + actual.add(connection.zAdd("myset", 3, "Joe")); + actual.add(connection.zScore("myset", "Joe")); + verifyResults(Arrays.asList(new Object[] { 1l, 1l, 1l, 3d }), actual); + } + + @Test + public void testZUnionStore() { + actual.add(connection.zAdd("myset", 2, "Bob")); + actual.add(connection.zAdd("myset", 1, "James")); + actual.add(connection.zAdd("myset", 6, "Joe")); + actual.add(connection.zAdd("otherset", 1, "Bob")); + actual.add(connection.zAdd("otherset", 4, "James")); + actual.add(connection.zUnionStore("thirdset", "myset", "otherset")); + actual.add(connection.zRange("thirdset", 0, -1)); + + verifyResults( + Arrays.asList(new Object[] { 1l, 1l, 1l, 1l, 1l, 3l, + Arrays.asList(new String[] { "Bob", "James", "Joe" }) }), actual); + } + + @Test + public void testZUnionStoreAggWeights() { + actual.add(connection.zAdd("myset", 2, "Bob")); + actual.add(connection.zAdd("myset", 1, "James")); + actual.add(connection.zAdd("myset", 4, "Joe")); + actual.add(connection.zAdd("otherset", 1, "Bob")); + actual.add(connection.zAdd("otherset", 4, "James")); + actual.add(connection.zUnionStore("thirdset", Aggregate.MAX, new int[] { 2, 3 }, "myset", + "otherset")); + actual.add(connection.zRangeWithScores("thirdset", 0, -1)); + + verifyResults( + Arrays.asList(new Object[] { + 1l, + 1l, + 1l, + 1l, + 1l, + 3l, + Arrays.asList(new StringTuple[] { + new DefaultStringTuple("Bob".getBytes(), "Bob", 4d), + new DefaultStringTuple("Joe".getBytes(), "Joe", 8d), + new DefaultStringTuple("James".getBytes(), "James", 12d) }) }), + actual); + } + + @Test + public void testHDel() throws Exception { + actual.add(connection.hSet("test", "key", "val")); + actual.add(connection.hDel("test", "key")); + actual.add(connection.hDel("test", "foo")); + actual.add(connection.hExists("test", "key")); + verifyResults(Arrays.asList(new Object[] { 1l, 1l, 0l, 0l }), actual); + } + + @Test + public void testHKeys() { + convertResultToSet = true; + actual.add(connection.hSet("test", "key", "2")); + actual.add(connection.hSet("test", "key2", "2")); + actual.add(connection.hKeys("test")); + verifyResults( + Arrays.asList(new Object[] { 1l, 1l, + new LinkedHashSet(Arrays.asList(new String[] { "key", "key2" })) }), + actual); + } + + @Test + public void testHSetNX() throws Exception { + actual.add(connection.hSetNX("myhash", "key1", "foo")); + actual.add(connection.hSetNX("myhash", "key1", "bar")); + actual.add(connection.hGet("myhash", "key1")); + verifyResults(Arrays.asList(new Object[] { 1l, 0l, "foo" }), actual); + } + + @Test + public void testHIncrBy() { + actual.add(connection.hSet("test", "key", "2")); + actual.add(connection.hIncrBy("test", "key", 3l)); + actual.add(connection.hGet("test", "key")); + verifyResults(Arrays.asList(new Object[] { 1l, 5l, "5" }), actual); + } + + @Test + public void testHLen() { + actual.add(connection.hSet("test", "key", "2")); + actual.add(connection.hSet("test", "key2", "2")); + actual.add(connection.hLen("test")); + verifyResults(Arrays.asList(new Object[] { 1l, 1l, 2l }), actual); + } + + @Test + public void testHVals() { + actual.add(connection.hSet("test", "key", "foo")); + actual.add(connection.hSet("test", "key2", "bar")); + actual.add(connection.hVals("test")); + verifyResults(Arrays.asList(new Object[] { 1l, 1l, + Arrays.asList(new String[] { "foo", "bar" }) }), actual); + } + + protected void verifyResults(List expected, List actual) { + List expectedPipeline = new ArrayList(); + for (int i = 0; i < actual.size(); i++) { + expectedPipeline.add(null); + } + assertEquals(expectedPipeline, actual); + List pipelinedResults = connection.closePipeline(); + assertEquals(expected, convertResults(pipelinedResults)); + } + + protected List convertResults(List pipelinedResults) { + List serializedResults = new ArrayList(); + 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) 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; + } +} diff --git a/src/test/java/org/springframework/data/redis/connection/jedis/JedisConnectionIntegrationTests.java b/src/test/java/org/springframework/data/redis/connection/jedis/JedisConnectionIntegrationTests.java index a98503305..868076c18 100644 --- a/src/test/java/org/springframework/data/redis/connection/jedis/JedisConnectionIntegrationTests.java +++ b/src/test/java/org/springframework/data/redis/connection/jedis/JedisConnectionIntegrationTests.java @@ -21,50 +21,58 @@ import static org.junit.Assert.assertEquals; import org.junit.After; import org.junit.Test; import org.junit.runner.RunWith; -import org.springframework.dao.DataAccessException; import org.springframework.data.redis.connection.AbstractConnectionIntegrationTests; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +/** + * Integration test of {@link JedisConnection} + * + * @author Costin Leau + * @author Jennifer Hickey + * + */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration public class JedisConnectionIntegrationTests extends AbstractConnectionIntegrationTests { - + @After public void tearDown() { try { + connection.flushDb(); connection.close(); - }catch(DataAccessException e) { - // Jedis leaves some incomplete data in OutputStream on NPE caused by null key/value tests - // Attempting to close the connection will result in error on sending QUIT to Redis - System.out.println("Connection already closed"); + } catch (Exception e) { + // Jedis leaves some incomplete data in OutputStream on NPE caused + // by null key/value tests + // Attempting to flush the DB or close the connection will result in + // error on sending QUIT to Redis } connection = null; } @Test - public void testIncrDecrBy() { + public void testIncrDecrByLong() { String key = "test.count"; long largeNumber = 0x123456789L; // > 32bits - connection.set(key.getBytes(), "0".getBytes()); - connection.incrBy(key.getBytes(), largeNumber); - assertEquals(largeNumber, Long.valueOf(new String(connection.get(key.getBytes()))).longValue()); - connection.decrBy(key.getBytes(), largeNumber); - assertEquals(0, Long.valueOf(new String(connection.get(key.getBytes()))).longValue()); - connection.decrBy(key.getBytes(), 2*largeNumber); - assertEquals(-2*largeNumber, Long.valueOf(new String(connection.get(key.getBytes()))).longValue()); + connection.set(key, "0"); + connection.incrBy(key, largeNumber); + assertEquals(largeNumber, Long.valueOf(connection.get(key)).longValue()); + connection.decrBy(key, largeNumber); + assertEquals(0, Long.valueOf(connection.get(key)).longValue()); + connection.decrBy(key, 2 * largeNumber); + assertEquals(-2 * largeNumber, Long.valueOf(connection.get(key)).longValue()); } @Test - public void testHashIncrDecrBy() { - byte[] key = "test.hcount".getBytes(); - byte[] hkey = "hashkey".getBytes(); + public void testHashIncrDecrByLong() { + String key = "test.hcount"; + String hkey = "hashkey"; long largeNumber = 0x123456789L; // > 32bits - connection.hSet(key, hkey, "0".getBytes()); + connection.hSet(key, hkey, "0"); connection.hIncrBy(key, hkey, largeNumber); - assertEquals(largeNumber, Long.valueOf(new String(connection.hGet(key, hkey))).longValue()); - connection.hIncrBy(key, hkey, -2*largeNumber); - assertEquals(-largeNumber, Long.valueOf(new String(connection.hGet(key, hkey))).longValue()); + assertEquals(largeNumber, Long.valueOf(connection.hGet(key, hkey)).longValue()); + connection.hIncrBy(key, hkey, -2 * largeNumber); + assertEquals(-largeNumber, Long.valueOf(connection.hGet(key, hkey)).longValue()); } } diff --git a/src/test/java/org/springframework/data/redis/connection/jedis/JedisConnectionPipelineIntegrationTests.java b/src/test/java/org/springframework/data/redis/connection/jedis/JedisConnectionPipelineIntegrationTests.java new file mode 100644 index 000000000..d44ab85ca --- /dev/null +++ b/src/test/java/org/springframework/data/redis/connection/jedis/JedisConnectionPipelineIntegrationTests.java @@ -0,0 +1,277 @@ +/* + * Copyright 2011-2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.redis.connection.jedis; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Set; + +import org.junit.After; +import org.junit.Ignore; +import org.junit.Test; +import org.junit.runner.RunWith; +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.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import redis.clients.jedis.Tuple; + +/** + * Integration test of {@link JedisConnection} pipeline functionality + * + * @author Jennifer Hickey + * + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration("JedisConnectionIntegrationTests-context.xml") +public class JedisConnectionPipelineIntegrationTests extends + AbstractConnectionPipelineIntegrationTests { + + /** + * Individual results from closePipeline should be converted from + * LinkedHashSet to List + **/ + private boolean convertResultToList; + + @After + public void tearDown() { + try { + connection.flushDb(); + connection.close(); + } catch (Exception e) { + // Jedis leaves some incomplete data in OutputStream on NPE caused + // by null key/value tests + // Attempting to close the connection will result in error on + // sending QUIT to Redis + } + connection = null; + } + + @Ignore("DATAREDIS-141 Jedis dbSize/flush ops execute synchronously while pipelining") + public void testDbSize() { + } + + @Ignore("DATAREDIS-141 Jedis dbSize/flush ops execute synchronously while pipelining") + public void testFlushDb() { + } + + @Ignore("DATAREDIS-138 NPE in DefaultStringRedisConnection deserializing a null Map") + public void testHSetGet() throws Exception { + // String hash = getClass() + ":hashtest"; + // String key1 = UUID.randomUUID().toString(); + // String key2 = UUID.randomUUID().toString(); + // String value1 = "foo"; + // String value2 = "bar"; + // actual.add(connection.hSet(hash, key1, value1)); + // actual.add(connection.hSet(hash, key2, value2)); + // actual.add(connection.hGet(hash, key1)); + // actual.add(connection.hGetAll(hash)); + // Map expected = new HashMap(); + // expected.put(key1, value1); + // expected.put(key2, value2); + // verifyResults(Arrays.asList(new Object[] { 1l, 1l, value1, expected + // }), actual); + } + + @Ignore("DATAREDIS-143 Jedis ClassCastExceptions closing pipeline on certain ops") + public void testGetConfig() { + } + + @Ignore("DATAREDIS-143 Jedis ClassCastExceptions closing pipeline on certain ops") + public void testWatch() { + } + + @Ignore("DATAREDIS-143 Jedis ClassCastExceptions closing pipeline on certain ops") + public void testUnwatch() { + } + + @Ignore("DATAREDIS-143 Jedis ClassCastExceptions closing pipeline on certain ops") + public void testSortStore() { + } + + @Ignore("DATAREDIS-143 Jedis ClassCastExceptions closing pipeline on certain ops") + public void testMultiExec() { + } + + @Ignore("DATAREDIS-143 Jedis NPE closing pipeline on certain ops") + public void testMultiDiscard() { + } + + @Ignore("DATAREDIS-155 Exists returns true after key is supposed to expire") + public void testExpire() throws Exception { + } + + @Ignore("DATAREDIS-155 Exists returns true after key is supposed to expire") + public void testSetEx() { + } + + // Unsupported Ops + @Test(expected = RedisSystemException.class) + public void testBitSet() throws Exception { + super.testBitSet(); + } + + @Test(expected = RedisSystemException.class) + public void testRandomKey() { + super.testRandomKey(); + } + + @Test(expected = RedisSystemException.class) + public void testGetRangeSetRange() { + super.testGetRangeSetRange(); + } + + @Test(expected = RedisSystemException.class) + public void testPingPong() throws Exception { + super.testPingPong(); + } + + @Test(expected = RedisSystemException.class) + public void testInfo() throws Exception { + super.testInfo(); + } + + // Overrides, usually due to return values being Long vs Boolean or Set vs + // List + + @Test + public void testRenameNx() { + connection.set("nxtest", "testit"); + actual.add(connection.renameNX("nxtest", "newnxtest")); + actual.add(connection.get("newnxtest")); + actual.add(connection.exists("nxtest")); + verifyResults(Arrays.asList(new Object[] { 1l, "testit", false }), actual); + } + + @Test + public void testKeys() throws Exception { + convertResultToList = true; + super.testKeys(); + } + + @Test + public void testZAddAndZRange() { + convertResultToList = true; + super.testZAddAndZRange(); + } + + @Test + public void testZIncrBy() { + convertResultToList = true; + super.testZIncrBy(); + } + + @Test + public void testZInterStore() { + convertResultToList = true; + super.testZInterStore(); + } + + @Test + public void testZRangeByScore() { + convertResultToList = true; + super.testZRangeByScore(); + } + + @Test + public void testZRangeByScoreOffsetCount() { + convertResultToList = true; + super.testZRangeByScoreOffsetCount(); + } + + @Test + public void testZRevRange() { + convertResultToList = true; + super.testZRevRange(); + } + + @Test + public void testZRem() { + convertResultToList = true; + super.testZRem(); + } + + @Test + public void testZRemRangeByScore() { + convertResultToList = true; + super.testZRemRangeByScore(); + } + + @Test + public void testZUnionStore() { + convertResultToList = true; + super.testZUnionStore(); + } + + @Test + public void testZRemRangeByRank() { + convertResultToList = true; + super.testZRemRangeByRank(); + } + + @Test + public void testHDel() throws Exception { + actual.add(connection.hSet("test", "key", "val")); + actual.add(connection.hDel("test", "key")); + actual.add(connection.hDel("test", "foo")); + actual.add(connection.hExists("test", "key")); + verifyResults(Arrays.asList(new Object[] { 1l, 1l, 0l, false }), actual); + } + + @Test + public void testExpireAt() throws Exception { + connection.set("exp2", "true"); + actual.add(connection.expireAt("exp2", System.currentTimeMillis() / 1000 + 1)); + Thread.sleep(2000); + actual.add(connection.exists("exp2")); + verifyResults(Arrays.asList(new Object[] { 1l, false }), actual); + } + + @Test + public void testPersist() throws Exception { + connection.set("exp3", "true"); + actual.add(connection.expire("exp3", 1)); + actual.add(connection.persist("exp3")); + Thread.sleep(1500); + actual.add(connection.exists("exp3")); + verifyResults(Arrays.asList(new Object[] { 1l, 1l, true }), actual); + } + + @SuppressWarnings({ "rawtypes", "unchecked" }) + protected Object convertResult(Object result) { + Object convertedResult = super.convertResult(result); + if (convertedResult instanceof Set) { + if (convertResultToList) { + // Other providers represent zSets as Lists, so transform here + return new ArrayList((Set) result); + } else if (!(((Set) result).isEmpty()) + && ((Set) convertedResult).iterator().next() instanceof Tuple) { + List tuples = new ArrayList(); + for (Tuple value : ((Set) convertedResult)) { + DefaultStringTuple tuple = new DefaultStringTuple( + (byte[]) value.getBinaryElement(), value.getElement(), value.getScore()); + tuples.add(tuple); + } + return tuples; + } + } + return convertedResult; + } +} diff --git a/src/test/java/org/springframework/data/redis/connection/jredis/JRedisConnectionIntegrationTests.java b/src/test/java/org/springframework/data/redis/connection/jredis/JRedisConnectionIntegrationTests.java index 7be632cd6..a4f305251 100644 --- a/src/test/java/org/springframework/data/redis/connection/jredis/JRedisConnectionIntegrationTests.java +++ b/src/test/java/org/springframework/data/redis/connection/jredis/JRedisConnectionIntegrationTests.java @@ -16,69 +16,77 @@ package org.springframework.data.redis.connection.jredis; +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.dao.DataAccessException; import org.springframework.data.redis.connection.AbstractConnectionIntegrationTests; +import org.springframework.data.redis.connection.DefaultSortParameters; +import org.springframework.data.redis.connection.SortParameters.Order; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +/** + * Integration test of {@link JredisConnection} + * + * @author Costin Leau + * @author Jennifer Hickey + * + */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration public class JRedisConnectionIntegrationTests extends AbstractConnectionIntegrationTests { - + @After public void tearDown() { try { + connection.flushDb(); connection.close(); - }catch(DataAccessException e) { - // Jredis closes a connection on Exception (which some tests intentionally throw) + } catch (DataAccessException e) { + // Jredis closes a connection on Exception (which some tests + // intentionally throw) // Attempting to close the connection again will result in error System.out.println("Connection already closed"); } connection = null; } - @Ignore("JRedis does not support pipelining") - public void testNullCollections() { - } - - @Ignore + @Ignore("nulls are encoded to empty strings") public void testNullKey() throws Exception { } - @Ignore + @Ignore("nulls are encoded to empty strings") public void testNullValue() throws Exception { } - @Ignore + @Ignore("nulls are encoded to empty strings") public void testHashNullKey() throws Exception { } - @Ignore + @Ignore("nulls are encoded to empty strings") public void testHashNullValue() throws Exception { } - @Ignore - public void testNullSerialization() throws Exception { - } - - @Ignore - public void testPubSub() throws Exception { - } - - @Ignore + @Ignore("Pub/Sub not supported") public void testPubSubWithPatterns() { } - @Ignore + @Ignore("Pub/Sub not supported") public void testPubSubWithNamedChannels() { } - @Ignore + @Ignore("DATAREDIS-129 Key search does not work with regex") + public void testKeys() throws Exception { + } + + @Test(expected = UnsupportedOperationException.class) public void testBitSet() throws Exception { + super.testBitSet(); } @Test(expected = UnsupportedOperationException.class) @@ -91,28 +99,19 @@ public class JRedisConnectionIntegrationTests extends AbstractConnectionIntegrat super.testMultiDiscard(); } - @Ignore - public void exceptionExecuteNativeWithPipeline() throws Exception { + @Test(expected = UnsupportedOperationException.class) + public void testWatch() throws Exception { + super.testWatch(); } @Test(expected = UnsupportedOperationException.class) - public void testExceptionExecuteNativeWithPipeline() throws Exception { - super.testExceptionExecuteNativeWithPipeline(); + public void testUnwatch() throws Exception { + super.testUnwatch(); } @Test(expected = UnsupportedOperationException.class) - public void testExecuteNativeWithPipeline() throws Exception { - super.testExecuteNativeWithPipeline(); - } - - @Test(expected = UnsupportedOperationException.class) - public void testBlPopTimeout() { - super.testBlPopTimeout(); - } - - @Test(expected = UnsupportedOperationException.class) - public void testBlPop() { - super.testBlPop(); + public void testBLPop() { + super.testBLPop(); } @Test(expected = UnsupportedOperationException.class) @@ -121,7 +120,214 @@ public class JRedisConnectionIntegrationTests extends AbstractConnectionIntegrat } @Test(expected = UnsupportedOperationException.class) - public void testBRPopTimeout() { + public void testLInsert() { + super.testLInsert(); + } + + @Test(expected = UnsupportedOperationException.class) + public void testBRPopLPush() { + super.testBRPopLPush(); + } + + @Test(expected = UnsupportedOperationException.class) + public void testLPushX() { + super.testLPushX(); + } + + @Test(expected = UnsupportedOperationException.class) + public void testRPushX() { + super.testRPushX(); + } + + @Test(expected = UnsupportedOperationException.class) + public void testGetRangeSetRange() { + super.testGetRangeSetRange(); + } + + @Test(expected = UnsupportedOperationException.class) + public void testStrLen() { + super.testStrLen(); + } + + @Test(expected = UnsupportedOperationException.class) + public void testGetConfig() { + super.testGetConfig(); + } + + @Test(expected = UnsupportedOperationException.class) + public void testZInterStore() { + super.testZInterStore(); + } + + @Test(expected = UnsupportedOperationException.class) + public void testZInterStoreAggWeights() { + super.testZInterStoreAggWeights(); + } + + @Test(expected = UnsupportedOperationException.class) + public void testZRangeWithScores() { + super.testZRangeWithScores(); + } + + @Test(expected = UnsupportedOperationException.class) + public void testZRangeByScoreOffsetCount() { + super.testZRangeByScoreOffsetCount(); + } + + @Test(expected = UnsupportedOperationException.class) + public void testZRangeByScoreWithScores() { + super.testZRangeByScoreWithScores(); + } + + @Test(expected = UnsupportedOperationException.class) + public void testZRangeByScoreWithScoresOffsetCount() { + super.testZRangeByScoreWithScoresOffsetCount(); + } + + @Test(expected = UnsupportedOperationException.class) + public void testZRevRangeWithScores() { + super.testZRevRangeWithScores(); + } + + @Test(expected = UnsupportedOperationException.class) + public void testZUnionStore() { + super.testZUnionStore(); + } + + @Test(expected = UnsupportedOperationException.class) + public void testZUnionStoreAggWeights() { + super.testZUnionStoreAggWeights(); + } + + @Test(expected = UnsupportedOperationException.class) + public void testHSetNX() throws Exception { + super.testHSetNX(); + } + + @Test(expected = UnsupportedOperationException.class) + public void testHIncrBy() { + super.testHIncrBy(); + } + + @Test(expected = UnsupportedOperationException.class) + public void testHMGetSet() { + super.testHMGetSet(); + } + + @Test(expected = UnsupportedOperationException.class) + public void testPersist() throws Exception { + super.testPersist(); + } + + @Test(expected = UnsupportedOperationException.class) + public void testSetEx() throws Exception { + super.testSetEx(); + } + + @Test(expected = UnsupportedOperationException.class) + public void testBRPopTimeout() throws Exception { super.testBRPopTimeout(); } + + @Test(expected = UnsupportedOperationException.class) + public void testBLPopTimeout() throws Exception { + super.testBLPopTimeout(); + } + + @Test(expected = UnsupportedOperationException.class) + public void testBRPopLPushTimeout() throws Exception { + super.testBRPopLPushTimeout(); + } + + // Jredis returns null for rPush + @Test + public void testSort() { + connection.rPush("sortlist", "foo"); + connection.rPush("sortlist", "bar"); + connection.rPush("sortlist", "baz"); + assertEquals(Arrays.asList(new String[] { "bar", "baz", "foo" }), + connection.sort("sortlist", new DefaultSortParameters(null, Order.ASC, true))); + } + + @Test + public void testSortStore() { + connection.rPush("sortlist", "foo"); + connection.rPush("sortlist", "bar"); + connection.rPush("sortlist", "baz"); + assertEquals(Long.valueOf(3), connection.sort("sortlist", new DefaultSortParameters(null, + Order.ASC, true), "newlist")); + assertEquals(Arrays.asList(new String[] { "bar", "baz", "foo" }), + connection.lRange("newlist", 0, 9)); + } + + @Test + public void testLPop() { + connection.rPush("PopList", "hello"); + connection.rPush("PopList", "world"); + assertEquals("hello", connection.lPop("PopList")); + } + + @Test + public void testLRem() { + connection.rPush("PopList", "hello"); + connection.rPush("PopList", "big"); + connection.rPush("PopList", "world"); + connection.rPush("PopList", "hello"); + assertEquals(Long.valueOf(2), connection.lRem("PopList", 2, "hello")); + assertEquals(Arrays.asList(new String[] { "big", "world" }), + connection.lRange("PopList", 0, -1)); + } + + @Test + public void testLSet() { + connection.rPush("PopList", "hello"); + connection.rPush("PopList", "big"); + connection.rPush("PopList", "world"); + connection.lSet("PopList", 1, "cruel"); + assertEquals(Arrays.asList(new String[] { "hello", "cruel", "world" }), + connection.lRange("PopList", 0, -1)); + } + + @Test + public void testLTrim() { + connection.rPush("PopList", "hello"); + connection.rPush("PopList", "big"); + connection.rPush("PopList", "world"); + connection.lTrim("PopList", 1, -1); + assertEquals(Arrays.asList(new String[] { "big", "world" }), + connection.lRange("PopList", 0, -1)); + } + + @Test + public void testRPop() { + connection.rPush("PopList", "hello"); + connection.rPush("PopList", "world"); + assertEquals("world", connection.rPop("PopList")); + } + + @Test + public void testRPopLPush() { + connection.rPush("PopList", "hello"); + connection.rPush("PopList", "world"); + connection.rPush("pop2", "hey"); + assertEquals("world", connection.rPopLPush("PopList", "pop2")); + assertEquals(Arrays.asList(new String[] { "hello" }), connection.lRange("PopList", 0, -1)); + assertEquals(Arrays.asList(new String[] { "world", "hey" }), + connection.lRange("pop2", 0, -1)); + } + + @Test + public void testLIndex() { + connection.lPush("testylist", "foo"); + assertEquals("foo", connection.lIndex("testylist", 0)); + } + + @Test + public void testLPush() throws Exception { + connection.lPush("testlist", "bar"); + connection.lPush("testlist", "baz"); + assertEquals(Arrays.asList(new String[] { "baz", "bar" }), + connection.lRange("testlist", 0, -1)); + } + } \ No newline at end of file diff --git a/src/test/java/org/springframework/data/redis/connection/lettuce/LettuceConnectionIntegrationTests.java b/src/test/java/org/springframework/data/redis/connection/lettuce/LettuceConnectionIntegrationTests.java index 8743f0284..ff834a946 100644 --- a/src/test/java/org/springframework/data/redis/connection/lettuce/LettuceConnectionIntegrationTests.java +++ b/src/test/java/org/springframework/data/redis/connection/lettuce/LettuceConnectionIntegrationTests.java @@ -16,33 +16,28 @@ package org.springframework.data.redis.connection.lettuce; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; - -import java.util.List; - -import org.junit.Test; +import org.junit.Ignore; import org.junit.runner.RunWith; import org.springframework.data.redis.connection.AbstractConnectionIntegrationTests; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +/** + * Integration test of {@link LettuceConnection} + * + * @author Costin Leau + * @author Jennifer Hickey + * + */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration public class LettuceConnectionIntegrationTests extends AbstractConnectionIntegrationTests { + @Ignore("DATAREDIS-122 exec never returns null") + public void testWatch() throws Exception { + } - @Test - public void testMultiExec() throws Exception { - byte[] key = "key".getBytes(); - byte[] value = "value".getBytes(); - - connection.multi(); - connection.set(key, value); - assertNull(connection.get(key)); - List results = connection.exec(); - assertEquals(2, results.size()); - assertEquals("OK", results.get(0)); - assertEquals(new String(value), new String((byte[])results.get(1))); + @Ignore("DATAREDIS-122 exec never returns null") + public void testUnwatch() throws Exception { } } \ No newline at end of file diff --git a/src/test/java/org/springframework/data/redis/connection/lettuce/LettuceConnectionPipelineIntegrationTests.java b/src/test/java/org/springframework/data/redis/connection/lettuce/LettuceConnectionPipelineIntegrationTests.java new file mode 100644 index 000000000..1f5ee5e66 --- /dev/null +++ b/src/test/java/org/springframework/data/redis/connection/lettuce/LettuceConnectionPipelineIntegrationTests.java @@ -0,0 +1,268 @@ +/* + * Copyright 2011-2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.redis.connection.lettuce; + +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 java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import org.junit.Ignore; +import org.junit.Test; +import org.junit.runner.RunWith; +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.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import com.lambdaworks.redis.KeyValue; +import com.lambdaworks.redis.ScoredValue; + +/** + * Integration test of {@link LettuceConnection} pipeline functionality + * + * @author Jennifer Hickey + * + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration("LettuceConnectionIntegrationTests-context.xml") +public class LettuceConnectionPipelineIntegrationTests extends + AbstractConnectionPipelineIntegrationTests { + + @Ignore("DATAREDIS-144 Lettuce closePipeline hangs with discarded transaction") + public void testMultiDiscard() { + } + + @Ignore("DATAREDIS-122 exec never returns null") + public void testWatch() throws Exception { + } + + @Ignore("DATAREDIS-122 exec never returns null") + public void testUnwatch() throws Exception { + } + + @Ignore("DATAREDIS-139 Lettuce exec while pipelining returns a non-null value") + public void testMultiExec() throws Exception { + } + + @Ignore("DATAREDIS-140 Lettuce zCount/zInterStore methods execute synchronously when pipelining") + public void testZInterStoreAggWeights() { + } + + @Ignore("DATAREDIS-140 Lettuce zCount/zInterStore methods execute synchronously when pipelining") + public void testZInterStore() { + } + + @Ignore("DATAREDIS-140 Lettuce zCount/zInterStore methods execute synchronously when pipelining") + public void testZCount() { + } + + @Ignore("DATAREDIS-138 NPE in DefaultStringRedisConnection deserializing a null Map") + public void testHSetGet() throws Exception { + // String hash = getClass() + ":hashtest"; + // String key1 = UUID.randomUUID().toString(); + // String key2 = UUID.randomUUID().toString(); + // String value1 = "foo"; + // String value2 = "bar"; + // actual.add(connection.hSet(hash, key1, value1)); + // actual.add(connection.hSet(hash, key2, value2)); + // actual.add(connection.hGet(hash, key1)); + // actual.add(connection.hGetAll(hash)); + // Map expected = new HashMap(); + // expected.put(key1, value1); + // expected.put(key2, value2); + // verifyResults(Arrays.asList(new Object[] { true, true, value1, + // expected }), actual); + } + + // Overrides, usually due to return values being Long vs Boolean or Set vs + // List + + @Test + public void testInfo() throws Exception { + assertNull(connection.info()); + List results = connection.closePipeline(); + assertEquals(1, results.size()); + Properties info = LettuceUtils.info((String) results.get(0)); + assertTrue("at least 5 settings should be present", info.size() >= 5); + String version = info.getProperty("redis_version"); + assertNotNull(version); + } + + @Test + public void testMSetNx() { + Map vals = new HashMap(); + vals.put("height", "5"); + vals.put("width", "1"); + connection.mSetNXString(vals); + assertNull(connection.mGet("height", "width")); + verifyResults( + Arrays.asList(new Object[] { true, Arrays.asList(new String[] { "5", "1" }) }), + actual); + } + + @Test + public void testSetNx() { + actual.add(connection.setNX("notaround", "54")); + actual.add(connection.get("notaround")); + actual.add(connection.setNX("notaround", "55")); + actual.add(connection.get("notaround")); + verifyResults(Arrays.asList(new Object[] { true, "54", false, "54" }), actual); + } + + @Test + public void testRenameNx() { + connection.set("nxtest", "testit"); + actual.add(connection.renameNX("nxtest", "newnxtest")); + actual.add(connection.get("newnxtest")); + actual.add(connection.exists("nxtest")); + verifyResults(Arrays.asList(new Object[] { true, "testit", false }), actual); + } + + @Test + public void testSMove() { + convertResultToSet = true; + actual.add(connection.sAdd("myset", "foo")); + actual.add(connection.sAdd("myset", "bar")); + actual.add(connection.sAdd("otherset", "bar")); + actual.add(connection.sMove("myset", "otherset", "foo")); + actual.add(connection.sMembers("otherset")); + verifyResults( + Arrays.asList(new Object[] { 1l, 1l, 1l, true, + new HashSet(Arrays.asList(new String[] { "foo", "bar" })) }), + actual); + } + + @Test + public void testHKeys() { + actual.add(connection.hSet("test", "key", "2")); + actual.add(connection.hSet("test", "key2", "2")); + actual.add(connection.hKeys("test")); + verifyResults( + Arrays.asList(new Object[] { true, true, + Arrays.asList(new String[] { "key", "key2" }) }), actual); + } + + @Test + public void testHSetNX() throws Exception { + actual.add(connection.hSetNX("myhash", "key1", "foo")); + actual.add(connection.hSetNX("myhash", "key1", "bar")); + actual.add(connection.hGet("myhash", "key1")); + verifyResults(Arrays.asList(new Object[] { true, false, "foo" }), actual); + } + + @Test + public void testHIncrBy() { + actual.add(connection.hSet("test", "key", "2")); + actual.add(connection.hIncrBy("test", "key", 3l)); + actual.add(connection.hGet("test", "key")); + verifyResults(Arrays.asList(new Object[] { true, 5l, "5" }), actual); + } + + @Test + public void testHLen() { + actual.add(connection.hSet("test", "key", "2")); + actual.add(connection.hSet("test", "key2", "2")); + actual.add(connection.hLen("test")); + verifyResults(Arrays.asList(new Object[] { true, true, 2l }), actual); + } + + @Test + public void testHVals() { + actual.add(connection.hSet("test", "key", "foo")); + actual.add(connection.hSet("test", "key2", "bar")); + actual.add(connection.hVals("test")); + verifyResults( + Arrays.asList(new Object[] { true, true, + Arrays.asList(new String[] { "foo", "bar" }) }), actual); + } + + @Test + public void testHDel() throws Exception { + actual.add(connection.hSet("test", "key", "val")); + actual.add(connection.hDel("test", "key")); + actual.add(connection.hDel("test", "foo")); + actual.add(connection.hExists("test", "key")); + verifyResults(Arrays.asList(new Object[] { true, 1l, 0l, false }), actual); + } + + @Test + public void testPersist() throws Exception { + connection.set("exp3", "true"); + actual.add(connection.expire("exp3", 1)); + actual.add(connection.persist("exp3")); + Thread.sleep(1500); + actual.add(connection.exists("exp3")); + verifyResults(Arrays.asList(new Object[] { true, true, true }), actual); + } + + @Test + public void testExpireAt() throws Exception { + connection.set("exp2", "true"); + actual.add(connection.expireAt("exp2", System.currentTimeMillis() / 1000 + 1)); + Thread.sleep(2000); + actual.add(connection.exists("exp2")); + verifyResults(Arrays.asList(new Object[] { true, false }), actual); + } + + @Test + public void testExpire() throws Exception { + connection.set("exp", "true"); + actual.add(connection.expire("exp", 1)); + Thread.sleep(2000); + actual.add(connection.exists("exp")); + verifyResults(Arrays.asList(new Object[] { true, false }), actual); + } + + @Test + public void testSetEx() throws Exception { + connection.setEx("expy", 1l, "yep"); + actual.add(connection.get("expy")); + Thread.sleep(2000); + actual.add(connection.exists("expy")); + verifyResults(Arrays.asList(new Object[] { "yep", false }), actual); + } + + @SuppressWarnings({ "rawtypes", "unchecked" }) + protected Object convertResult(Object result) { + Object convertedResult = super.convertResult(result); + if (convertedResult instanceof KeyValue) { + List keyValue = new ArrayList(); + keyValue.add((String) super.convertResult(((KeyValue) convertedResult).key)); + keyValue.add((String) super.convertResult(((KeyValue) convertedResult).value)); + return keyValue; + } else if (convertedResult instanceof List && !(((List) result).isEmpty()) + && ((List) convertedResult).get(0) instanceof ScoredValue) { + List tuples = new ArrayList(); + for (ScoredValue value : ((List) convertedResult)) { + DefaultStringTuple tuple = new DefaultStringTuple((byte[]) value.value, new String( + (byte[]) value.value), value.score); + tuples.add(tuple); + } + return tuples; + } + return convertedResult; + } +} diff --git a/src/test/java/org/springframework/data/redis/connection/rjc/RjcConnectionIntegrationTests.java b/src/test/java/org/springframework/data/redis/connection/rjc/RjcConnectionIntegrationTests.java index c80402f38..b697f369a 100644 --- a/src/test/java/org/springframework/data/redis/connection/rjc/RjcConnectionIntegrationTests.java +++ b/src/test/java/org/springframework/data/redis/connection/rjc/RjcConnectionIntegrationTests.java @@ -1,12 +1,12 @@ /* * Copyright 2011-2013 the original author or authors. - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -19,7 +19,6 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import java.util.List; -import java.util.UUID; import org.junit.Ignore; import org.junit.Test; @@ -29,7 +28,11 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; /** + * Integration test of {@link RjcConnection} + * * @author Costin Leau + * @author Jennifer Hickey + * */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration @@ -46,27 +49,66 @@ public class RjcConnectionIntegrationTests extends AbstractConnectionIntegration List results = connection.exec(); assertEquals(2, results.size()); assertEquals("OK", (String) results.get(0)); - assertEquals(new String(value), new String(RjcUtils.encode((String)results.get(1)))); + assertEquals(new String(value), new String(RjcUtils.encode((String) results.get(1)))); } - // override test to address the encoding issue (the bytes[] in raw format differ) - @Test - public void testExecuteNativeWithPipeline() throws Exception { - String key1 = getClass() + "#ExecuteNativeWithPipeline#1"; - String value1 = UUID.randomUUID().toString(); - String key2 = getClass() + "#ExecuteNativeWithPipeline#2"; - String value2 = UUID.randomUUID().toString(); + @Ignore("nulls are encoded to empty strings") + public void testNullKey() throws Exception { + } - connection.openPipeline(); - connection.execute("SET", key1, value1); - connection.execute("SET", key2, value2); - connection.execute("GET", key1); - connection.execute("GET", key2); - List result = connection.closePipeline(); - assertEquals(4, result.size()); + @Ignore("nulls are encoded to empty strings") + public void testNullValue() throws Exception { + } + + @Ignore("nulls are encoded to empty strings") + public void testHashNullKey() throws Exception { + } + + @Ignore("nulls are encoded to empty strings") + public void testHashNullValue() throws Exception { + } + + @Ignore("DATAREDIS-133 Key search does not work with regex") + public void testKeys() throws Exception { + } + + @Ignore("DATAREDIS-121 incr/decr does not work with encoded values") + public void testDecrByIncrBy() { + } + + @Ignore("DATAREDIS-121 incr/decr does not work with encoded values") + public void testIncDecr() { + } + + @Ignore("DATAREDIS-121 incr/decr does not work with encoded values") + public void testHIncrBy() { + } + + @Ignore("DATAREDIS-134 string ops do not work with encoded values") + public void testSort() { } @Ignore("DATAREDIS-134 string ops do not work with encoded values") public void testSortStore() { } + + @Ignore("DATAREDIS-134 string ops do not work with encoded values") + public void testGetRangeSetRange() { + } + + @Ignore("DATAREDIS-134 string ops do not work with encoded values") + public void testStrLen() { + } + + @Ignore("DATAREDIS-120 Pattern matching currently broken") + public void testPubSubWithPatterns() { + } + + @Ignore("DATAREDIS-137 zRevRangeWithScores returns incorrect results") + public void testZRevRangeWithScores() { + } + + @Ignore("DATAREDIS-148 Syntax error on RJC zUnionStore") + public void testZUnionStoreAggWeights() { + } } diff --git a/src/test/java/org/springframework/data/redis/connection/rjc/RjcConnectionPipelineIntegrationTests.java b/src/test/java/org/springframework/data/redis/connection/rjc/RjcConnectionPipelineIntegrationTests.java new file mode 100644 index 000000000..3e3cc3374 --- /dev/null +++ b/src/test/java/org/springframework/data/redis/connection/rjc/RjcConnectionPipelineIntegrationTests.java @@ -0,0 +1,280 @@ +/* + * Copyright 2011-2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.redis.connection.rjc; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; +import org.junit.runner.RunWith; +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.StringRedisConnection.StringTuple; +import org.springframework.data.redis.serializer.SerializationUtils; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +/** + * Integration test of {@link RjcConnection} pipeline functionality + * + * @author Jennifer Hickey + * + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration +public class RjcConnectionPipelineIntegrationTests extends + AbstractConnectionPipelineIntegrationTests { + + @Before + public void setUp() { + super.setUp(); + } + + @Ignore("DATAREDIS-134 string ops do not work with encoded values") + public void testGetRangeSetRange() { + } + + @Ignore("DATAREDIS-133 Key search does not work with regex") + public void testKeys() throws Exception { + } + + @Ignore("DATAREDIS-121 incr/decr does not work with encoded values") + public void testDecrByIncrBy() { + } + + @Ignore("DATAREDIS-121 incr/decr does not work with encoded values") + public void testIncDecr() { + } + + @Ignore("DATAREDIS-121 incr/decr does not work with encoded values") + public void testHIncrBy() { + } + + @Ignore("DATAREDIS-134 string ops do not work with encoded values") + public void testSort() { + } + + @Ignore("DATAREDIS-134 string ops do not work with encoded values") + public void testSortStore() { + } + + @Ignore("DATAREDIS-134 string ops do not work with encoded values") + public void testStrLen() { + } + + @Ignore("DATAREDIS-137 zRevRangeWithScores returns incorrect results") + public void testZRevRangeWithScores() { + } + + @Ignore("DATAREDIS-138 NPE in DefaultStringRedisConnection deserializing a null Map") + public void testHSetGet() throws Exception { + // String hash = getClass() + ":hashtest"; + // String key1 = UUID.randomUUID().toString(); + // String key2 = UUID.randomUUID().toString(); + // String value1 = "foo"; + // String value2 = "bar"; + // actual.add(connection.hSet(hash, key1, value1)); + // actual.add(connection.hSet(hash, key2, value2)); + // actual.add(connection.hGet(hash, key1)); + // actual.add(connection.hGetAll(hash)); + // List expected = Arrays.asList(new String[] { key1, value1, + // key2, value2 }); + // verifyResults(Arrays.asList(new Object[] { 1l, 1l, value1, expected + // }), actual); + } + + @Ignore("DATAREDIS-148 Syntax error on RJC zUnionStore") + public void testZUnionStoreAggWeights() { + } + + @Ignore("DATAREDIS-149 Wrong number of args on RJC brPop when pipelining") + public void testBRPop() { + } + + @Ignore("DATAREDIS-149 Wrong number of args on RJC brPop when pipelining") + public void testBLPop() { + } + + @Ignore("DATAREDIS-149 Wrong number of args on RJC brPop when pipelining") + public void testBRPopTimeout() { + } + + @Ignore("DATAREDIS-149 Wrong number of args on RJC brPop when pipelining") + public void testBLPopTimeout() { + } + + @Ignore("DATAREDIS-150 the 6 from zIncrBy improperly decoded") + public void testZIncrBy() { + } + + @Ignore("DATAREDIS-150 the 3 from zScore improperly decoded") + public void testZScore() { + } + + @Ignore("DATAREDIS-150 the results of info improperly decoded") + public void testInfo() throws Exception { + } + + @Ignore("DATAREDIS-150 the results of ping improperly decoded") + public void testPingPong() throws Exception { + } + + @Ignore("DATAREDIS-150 the results of tye improperly decoded") + public void testType() { + } + + // Overrides, usually due to return values being Long vs Boolean or Set vs + // List + + @Test + public void testSIsMember() { + convertResultToSet = true; + actual.add(connection.sAdd("myset", "foo")); + actual.add(connection.sAdd("myset", "bar")); + actual.add(connection.sIsMember("myset", "foo")); + actual.add(connection.sIsMember("myset", "baz")); + verifyResults(Arrays.asList(new Object[] { 1l, 1l, 1l, 0l }), actual); + } + + @Test + public void testRename() { + connection.set("renametest", "testit"); + connection.rename("renametest", "newrenametest"); + actual.add(connection.get("newrenametest")); + actual.add(connection.exists("renametest")); + verifyResults(Arrays.asList(new Object[] { "testit", 0l }), actual); + } + + @Test + public void testExists() { + connection.set("existent", "true"); + actual.add(connection.exists("existent")); + actual.add(connection.exists("nonexistent")); + verifyResults(Arrays.asList(new Object[] { 1l, 0l }), actual); + } + + @Test + public void testMultiExec() throws Exception { + connection.multi(); + connection.set("key", "value"); + assertNull(connection.get("key")); + assertNull(connection.exec()); + List convertedResults = convertResults(connection.closePipeline()); + // "OK" will be decoded to null + assertEquals(Arrays.asList(new Object[] { Arrays.asList(new String[] { null, "value" }) }), + convertedResults); + } + + @Test + public void testWatch() throws Exception { + connection.set("testitnow", "willdo"); + connection.watch("testitnow".getBytes()); + DefaultStringRedisConnection conn2 = new DefaultStringRedisConnection( + connectionFactory.getConnection()); + conn2.set("testitnow", "something"); + conn2.close(); + connection.multi(); + connection.set("testitnow", "somethingelse"); + actual.add(connection.exec()); + actual.add(connection.get("testitnow")); + List convertedResults = convertResults(connection.closePipeline()); + // The null returned from exec will be filtered out + assertEquals(Arrays.asList(new String[] { "something" }), convertedResults); + } + + @Test + public void testUnwatch() throws Exception { + connection.set("testitnow", "willdo"); + connection.watch("testitnow".getBytes()); + connection.unwatch(); + connection.multi(); + DefaultStringRedisConnection conn2 = new DefaultStringRedisConnection( + connectionFactory.getConnection()); + conn2.set("testitnow", "something"); + connection.set("testitnow", "somethingelse"); + connection.get("testitnow"); + connection.exec(); + List convertedResults = convertResults(connection.closePipeline()); + // "OK" will be decoded to null + assertEquals(Arrays.asList(new Object[] { Arrays.asList(new String[] { null, + "somethingelse" }) }), convertedResults); + } + + @Test + public void testBRPopLPushTimeout() throws Exception { + connection.bRPopLPush(1, "alist", "foo"); + Thread.sleep(1500l); + List results = connection.closePipeline(); + assertEquals(Arrays.asList(new Object[] { null }), results); + } + + protected List convertResults(List pipelinedResults) { + List serializedResults = new ArrayList(); + for (Object result : pipelinedResults) { + Object convertedResult = convertResult(result); + // closePipeline attempts to decode "OK" and "QUEUED" which turn + // them into null + // Filter them out here + if (convertedResult != null && !"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 String) { + if (convertResultToSet) { + return SerializationUtils.deserialize(RjcUtils.convertToSet((List) result), + stringSerializer); + } else if (convertResultToTuples) { + List resultList = (List) result; + List stringTuples = new ArrayList(); + for (int i = 0; i < resultList.size(); i += 2) { + String value = stringSerializer.deserialize(RjcUtils.encode((String) resultList + .get(i))); + stringTuples.add(new DefaultStringTuple(value.getBytes(), value, Double + .valueOf((String) resultList.get(i + 1)))); + } + return stringTuples; + } else { + return SerializationUtils.deserialize(RjcUtils.convertToList((List) 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; + } +} diff --git a/src/test/java/org/springframework/data/redis/connection/srp/SrpConnectionIntegrationTests.java b/src/test/java/org/springframework/data/redis/connection/srp/SrpConnectionIntegrationTests.java index f2708903f..4e5450ffc 100644 --- a/src/test/java/org/springframework/data/redis/connection/srp/SrpConnectionIntegrationTests.java +++ b/src/test/java/org/springframework/data/redis/connection/srp/SrpConnectionIntegrationTests.java @@ -16,21 +16,36 @@ package org.springframework.data.redis.connection.srp; +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.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; /** + * Integration test of {@link SrpConnection} + * * @author Costin Leau + * @author Jennifer Hickey + * */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration public class SrpConnectionIntegrationTests extends AbstractConnectionIntegrationTests { - @Ignore - public void testNullCollections() throws Exception { + @After + public void tearDown() { + try { + connection.flushDb(); + } catch (Exception e) { + // SRP doesn't allow other commands to be executed once subscribed, + // so + // this fails after pub/sub tests + } + connection.close(); + connection = null; } @Ignore("DATAREDIS-123, exec does not return command results") @@ -41,7 +56,45 @@ public class SrpConnectionIntegrationTests extends AbstractConnectionIntegration public void testMultiDiscard() { } + @Ignore("DATAREDIS-123, exec does not return command results") + public void testWatch() { + } + + @Ignore("DATAREDIS-123, exec does not return command results") + public void testUnwatch() { + } + + @Ignore("DATAREDIS-130, sort not working") + public void testSort() { + } + @Ignore("DATAREDIS-130, sort not working") public void testSortStore() { } + + @Ignore("DATAREDIS-132 config get broken in SRP 0.2") + public void testGetConfig() { + } + + @Ignore("DATAREDIS-152 Syntax error on zRangeByScore and and zRangeByScoreWithScores when using offset and count") + public void testZRangeByScoreOffsetCount() { + } + + @Ignore("DATAREDIS-152 Syntax error on zRangeByScore and and zRangeByScoreWithScores when using offset and count") + public void testZRangeByScoreWithScoresOffsetCount() { + } + + @Ignore("DATAREDIS-156 SRP bRPopLPush ClassCastException") + public void testBRPopLPushTimeout() { + } + + @Test(expected = UnsupportedOperationException.class) + public void testZInterStoreAggWeights() { + super.testZInterStoreAggWeights(); + } + + @Test(expected = UnsupportedOperationException.class) + public void testZUnionStoreAggWeights() { + super.testZUnionStoreAggWeights(); + } } diff --git a/src/test/java/org/springframework/data/redis/connection/srp/SrpConnectionPipelineIntegrationTests.java b/src/test/java/org/springframework/data/redis/connection/srp/SrpConnectionPipelineIntegrationTests.java new file mode 100644 index 000000000..ea0e9db2a --- /dev/null +++ b/src/test/java/org/springframework/data/redis/connection/srp/SrpConnectionPipelineIntegrationTests.java @@ -0,0 +1,208 @@ +/* + * Copyright 2011-2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.redis.connection.srp; + +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 java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +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; +import org.springframework.data.redis.connection.DefaultStringTuple; +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.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import redis.reply.BulkReply; +import redis.reply.Reply; + +/** + * Integration test of {@link SrpConnection} pipeline functionality + * + * @author Jennifer Hickey + * + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration("SrpConnectionIntegrationTests-context.xml") +public class SrpConnectionPipelineIntegrationTests extends + AbstractConnectionPipelineIntegrationTests { + + @Ignore("DATAREDIS-123, exec does not return command results") + public void testMultiExec() throws Exception { + } + + @Ignore("DATAREDIS-123, exec does not return command results") + public void testMultiDiscard() { + } + + @Ignore("DATAREDIS-123, exec does not return command results") + public void testWatch() { + } + + @Ignore("DATAREDIS-123, exec does not return command results") + public void testUnwatch() { + } + + @Ignore("DATAREDIS-130, sort not working") + public void testSort() { + } + + @Ignore("DATAREDIS-130, sort not working") + public void testSortStore() { + } + + @Ignore("DATAREDIS-132 config get broken in SRP 0.2") + public void testGetConfig() { + } + + @Ignore("DATAREDIS-142 SRP zCount/zInterStore methods execute synchronously when pipelining") + public void testZCount() { + } + + @Ignore("DATAREDIS-142 SRP zCount/zInterStore methods execute synchronously when pipelining") + public void testZInterStore() { + } + + @Ignore("DATAREDIS-152 Syntax error on zRangeByScore and and zRangeByScoreWithScores when using offset and count") + public void testZRangeByScoreOffsetCount() { + } + + @Ignore("DATAREDIS-152 Syntax error on zRangeByScore and and zRangeByScoreWithScores when using offset and count") + public void testZRangeByScoreWithScoresOffsetCount() { + } + + @Ignore("DATAREDIS-138 NPE in DefaultStringRedisConnection deserializing a null Map") + public void testHSetGet() throws Exception { + // String hash = getClass() + ":hashtest"; + // String key1 = UUID.randomUUID().toString(); + // String key2 = UUID.randomUUID().toString(); + // String value1 = "foo"; + // String value2 = "bar"; + // actual.add(connection.hSet(hash, key1, value1)); + // actual.add(connection.hSet(hash, key2, value2)); + // actual.add(connection.hGet(hash, key1)); + // actual.add(connection.hGetAll(hash)); + // List expected = Arrays.asList(new String[] {key1, value1, + // key2, value2}); + // verifyResults(Arrays.asList(new Object[] { 1l, 1l, value1, expected + // }), actual); + } + + @Test(expected = UnsupportedOperationException.class) + public void testZInterStoreAggWeights() { + super.testZInterStoreAggWeights(); + } + + @Test(expected = UnsupportedOperationException.class) + public void testZUnionStoreAggWeights() { + super.testZUnionStoreAggWeights(); + } + + // Overrides, usually due to return values being Long vs Boolean or Set vs + // List + + @Test + public void testInfo() throws Exception { + assertNull(connection.info()); + List results = connection.closePipeline(); + assertEquals(1, results.size()); + Properties info = SrpUtils.info(new BulkReply((byte[]) results.get(0))); + assertTrue("at least 5 settings should be present", info.size() >= 5); + String version = info.getProperty("redis_version"); + assertNotNull(version); + } + + @Test + public void testExists() { + connection.set("existent", "true"); + actual.add(connection.exists("existent")); + actual.add(connection.exists("nonexistent")); + verifyResults(Arrays.asList(new Object[] { 1l, 0l }), actual); + } + + @Test + public void testRename() { + connection.set("renametest", "testit"); + connection.rename("renametest", "newrenametest"); + actual.add(connection.get("newrenametest")); + actual.add(connection.exists("renametest")); + verifyResults(Arrays.asList(new Object[] { "testit", 0l }), actual); + } + + @Test + public void testSIsMember() { + convertResultToSet = true; + actual.add(connection.sAdd("myset", "foo")); + actual.add(connection.sAdd("myset", "bar")); + actual.add(connection.sIsMember("myset", "foo")); + actual.add(connection.sIsMember("myset", "baz")); + verifyResults(Arrays.asList(new Object[] { 1l, 1l, 1l, 0l }), actual); + } + + @Test + public void testZIncrBy() { + actual.add(connection.zAdd("myset", 2, "Bob")); + actual.add(connection.zAdd("myset", 1, "James")); + actual.add(connection.zAdd("myset", 4, "Joe")); + actual.add(connection.zIncrBy("myset", 2, "Joe")); + actual.add(connection.zRangeByScore("myset", 6, 6)); + verifyResults( + Arrays.asList(new Object[] { 1l, 1l, 1l, "6", Collections.singletonList("Joe") }), + actual); + } + + @Test + public void testZScore() { + actual.add(connection.zAdd("myset", 2, "Bob")); + actual.add(connection.zAdd("myset", 1, "James")); + actual.add(connection.zAdd("myset", 3, "Joe")); + actual.add(connection.zScore("myset", "Joe")); + verifyResults(Arrays.asList(new Object[] { 1l, 1l, 1l, "3" }), actual); + } + + protected Object convertResult(Object result) { + Object convertedResult = super.convertResult(result); + if (convertedResult instanceof Reply[]) { + if (convertResultToSet) { + return SerializationUtils.deserialize(SrpUtils.toSet((Reply[]) convertedResult), + stringSerializer); + } else if (convertResultToTuples) { + Set tuples = SrpUtils.convertTuple((Reply[]) convertedResult); + List stringTuples = new ArrayList(); + for (Tuple tuple : tuples) { + stringTuples.add(new DefaultStringTuple(tuple, new String(tuple.getValue()))); + } + return stringTuples; + } else { + return SerializationUtils.deserialize( + SrpUtils.toBytesList((Reply[]) convertedResult), stringSerializer); + } + } + return convertedResult; + } +} diff --git a/src/test/java/org/springframework/data/redis/support/BoundKeyOperationsTest.java b/src/test/java/org/springframework/data/redis/support/BoundKeyOperationsTest.java index 44815f321..0e37fc83f 100644 --- a/src/test/java/org/springframework/data/redis/support/BoundKeyOperationsTest.java +++ b/src/test/java/org/springframework/data/redis/support/BoundKeyOperationsTest.java @@ -71,6 +71,16 @@ public class BoundKeyOperationsTest { public void testRename() throws Exception { Object key = keyOps.getKey(); assertNotNull(key); + // RedisAtomicInteger/Long need to be reset, as they may be created + // at start of test run and underlying key wiped out by other tests + try { + keyOps.getClass().getMethod("set", int.class).invoke(keyOps, 0); + }catch(NoSuchMethodException e) { + } + try { + keyOps.getClass().getMethod("set", long.class).invoke(keyOps, 0l); + }catch(NoSuchMethodException e) { + } Object newName = objFactory.instance(); keyOps.rename(newName); assertEquals(newName, keyOps.getKey()); diff --git a/src/test/resources/org/springframework/data/redis/connection/jedis/JedisConnectionIntegrationTests-context.xml b/src/test/resources/org/springframework/data/redis/connection/jedis/JedisConnectionIntegrationTests-context.xml index 0138acddf..ba982af64 100644 --- a/src/test/resources/org/springframework/data/redis/connection/jedis/JedisConnectionIntegrationTests-context.xml +++ b/src/test/resources/org/springframework/data/redis/connection/jedis/JedisConnectionIntegrationTests-context.xml @@ -4,10 +4,10 @@ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> - + diff --git a/src/test/resources/org/springframework/data/redis/connection/jredis/JredisConnectionIntegrationTests-context.xml b/src/test/resources/org/springframework/data/redis/connection/jredis/JredisConnectionIntegrationTests-context.xml index 96aea6242..13eb7935a 100644 --- a/src/test/resources/org/springframework/data/redis/connection/jredis/JredisConnectionIntegrationTests-context.xml +++ b/src/test/resources/org/springframework/data/redis/connection/jredis/JredisConnectionIntegrationTests-context.xml @@ -3,9 +3,9 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> - + diff --git a/src/test/resources/org/springframework/data/redis/connection/rjc/RjcConnectionPipelineIntegrationTests-context.xml b/src/test/resources/org/springframework/data/redis/connection/rjc/RjcConnectionPipelineIntegrationTests-context.xml new file mode 100644 index 000000000..3fb031250 --- /dev/null +++ b/src/test/resources/org/springframework/data/redis/connection/rjc/RjcConnectionPipelineIntegrationTests-context.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + \ No newline at end of file