From e003ef6ca3fac6f09ad2ebcb55cbd83d185aff8f Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Tue, 11 Feb 2014 15:42:34 +0100 Subject: [PATCH] DATAREDIS-206 - Add support for TIME operation. Enhanced RedisServerCommands to reflect time operation and added empty implementation to recent RedisConnection abstractions. Added implementation of time() for Srp, Jedis, Lettuce (emulated via eval). Added UnsupportedOperation of time() JRedis since it doesn't support time command or sending scripts or sending raw commands via the underlying connection. Added implementation for DefaultStringRedisConnection to delegate time() operation to native connection. Added integration test to abstract base class. Ignored the test for those connections not supporting time command. Original pull request: #34 --- .../DefaultStringRedisConnection.java | 13 +- .../redis/connection/RedisServerCommands.java | 11 +- .../redis/connection/convert/Converters.java | 17 ++- .../connection/jedis/JedisConnection.java | 19 +++ .../connection/jredis/JredisConnection.java | 13 +- .../connection/lettuce/LettuceConnection.java | 30 ++++- .../redis/connection/srp/SrpConnection.java | 22 +++- .../redis/connection/srp/SrpConverters.java | 35 +++++- .../AbstractConnectionIntegrationTests.java | 27 +++-- ...ultStringRedisConnectionPipelineTests.java | 17 ++- .../DefaultStringRedisConnectionTests.java | 19 ++- .../DefaultStringRedisConnectionTxTests.java | 34 +++++- .../JRedisConnectionIntegrationTests.java | 14 ++- .../LettuceConnectionIntegrationTests.java | 18 +-- ...uceConnectionPipelineIntegrationTests.java | 18 +-- ...eConnectionPipelineTxIntegrationTests.java | 19 ++- ...ConnectionTransactionIntegrationTests.java | 11 +- ...rpReplyToTimeAsLongConverterUnitTests.java | 113 ++++++++++++++++++ 18 files changed, 397 insertions(+), 53 deletions(-) create mode 100644 src/test/java/org/springframework/data/redis/connection/srp/SrpReplyToTimeAsLongConverterUnitTests.java diff --git a/src/main/java/org/springframework/data/redis/connection/DefaultStringRedisConnection.java b/src/main/java/org/springframework/data/redis/connection/DefaultStringRedisConnection.java index d5693c450..1b9bf44bc 100644 --- a/src/main/java/org/springframework/data/redis/connection/DefaultStringRedisConnection.java +++ b/src/main/java/org/springframework/data/redis/connection/DefaultStringRedisConnection.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2013 the original author or authors. + * Copyright 2011-2014 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. @@ -41,6 +41,7 @@ import org.springframework.util.Assert; * * @author Costin Leau * @author Jennifer Hickey + * @author Christoph Strobl */ public class DefaultStringRedisConnection implements StringRedisConnection { @@ -2144,6 +2145,15 @@ public class DefaultStringRedisConnection implements StringRedisConnection { return result; } + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#time() + */ + @Override + public Long time() { + return this.delegate.time(); + } + /** * Specifies if pipelined and tx results should be deserialized to Strings. If false, results of * {@link #closePipeline()} and {@link #exec()} will be of the type returned by the underlying connection @@ -2182,4 +2192,5 @@ public class DefaultStringRedisConnection implements StringRedisConnection { } return convertedResults; } + } diff --git a/src/main/java/org/springframework/data/redis/connection/RedisServerCommands.java b/src/main/java/org/springframework/data/redis/connection/RedisServerCommands.java index d3a220579..ce325e808 100644 --- a/src/main/java/org/springframework/data/redis/connection/RedisServerCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/RedisServerCommands.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2013 the original author or authors. + * Copyright 2011-2014 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. @@ -22,6 +22,7 @@ import java.util.Properties; * Server-specific commands supported by Redis. * * @author Costin Leau + * @author Christoph Strobl */ public interface RedisServerCommands { @@ -50,4 +51,12 @@ public interface RedisServerCommands { void setConfig(String param, String value); void resetConfigStats(); + + /** + * Request server timestamp using {@code TIME} command. + * + * @return current server time in milliseconds. + * @since 1.1 + */ + Long time(); } diff --git a/src/main/java/org/springframework/data/redis/connection/convert/Converters.java b/src/main/java/org/springframework/data/redis/connection/convert/Converters.java index 6cf3fbf94..ff930bed8 100644 --- a/src/main/java/org/springframework/data/redis/connection/convert/Converters.java +++ b/src/main/java/org/springframework/data/redis/connection/convert/Converters.java @@ -1,5 +1,5 @@ /* - * Copyright 2013 the original author or authors. + * Copyright 2013-2014 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. @@ -23,11 +23,13 @@ import java.util.Set; import org.springframework.core.convert.converter.Converter; import org.springframework.data.redis.connection.DataType; import org.springframework.data.redis.connection.RedisZSetCommands.Tuple; +import org.springframework.util.NumberUtils; /** * Common type converters * * @author Jennifer Hickey + * @author Thomas Darimont */ abstract public class Converters { @@ -73,4 +75,17 @@ abstract public class Converters { } return tupleArgs; } + + + /** + * Returns the timestamp constructed from the given {@code seconds} and {@code microseconds}. + * + * @param seconds server time in seconds + * @param microseconds elapsed microseconds in current second + * @return + */ + public static Long toTimeMillis(String seconds, String microseconds) { + return NumberUtils.parseNumber(seconds, Long.class) * 1000L + NumberUtils.parseNumber(microseconds, Long.class) + / 1000L; + } } diff --git a/src/main/java/org/springframework/data/redis/connection/jedis/JedisConnection.java b/src/main/java/org/springframework/data/redis/connection/jedis/JedisConnection.java index d26e946ad..edcad9597 100644 --- a/src/main/java/org/springframework/data/redis/connection/jedis/JedisConnection.java +++ b/src/main/java/org/springframework/data/redis/connection/jedis/JedisConnection.java @@ -39,8 +39,10 @@ import org.springframework.data.redis.connection.RedisSubscribedConnectionExcept import org.springframework.data.redis.connection.ReturnType; import org.springframework.data.redis.connection.SortParameters; import org.springframework.data.redis.connection.Subscription; +import org.springframework.data.redis.connection.convert.Converters; import org.springframework.data.redis.connection.convert.TransactionResultConverter; import org.springframework.util.Assert; +import org.springframework.util.NumberUtils; import org.springframework.util.ObjectUtils; import org.springframework.util.ReflectionUtils; @@ -67,6 +69,7 @@ import redis.clients.util.Pool; * @author Costin Leau * @author Jennifer Hickey * @author Christoph Strobl + * @author Thomas Darimont */ public class JedisConnection implements RedisConnection { @@ -2709,6 +2712,22 @@ public class JedisConnection implements RedisConnection { } } + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#time() + */ + @Override + public Long time() { + + List serverTimeInformation = this.jedis.time(); + + Assert.notEmpty(serverTimeInformation, "Received invalid result from server. Expected 2 items in collection."); + Assert.isTrue(serverTimeInformation.size() == 2, "Received invalid nr of arguments from redis server. Expected 2 received " + + serverTimeInformation.size()); + + return Converters.toTimeMillis(serverTimeInformation.get(0), serverTimeInformation.get(1)); + } + /** * Specifies if pipelined results should be converted to the expected data type. If false, results of * {@link #closePipeline()} and {@link #exec()} will be of the type returned by the Jedis driver diff --git a/src/main/java/org/springframework/data/redis/connection/jredis/JredisConnection.java b/src/main/java/org/springframework/data/redis/connection/jredis/JredisConnection.java index ec900708b..3d24f1f2b 100644 --- a/src/main/java/org/springframework/data/redis/connection/jredis/JredisConnection.java +++ b/src/main/java/org/springframework/data/redis/connection/jredis/JredisConnection.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2013 the original author or authors. + * Copyright 2011-2014 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. @@ -52,6 +52,8 @@ import org.springframework.util.ReflectionUtils; * * @author Costin Leau * @author Jennifer Hickey + * @author Christoph Strobl + * @author Thomas Darimont */ public class JredisConnection implements RedisConnection { @@ -1148,4 +1150,13 @@ public class JredisConnection implements RedisConnection { public T evalSha(String scriptSha1, ReturnType returnType, int numKeys, byte[]... keysAndArgs) { throw new UnsupportedOperationException(); } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#time() + */ + @Override + public Long time() { + throw new UnsupportedOperationException("The 'TIME' command is not supported by the JRedis driver."); + } } diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConnection.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConnection.java index dcd0646b6..a363f7675 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConnection.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConnection.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2013 the original author or authors. + * Copyright 2011-2014 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. @@ -15,7 +15,7 @@ */ package org.springframework.data.redis.connection.lettuce; -import static com.lambdaworks.redis.protocol.CommandType.MULTI; +import static com.lambdaworks.redis.protocol.CommandType.*; import java.util.ArrayList; import java.util.Arrays; @@ -43,8 +43,10 @@ import org.springframework.data.redis.connection.RedisSubscribedConnectionExcept import org.springframework.data.redis.connection.ReturnType; import org.springframework.data.redis.connection.SortParameters; import org.springframework.data.redis.connection.Subscription; +import org.springframework.data.redis.connection.convert.Converters; import org.springframework.data.redis.connection.convert.TransactionResultConverter; import org.springframework.util.Assert; +import org.springframework.util.NumberUtils; import org.springframework.util.ObjectUtils; import com.lambdaworks.redis.RedisAsyncConnection; @@ -64,6 +66,8 @@ import com.lambdaworks.redis.pubsub.RedisPubSubConnection; * * @author Costin Leau * @author Jennifer Hickey + * @author Christoph Strobl + * @author Thomas Darimont */ public class LettuceConnection implements RedisConnection { @@ -2760,6 +2764,27 @@ public class LettuceConnection implements RedisConnection { } } + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#time() + */ + @Override + public Long time() { + + /* + * We have to emulate the time command via eval script since the current driver version doesn't + * support the time command natively. + * see https://github.com/wg/lettuce/issues/19 + */ + List result = (List)eval("return redis.call('TIME')".getBytes(),ReturnType.MULTI,0); + + Assert.notEmpty(result, "Received invalid result from server. Expected 2 items in collection."); + Assert.isTrue(result.size() == 2, "Received invalid nr of arguments from redis server. Expected 2 received " + + result.size()); + + return Converters.toTimeMillis(new String(result.get(0)), new String(result.get(1))); + } + /** * Specifies if pipelined and transaction results should be converted to the expected data type. If false, results of * {@link #closePipeline()} and {@link #exec()} will be of the type returned by the Lettuce driver @@ -2905,4 +2930,5 @@ public class LettuceConnection implements RedisConnection { args.weights(lg); return args; } + } diff --git a/src/main/java/org/springframework/data/redis/connection/srp/SrpConnection.java b/src/main/java/org/springframework/data/redis/connection/srp/SrpConnection.java index a25bef6eb..5594c0ccd 100644 --- a/src/main/java/org/springframework/data/redis/connection/srp/SrpConnection.java +++ b/src/main/java/org/springframework/data/redis/connection/srp/SrpConnection.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2013 the original author or authors. + * Copyright 2011-2014 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. @@ -59,6 +59,7 @@ import com.google.common.util.concurrent.ListenableFuture; * * @author Costin Leau * @author Jennifer Hickey + * @author Christoph Strobl */ public class SrpConnection implements RedisConnection { @@ -2138,6 +2139,24 @@ public class SrpConnection implements RedisConnection { return results; } + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#time() + */ + @Override + public Long time() { + + if (isPipelined()) { + pipeline(new SrpGenericResult(pipeline.time(), SrpConverters.repliesToTimeAsLong())); + return null; + } + + MultiBulkReply reply = this.client.time(); + Assert.notNull(reply, "Received invalid result from server. MultiBulkReply must not be empty."); + + return SrpConverters.toTimeAsLong(reply.data()); + } + private List closeTransaction() { List results = Collections.emptyList(); if (txTracker != null) { @@ -2231,4 +2250,5 @@ public class SrpConnection implements RedisConnection { } return arrays.toArray(); } + } diff --git a/src/main/java/org/springframework/data/redis/connection/srp/SrpConverters.java b/src/main/java/org/springframework/data/redis/connection/srp/SrpConverters.java index 453ac1048..ee6b03217 100644 --- a/src/main/java/org/springframework/data/redis/connection/srp/SrpConverters.java +++ b/src/main/java/org/springframework/data/redis/connection/srp/SrpConverters.java @@ -1,5 +1,5 @@ /* - * Copyright 2013 the original author or authors. + * Copyright 2013-2014 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. @@ -35,6 +35,7 @@ import org.springframework.data.redis.connection.RedisStringCommands.BitOperatio import org.springframework.data.redis.connection.RedisZSetCommands.Tuple; import org.springframework.data.redis.connection.convert.Converters; import org.springframework.util.Assert; +import org.springframework.util.NumberUtils; import redis.client.RedisException; import redis.reply.IntegerReply; @@ -46,6 +47,8 @@ import com.google.common.base.Charsets; * SRP type converters * * @author Jennifer Hickey + * @author Christoph Strobl + * @author Thomas Darimont */ @SuppressWarnings("rawtypes") abstract public class SrpConverters extends Converters { @@ -61,6 +64,7 @@ abstract public class SrpConverters extends Converters { private static final Converter BYTES_TO_PROPERTIES; private static final Converter BYTES_TO_STRING; private static final Converter BYTES_TO_DOUBLE; + private static final Converter REPLIES_TO_TIME_AS_LONG; static { REPLIES_TO_BYTES_LIST = new Converter>() { @@ -96,6 +100,21 @@ abstract public class SrpConverters extends Converters { return (bytes == null || bytes.length == 0 ? null : Double.valueOf(new String(bytes, Charsets.UTF_8))); } }; + REPLIES_TO_TIME_AS_LONG = new Converter() { + + @Override + public Long convert(Reply[] reply) { + + Assert.notEmpty(reply, "Received invalid result from server. Expected 2 items in collection."); + Assert.isTrue(reply.length == 2, "Received invalid nr of arguments from redis server. Expected 2 received " + + reply.length); + + List serverTimeInformation = REPLIES_TO_STRING_LIST.convert(reply); + + return Converters.toTimeMillis(serverTimeInformation.get(0), serverTimeInformation.get(1)); + } + + }; REPLIES_TO_TUPLE_SET = new Converter>() { public Set convert(Reply[] byteArrays) { if (byteArrays == null) { @@ -190,6 +209,10 @@ abstract public class SrpConverters extends Converters { return REPLIES_TO_STRING_LIST; } + public static Converter repliesToTimeAsLong() { + return REPLIES_TO_TIME_AS_LONG; + } + public static List toBytesList(Reply[] source) { return REPLIES_TO_BYTES_LIST.convert(source); } @@ -226,6 +249,16 @@ abstract public class SrpConverters extends Converters { return REPLIES_TO_STRING_LIST.convert(source); } + /** + * Converts given {@link Reply}s to {@link Long}. + * + * @param source Array holding time values in seconds and microseconds. + * @return + */ + public static Long toTimeAsLong(Reply[] source) { + return REPLIES_TO_TIME_AS_LONG.convert(source); + } + public static byte[] toBytes(BitOperation op) { Assert.notNull(op, "The bit operation is required"); return op.name().toUpperCase().getBytes(Charsets.UTF_8); 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 f869bfd30..4a0943f3b 100644 --- a/src/test/java/org/springframework/data/redis/connection/AbstractConnectionIntegrationTests.java +++ b/src/test/java/org/springframework/data/redis/connection/AbstractConnectionIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2013 the original author or authors. + * Copyright 2011-2014 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. @@ -13,16 +13,13 @@ * 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 static org.junit.Assert.fail; -import static org.junit.Assume.assumeTrue; -import static org.springframework.data.redis.SpinBarrier.waitFor; +import static org.hamcrest.core.IsEqual.*; +import static org.hamcrest.core.IsNull.*; +import static org.junit.Assert.*; +import static org.junit.Assume.*; +import static org.springframework.data.redis.SpinBarrier.*; import java.util.ArrayList; import java.util.Arrays; @@ -68,6 +65,7 @@ import org.springframework.test.annotation.ProfileValueSourceConfiguration; * * @author Costin Leau * @author Jennifer Hickey + * @author Christoph Strobl */ @ProfileValueSourceConfiguration(RedisTestProfileValueSource.class) public abstract class AbstractConnectionIntegrationTests { @@ -1860,6 +1858,17 @@ public abstract class AbstractConnectionIntegrationTests { assertNotNull(results.get(0)); } + /** + * @see DATAREDIS-206 + */ + @Test + public void testGetTimeShouldRequestServerTime() { + + Long time = connectionFactory.getConnection().time(); + assertThat(time, notNullValue()); + assertThat(time > 0, equalTo(true)); + } + protected void verifyResults(List expected) { assertEquals(expected, getResults()); } diff --git a/src/test/java/org/springframework/data/redis/connection/DefaultStringRedisConnectionPipelineTests.java b/src/test/java/org/springframework/data/redis/connection/DefaultStringRedisConnectionPipelineTests.java index 951309090..b79477437 100644 --- a/src/test/java/org/springframework/data/redis/connection/DefaultStringRedisConnectionPipelineTests.java +++ b/src/test/java/org/springframework/data/redis/connection/DefaultStringRedisConnectionPipelineTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2013 the original author or authors. + * Copyright 2013-2014 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. @@ -15,8 +15,7 @@ */ package org.springframework.data.redis.connection; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.when; +import static org.mockito.Mockito.*; import java.util.Arrays; import java.util.Collections; @@ -30,6 +29,7 @@ import org.junit.Test; * Unit test of {@link DefaultStringRedisConnection} that executes commands in a pipeline * * @author Jennifer Hickey + * @author Christoph Strobl */ public class DefaultStringRedisConnectionPipelineTests extends DefaultStringRedisConnectionTests { @@ -1429,6 +1429,17 @@ public class DefaultStringRedisConnectionPipelineTests extends DefaultStringRedi verifyResults(Arrays.asList(new Object[] { barBytes, 3l })); } + /** + * @see DATAREDIS-206 + */ + @Test + @Override + public void testTimeIsDelegatedCorrectlyToNativeConnection() { + + doReturn(Arrays.asList(1L)).when(nativeConnection).closePipeline(); + super.testTimeIsDelegatedCorrectlyToNativeConnection(); + } + protected List getResults() { return connection.closePipeline(); } diff --git a/src/test/java/org/springframework/data/redis/connection/DefaultStringRedisConnectionTests.java b/src/test/java/org/springframework/data/redis/connection/DefaultStringRedisConnectionTests.java index 47f5bfff6..ea1a3d3e5 100644 --- a/src/test/java/org/springframework/data/redis/connection/DefaultStringRedisConnectionTests.java +++ b/src/test/java/org/springframework/data/redis/connection/DefaultStringRedisConnectionTests.java @@ -15,9 +15,9 @@ */ package org.springframework.data.redis.connection; -import static org.junit.Assert.assertEquals; -import static org.mockito.Matchers.anyMap; -import static org.mockito.Mockito.doReturn; +import static org.junit.Assert.*; +import static org.mockito.Matchers.*; +import static org.mockito.Mockito.*; import java.util.ArrayList; import java.util.Arrays; @@ -1677,11 +1677,22 @@ public class DefaultStringRedisConnectionTests { verifyResults(Arrays.asList(new Object[] { "foo" })); } + /** + * @see DATAREDIS-206 + */ + @Test + public void testTimeIsDelegatedCorrectlyToNativeConnection() { + + doReturn(1L).when(nativeConnection).time(); + actual.add(connection.time()); + verifyResults(Arrays.asList(1L)); + } + protected List getResults() { return actual; } - protected void verifyResults(List expected) { + protected void verifyResults(List expected) { assertEquals(expected, getResults()); } } diff --git a/src/test/java/org/springframework/data/redis/connection/DefaultStringRedisConnectionTxTests.java b/src/test/java/org/springframework/data/redis/connection/DefaultStringRedisConnectionTxTests.java index de9b9b02a..88051a298 100644 --- a/src/test/java/org/springframework/data/redis/connection/DefaultStringRedisConnectionTxTests.java +++ b/src/test/java/org/springframework/data/redis/connection/DefaultStringRedisConnectionTxTests.java @@ -1,7 +1,21 @@ +/* + * Copyright 2013-2014 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.mockito.Mockito.doReturn; -import static org.mockito.Mockito.when; +import static org.mockito.Mockito.*; import java.util.Arrays; import java.util.Collections; @@ -11,6 +25,10 @@ import java.util.Properties; import org.junit.Before; import org.junit.Test; +/** + * @author Jennifer Hickey + * @author Christoph Strobl + */ public class DefaultStringRedisConnectionTxTests extends DefaultStringRedisConnectionTests { @Before @@ -1413,6 +1431,18 @@ public class DefaultStringRedisConnectionTxTests extends DefaultStringRedisConne verifyResults(Arrays.asList(new Object[] { foo })); } + /** + * @see DATAREDIS-206 + */ + @Test + @Override + public void testTimeIsDelegatedCorrectlyToNativeConnection() { + + doReturn(Arrays.asList(new Object[] { 1L })).when(nativeConnection).exec(); + doReturn(Arrays.asList(new Object[] { Arrays.asList(new Object[] { 1L }) })).when(nativeConnection).closePipeline(); + super.testTimeIsDelegatedCorrectlyToNativeConnection(); + } + protected List getResults() { return connection.exec(); } 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 5ba4660ec..96ace9c12 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 @@ -1,5 +1,5 @@ /* - * Copyright 2011-2013 the original author or authors. + * Copyright 2011-2014 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. @@ -16,8 +16,7 @@ package org.springframework.data.redis.connection.jredis; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; +import static org.junit.Assert.*; import java.util.Arrays; import java.util.Collections; @@ -48,6 +47,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; * * @author Costin Leau * @author Jennifer Hickey + * @author Christoph Strobl */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration @@ -770,4 +770,12 @@ public class JRedisConnectionIntegrationTests extends AbstractConnectionIntegrat } } + /** + * @see DATAREDIS-206 + */ + @Test(expected = UnsupportedOperationException.class) + public void testGetTimeShouldRequestServerTime() { + super.testGetTimeShouldRequestServerTime(); + } + } 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 ad8cf1c11..5b6c553db 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 @@ -1,5 +1,5 @@ /* - * Copyright 2011-2013 the original author or authors. + * Copyright 2011-2014 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. @@ -16,7 +16,13 @@ package org.springframework.data.redis.connection.lettuce; -import com.lambdaworks.redis.RedisAsyncConnection; +import static org.junit.Assert.*; +import static org.junit.Assume.*; +import static org.springframework.data.redis.SpinBarrier.*; + +import java.util.Arrays; +import java.util.concurrent.atomic.AtomicBoolean; + import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.dao.DataAccessException; @@ -33,12 +39,7 @@ import org.springframework.test.annotation.IfProfileValue; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import java.util.Arrays; -import java.util.concurrent.atomic.AtomicBoolean; - -import static org.junit.Assert.*; -import static org.junit.Assume.assumeTrue; -import static org.springframework.data.redis.SpinBarrier.waitFor; +import com.lambdaworks.redis.RedisAsyncConnection; /** * Integration test of {@link LettuceConnection} @@ -46,6 +47,7 @@ import static org.springframework.data.redis.SpinBarrier.waitFor; * @author Costin Leau * @author Jennifer Hickey * @author Thomas Darimont + * @author Christoph Strobl */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration 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 index 0eddc1ae7..88e03211f 100644 --- a/src/test/java/org/springframework/data/redis/connection/lettuce/LettuceConnectionPipelineIntegrationTests.java +++ b/src/test/java/org/springframework/data/redis/connection/lettuce/LettuceConnectionPipelineIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2013 the original author or authors. + * Copyright 2011-2014 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. @@ -15,6 +15,13 @@ */ package org.springframework.data.redis.connection.lettuce; +import static org.junit.Assert.*; +import static org.junit.Assume.*; +import static org.springframework.data.redis.SpinBarrier.*; + +import java.util.Arrays; +import java.util.concurrent.atomic.AtomicBoolean; + import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.dao.DataAccessException; @@ -29,19 +36,12 @@ import org.springframework.test.annotation.IfProfileValue; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import java.util.Arrays; -import java.util.concurrent.atomic.AtomicBoolean; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.junit.Assume.assumeTrue; -import static org.springframework.data.redis.SpinBarrier.waitFor; - /** * Integration test of {@link LettuceConnection} pipeline functionality * * @author Jennifer Hickey * @author Thomas Darimont + * @author Christoph Strobl */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("LettuceConnectionIntegrationTests-context.xml") diff --git a/src/test/java/org/springframework/data/redis/connection/lettuce/LettuceConnectionPipelineTxIntegrationTests.java b/src/test/java/org/springframework/data/redis/connection/lettuce/LettuceConnectionPipelineTxIntegrationTests.java index 8eb7b8672..294a3b522 100644 --- a/src/test/java/org/springframework/data/redis/connection/lettuce/LettuceConnectionPipelineTxIntegrationTests.java +++ b/src/test/java/org/springframework/data/redis/connection/lettuce/LettuceConnectionPipelineTxIntegrationTests.java @@ -1,7 +1,21 @@ +/* + * Copyright 2013-2014 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.assertNull; +import static org.junit.Assert.*; import java.util.List; @@ -13,6 +27,7 @@ import org.springframework.test.annotation.IfProfileValue; * Integration test of {@link LettuceConnection} transactions within a pipeline * * @author Jennifer Hickey + * @author Christoph Strobl */ public class LettuceConnectionPipelineTxIntegrationTests extends LettuceConnectionTransactionIntegrationTests { diff --git a/src/test/java/org/springframework/data/redis/connection/lettuce/LettuceConnectionTransactionIntegrationTests.java b/src/test/java/org/springframework/data/redis/connection/lettuce/LettuceConnectionTransactionIntegrationTests.java index d8842804d..1c48f12aa 100644 --- a/src/test/java/org/springframework/data/redis/connection/lettuce/LettuceConnectionTransactionIntegrationTests.java +++ b/src/test/java/org/springframework/data/redis/connection/lettuce/LettuceConnectionTransactionIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2013 the original author or authors. + * Copyright 2011-2014 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. @@ -15,6 +15,10 @@ */ package org.springframework.data.redis.connection.lettuce; +import static org.junit.Assert.*; + +import java.util.Arrays; + import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; @@ -25,15 +29,12 @@ import org.springframework.test.annotation.IfProfileValue; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import java.util.Arrays; - -import static org.junit.Assert.assertEquals; - /** * Integration test of {@link LettuceConnection} functionality within a transaction * * @author Jennifer Hickey * @author Thomas Darimont + * @author Christoph Strobl */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("LettuceConnectionIntegrationTests-context.xml") diff --git a/src/test/java/org/springframework/data/redis/connection/srp/SrpReplyToTimeAsLongConverterUnitTests.java b/src/test/java/org/springframework/data/redis/connection/srp/SrpReplyToTimeAsLongConverterUnitTests.java new file mode 100644 index 000000000..5d9c9f9b1 --- /dev/null +++ b/src/test/java/org/springframework/data/redis/connection/srp/SrpReplyToTimeAsLongConverterUnitTests.java @@ -0,0 +1,113 @@ +/* + * Copyright 2014 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 java.nio.charset.Charset; + +import org.hamcrest.core.IsEqual; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.springframework.core.convert.converter.Converter; + +import redis.reply.BulkReply; +import redis.reply.Reply; + +/** + * @author Christoph Strobl + * @author Thomas Darimont + */ +public class SrpReplyToTimeAsLongConverterUnitTests { + + @SuppressWarnings("rawtypes") private Converter converter; + + @Before + public void setUp() { + this.converter = SrpConverters.repliesToTimeAsLong(); + } + + /** + * @see DATAREDIS-206 + */ + @Test + public void testConverterShouldCreateMillisecondsCorrectlyWhenGivenValidReplyArray() { + + Reply seconds = new BulkReply("1392183718".getBytes(Charset.forName("UTF-8"))); + Reply microseconds = new BulkReply("555122".getBytes(Charset.forName("UTF-8"))); + + Assert.assertThat(converter.convert(new Reply[] { seconds, microseconds }), IsEqual.equalTo(1392183718555L)); + } + + /** + * @see DATAREDIS-206 + */ + @Test(expected = IllegalArgumentException.class) + public void testConverterShouldThrowExceptionWhenGivenReplyArrayIsNull() { + + converter.convert(null); + } + + /** + * @see DATAREDIS-206 + */ + @Test(expected = IllegalArgumentException.class) + public void testConverterShouldThrowExceptionWhenGivenReplyArrayIsEmpty() { + + converter.convert(new Reply[] {}); + } + + /** + * @see DATAREDIS-206 + */ + @Test(expected = IllegalArgumentException.class) + public void testConverterShouldThrowExceptionWhenGivenReplyArrayHasOnlyOneItem() { + + converter.convert(new Reply[] { new BulkReply(null) }); + } + + /** + * @see DATAREDIS-206 + */ + @Test(expected = IllegalArgumentException.class) + public void testConverterShouldThrowExceptionWhenGivenReplyArrayMoreThanTwoItems() { + + converter.convert(new Reply[] { new BulkReply(null), new BulkReply(null), new BulkReply(null) }); + } + + /** + * @see DATAREDIS-206 + */ + @Test(expected = NumberFormatException.class) + public void testConverterShouldThrowExecptionForNonParsableReply() { + + Reply invalidDataBlock = new BulkReply("123-not-a-number".getBytes(Charset.forName("UTF-8"))); + Reply microseconds = new BulkReply("555122".getBytes(Charset.forName("UTF-8"))); + + converter.convert(new Reply[] { invalidDataBlock, microseconds }); + } + + /** + * @see DATAREDIS-206 + */ + @Test(expected = IllegalArgumentException.class) + public void testConverterShouldThrowExecptionForEmptyDataBlocks() { + + Reply invalidDataBlock = new BulkReply(null); + Reply microseconds = new BulkReply("555122".getBytes(Charset.forName("UTF-8"))); + + converter.convert(new Reply[] { invalidDataBlock, microseconds }); + } +}