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