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
This commit is contained in:
Christoph Strobl
2014-02-11 15:42:34 +01:00
committed by Thomas Darimont
parent b4cc33a24c
commit e003ef6ca3
18 changed files with 397 additions and 53 deletions

View File

@@ -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;
}
}

View File

@@ -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();
}

View File

@@ -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;
}
}

View File

@@ -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<String> 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

View File

@@ -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> 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.");
}
}

View File

@@ -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<byte[]> result = (List<byte[]>)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;
}
}

View File

@@ -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<Object> closeTransaction() {
List<Object> results = Collections.emptyList();
if (txTracker != null) {
@@ -2231,4 +2250,5 @@ public class SrpConnection implements RedisConnection {
}
return arrays.toArray();
}
}

View File

@@ -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<byte[], Properties> BYTES_TO_PROPERTIES;
private static final Converter<byte[], String> BYTES_TO_STRING;
private static final Converter<byte[], Double> BYTES_TO_DOUBLE;
private static final Converter<Reply[], Long> REPLIES_TO_TIME_AS_LONG;
static {
REPLIES_TO_BYTES_LIST = new Converter<Reply[], List<byte[]>>() {
@@ -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<Reply[], Long>() {
@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<String> serverTimeInformation = REPLIES_TO_STRING_LIST.convert(reply);
return Converters.toTimeMillis(serverTimeInformation.get(0), serverTimeInformation.get(1));
}
};
REPLIES_TO_TUPLE_SET = new Converter<Reply[], Set<Tuple>>() {
public Set<Tuple> convert(Reply[] byteArrays) {
if (byteArrays == null) {
@@ -190,6 +209,10 @@ abstract public class SrpConverters extends Converters {
return REPLIES_TO_STRING_LIST;
}
public static Converter<Reply[], Long> repliesToTimeAsLong() {
return REPLIES_TO_TIME_AS_LONG;
}
public static List<byte[]> 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);

View File

@@ -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<Object> expected) {
assertEquals(expected, getResults());
}

View File

@@ -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<Object> getResults() {
return connection.closePipeline();
}

View File

@@ -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<Object> getResults() {
return actual;
}
protected void verifyResults(List<Object> expected) {
protected void verifyResults(List<?> expected) {
assertEquals(expected, getResults());
}
}

View File

@@ -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<Object> getResults() {
return connection.exec();
}

View File

@@ -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();
}
}

View File

@@ -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

View File

@@ -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")

View File

@@ -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 {

View File

@@ -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")

View File

@@ -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<Reply[], Long> 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 });
}
}