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 }); + } +}