Add Redis 2.6 dump and restore commands to Connections
DATAREDIS-182
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.redis;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Jennifer Hickey
|
||||
*
|
||||
*/
|
||||
abstract public class SpinBarrier {
|
||||
|
||||
/**
|
||||
* Periodically tests for a condition until it is met or a timeout occurs
|
||||
*
|
||||
* @param condition
|
||||
* The condition to periodically test
|
||||
* @param timeout
|
||||
* The timeout
|
||||
* @return true if condition passes, false if condition does not pass within
|
||||
* timeout
|
||||
*/
|
||||
public static boolean waitFor(TestCondition condition, long timeout) {
|
||||
boolean passes = false;
|
||||
for (long currentTime = System.currentTimeMillis(); System.currentTimeMillis() - currentTime < timeout;) {
|
||||
if (condition.passes()) {
|
||||
passes = true;
|
||||
break;
|
||||
}
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
return passes;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.redis;
|
||||
|
||||
/**
|
||||
*
|
||||
* A condition to test periodically, used in conjunction with
|
||||
* {@link SpinBarrier}
|
||||
*
|
||||
* @author Jennifer Hickey
|
||||
*
|
||||
*/
|
||||
public interface TestCondition {
|
||||
|
||||
/**
|
||||
*
|
||||
* @return true if condition passes
|
||||
*/
|
||||
boolean passes();
|
||||
}
|
||||
@@ -22,6 +22,7 @@ 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.springframework.data.redis.SpinBarrier.waitFor;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@@ -44,7 +45,9 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.data.redis.Address;
|
||||
import org.springframework.data.redis.Person;
|
||||
import org.springframework.data.redis.RedisSystemException;
|
||||
import org.springframework.data.redis.RedisTestProfileValueSource;
|
||||
import org.springframework.data.redis.TestCondition;
|
||||
import org.springframework.data.redis.connection.RedisListCommands.Position;
|
||||
import org.springframework.data.redis.connection.RedisZSetCommands.Aggregate;
|
||||
import org.springframework.data.redis.connection.RedisZSetCommands.Tuple;
|
||||
@@ -562,6 +565,53 @@ public abstract class AbstractConnectionIntegrationTests {
|
||||
assertTrue(connection.pTtl("whatup") > -1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@IfProfileValue(name = "redisVersion", value = "2.6")
|
||||
public void testDumpAndRestore() {
|
||||
connection.set("testing", "12");
|
||||
byte[] serializedResults = connection.dump("testing".getBytes());
|
||||
assertNotNull(serializedResults);
|
||||
connection.del("testing");
|
||||
assertNull(connection.get("testing"));
|
||||
connection.restore("testing".getBytes(), 0, serializedResults);
|
||||
assertEquals("12",connection.get("testing"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@IfProfileValue(name = "redisVersion", value = "2.6")
|
||||
public void testDumpNonExistentKey() {
|
||||
actual.add(connection.dump("fakey".getBytes()));
|
||||
verifyResults(Arrays.asList(new Object[] { null }), actual);
|
||||
}
|
||||
|
||||
@Test(expected=RedisSystemException.class)
|
||||
@IfProfileValue(name = "redisVersion", value = "2.6")
|
||||
public void testRestoreBadData() {
|
||||
// Use something other than dump-specific serialization
|
||||
connection.restore("testing".getBytes(), 0, "foo".getBytes());
|
||||
}
|
||||
|
||||
@Test(expected=RedisSystemException.class)
|
||||
@IfProfileValue(name = "redisVersion", value = "2.6")
|
||||
public void testRestoreExistingKey() {
|
||||
connection.set("testing", "12");
|
||||
byte[] serializedResults = connection.dump("testing".getBytes());
|
||||
assertNotNull(serializedResults);
|
||||
connection.restore("testing".getBytes(), 0, serializedResults);
|
||||
}
|
||||
|
||||
@Test
|
||||
@IfProfileValue(name = "redisVersion", value = "2.6")
|
||||
public void testRestoreTtl() {
|
||||
connection.set("testing", "12");
|
||||
byte[] serializedResults = connection.dump("testing".getBytes());
|
||||
assertNotNull(serializedResults);
|
||||
connection.del("testing");
|
||||
assertNull(connection.get("testing"));
|
||||
connection.restore("testing".getBytes(), 100l, serializedResults);
|
||||
assertTrue(waitFor(new KeyExpired("testing"), 300l));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testType() {
|
||||
connection.set("something", "yo");
|
||||
@@ -1257,26 +1307,6 @@ public abstract class AbstractConnectionIntegrationTests {
|
||||
assertEquals(expected, actual);
|
||||
}
|
||||
|
||||
protected boolean waitFor(TestCondition condition, long timeout) {
|
||||
boolean passes = false;
|
||||
for (long currentTime = System.currentTimeMillis(); System.currentTimeMillis()
|
||||
- currentTime < timeout;) {
|
||||
if (condition.passes()) {
|
||||
passes = true;
|
||||
break;
|
||||
}
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
return passes;
|
||||
}
|
||||
|
||||
protected interface TestCondition {
|
||||
public boolean passes();
|
||||
}
|
||||
|
||||
protected class KeyExpired implements TestCondition {
|
||||
private String key;
|
||||
|
||||
|
||||
@@ -20,6 +20,8 @@ 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.springframework.data.redis.SpinBarrier.waitFor;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@@ -35,6 +37,7 @@ import java.util.UUID;
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.springframework.data.redis.TestCondition;
|
||||
import org.springframework.data.redis.connection.RedisZSetCommands.Aggregate;
|
||||
import org.springframework.data.redis.connection.RedisZSetCommands.Tuple;
|
||||
import org.springframework.data.redis.connection.StringRedisConnection.StringTuple;
|
||||
@@ -160,6 +163,57 @@ abstract public class AbstractConnectionPipelineIntegrationTests extends
|
||||
}, 1000l));
|
||||
}
|
||||
|
||||
@Test(expected=RedisPipelineException.class)
|
||||
@IfProfileValue(name = "redisVersion", value = "2.6")
|
||||
public void testRestoreBadData() {
|
||||
// Use something other than dump-specific serialization
|
||||
connection.restore("testing".getBytes(), 0, "foo".getBytes());
|
||||
getResults();
|
||||
}
|
||||
|
||||
@Test
|
||||
@IfProfileValue(name = "redisVersion", value = "2.6")
|
||||
public void testRestoreExistingKey() {
|
||||
connection.set("testing", "12");
|
||||
connection.dump("testing".getBytes());
|
||||
List<Object> results = getResults();
|
||||
initConnection();
|
||||
connection.restore("testing".getBytes(), 0, (byte[]) results.get(1));
|
||||
try {
|
||||
getResults();
|
||||
fail("Expected pipeline exception restoring an existing key");
|
||||
}catch(RedisPipelineException e) {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@IfProfileValue(name = "redisVersion", value = "2.6")
|
||||
public void testRestoreTtl() {
|
||||
connection.set("testing", "12");
|
||||
connection.dump("testing".getBytes());
|
||||
List<Object> results = getResults();
|
||||
initConnection();
|
||||
actual.add(connection.del("testing"));
|
||||
actual.add(connection.get("testing"));
|
||||
connection.restore("testing".getBytes(), 100l, (byte[]) results.get(results.size() - 1));
|
||||
verifyResults(Arrays.asList(new Object[] { 1l, null }), actual);
|
||||
assertTrue(waitFor(new KeyExpired("testing"), 300l));
|
||||
}
|
||||
|
||||
@Test
|
||||
@IfProfileValue(name = "redisVersion", value = "2.6")
|
||||
public void testDumpAndRestore() {
|
||||
connection.set("testing", "12");
|
||||
connection.dump("testing".getBytes());
|
||||
List<Object> results = getResults();
|
||||
initConnection();
|
||||
actual.add(connection.del("testing"));
|
||||
actual.add((connection.get("testing")));
|
||||
connection.restore("testing".getBytes(), 0, (byte[]) results.get(results.size() - 1));
|
||||
actual.add(connection.get("testing"));
|
||||
verifyResults(Arrays.asList(new Object[] { 1l, null, "12" }), actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
@IfProfileValue(name = "runLongTests", value = "true")
|
||||
public void testExpire() throws Exception {
|
||||
|
||||
@@ -80,6 +80,31 @@ public class JedisConnectionIntegrationTests extends AbstractConnectionIntegrati
|
||||
super.testPTtlNoExpire();
|
||||
}
|
||||
|
||||
@Test(expected=UnsupportedOperationException.class)
|
||||
public void testDumpAndRestore() {
|
||||
super.testDumpAndRestore();
|
||||
}
|
||||
|
||||
@Test(expected=UnsupportedOperationException.class)
|
||||
public void testDumpNonExistentKey() {
|
||||
super.testDumpNonExistentKey();
|
||||
}
|
||||
|
||||
@Test(expected=UnsupportedOperationException.class)
|
||||
public void testRestoreBadData() {
|
||||
super.testRestoreBadData();
|
||||
}
|
||||
|
||||
@Test(expected=UnsupportedOperationException.class)
|
||||
public void testRestoreExistingKey() {
|
||||
super.testRestoreExistingKey();
|
||||
}
|
||||
|
||||
@Test(expected=UnsupportedOperationException.class)
|
||||
public void testRestoreTtl() {
|
||||
super.testRestoreTtl();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIncrDecrByLong() {
|
||||
String key = "test.count";
|
||||
|
||||
@@ -122,6 +122,31 @@ public class JedisConnectionPipelineIntegrationTests extends
|
||||
super.testPTtlNoExpire();
|
||||
}
|
||||
|
||||
@Test(expected=UnsupportedOperationException.class)
|
||||
public void testDumpAndRestore() {
|
||||
super.testDumpAndRestore();
|
||||
}
|
||||
|
||||
@Test(expected=UnsupportedOperationException.class)
|
||||
public void testDumpNonExistentKey() {
|
||||
super.testDumpNonExistentKey();
|
||||
}
|
||||
|
||||
@Test(expected=UnsupportedOperationException.class)
|
||||
public void testRestoreBadData() {
|
||||
super.testRestoreBadData();
|
||||
}
|
||||
|
||||
@Test(expected=UnsupportedOperationException.class)
|
||||
public void testRestoreExistingKey() {
|
||||
super.testRestoreExistingKey();
|
||||
}
|
||||
|
||||
@Test(expected=UnsupportedOperationException.class)
|
||||
public void testRestoreTtl() {
|
||||
super.testRestoreTtl();
|
||||
}
|
||||
|
||||
@Test(expected = RedisSystemException.class)
|
||||
public void testBitSet() throws Exception {
|
||||
super.testBitSet();
|
||||
|
||||
@@ -318,6 +318,31 @@ public class JRedisConnectionIntegrationTests extends AbstractConnectionIntegrat
|
||||
super.testPTtlNoExpire();
|
||||
}
|
||||
|
||||
@Test(expected=UnsupportedOperationException.class)
|
||||
public void testDumpAndRestore() {
|
||||
super.testDumpAndRestore();
|
||||
}
|
||||
|
||||
@Test(expected=UnsupportedOperationException.class)
|
||||
public void testDumpNonExistentKey() {
|
||||
super.testDumpNonExistentKey();
|
||||
}
|
||||
|
||||
@Test(expected=UnsupportedOperationException.class)
|
||||
public void testRestoreBadData() {
|
||||
super.testRestoreBadData();
|
||||
}
|
||||
|
||||
@Test(expected=UnsupportedOperationException.class)
|
||||
public void testRestoreExistingKey() {
|
||||
super.testRestoreExistingKey();
|
||||
}
|
||||
|
||||
@Test(expected=UnsupportedOperationException.class)
|
||||
public void testRestoreTtl() {
|
||||
super.testRestoreTtl();
|
||||
}
|
||||
|
||||
// Jredis returns null for rPush
|
||||
@Test
|
||||
public void testSort() {
|
||||
|
||||
@@ -27,6 +27,7 @@ import org.junit.runner.RunWith;
|
||||
import org.springframework.data.redis.RedisSystemException;
|
||||
import org.springframework.data.redis.connection.AbstractConnectionIntegrationTests;
|
||||
import org.springframework.data.redis.connection.DefaultStringRedisConnection;
|
||||
import org.springframework.test.annotation.IfProfileValue;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
@@ -42,6 +43,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
public class LettuceConnectionIntegrationTests extends AbstractConnectionIntegrationTests {
|
||||
|
||||
@Test
|
||||
@IfProfileValue(name = "runLongTests", value = "true")
|
||||
public void testMultiThreadsOneBlocking() throws Exception {
|
||||
Thread th = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
|
||||
@@ -19,7 +19,7 @@ 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.springframework.data.redis.SpinBarrier.waitFor;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
@@ -32,6 +32,7 @@ import java.util.UUID;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.data.redis.TestCondition;
|
||||
import org.springframework.data.redis.connection.AbstractConnectionPipelineIntegrationTests;
|
||||
import org.springframework.data.redis.connection.DefaultStringRedisConnection;
|
||||
import org.springframework.data.redis.connection.DefaultStringTuple;
|
||||
|
||||
@@ -1,14 +1,17 @@
|
||||
package org.springframework.data.redis.connection.lettuce;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.data.redis.connection.RedisPipelineException;
|
||||
import org.springframework.test.annotation.IfProfileValue;
|
||||
|
||||
/**
|
||||
* Integration test of {@link LettuceConnection} transactions within a pipeline
|
||||
@@ -30,8 +33,42 @@ public class LettuceConnectionPipelineTxIntegrationTests extends
|
||||
connection.set("dbparam", "foo");
|
||||
assertNull(connection.dbSize());
|
||||
List<Object> results = getResults();
|
||||
assertEquals(1, results.size());
|
||||
assertTrue((Long) results.get(0) > 0);
|
||||
assertEquals(3, results.size());
|
||||
assertTrue((Long) results.get(2) > 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInfo() throws Exception {
|
||||
assertNull(connection.info());
|
||||
List<Object> results = getResults();
|
||||
assertEquals(2, results.size());
|
||||
Properties info = LettuceUtils.info((String) results.get(1));
|
||||
assertTrue("at least 5 settings should be present", info.size() >= 5);
|
||||
String version = info.getProperty("redis_version");
|
||||
assertNotNull(version);
|
||||
}
|
||||
|
||||
@Test(expected=RedisPipelineException.class)
|
||||
@IfProfileValue(name = "redisVersion", value = "2.6")
|
||||
public void testRestoreBadData() {
|
||||
// Use something other than dump-specific serialization
|
||||
connection.restore("testing".getBytes(), 0, "foo".getBytes());
|
||||
getResults();
|
||||
}
|
||||
|
||||
@Test
|
||||
@IfProfileValue(name = "redisVersion", value = "2.6")
|
||||
public void testRestoreExistingKey() {
|
||||
connection.set("testing", "12");
|
||||
connection.dump("testing".getBytes());
|
||||
List<Object> results = getResults();
|
||||
initConnection();
|
||||
connection.restore("testing".getBytes(), 0, (byte[]) results.get(2));
|
||||
try {
|
||||
getResults();
|
||||
fail("Expected RedisPipelineException restoring existing key");
|
||||
}catch(RedisPipelineException e) {
|
||||
}
|
||||
}
|
||||
|
||||
protected void initConnection() {
|
||||
@@ -41,15 +78,7 @@ public class LettuceConnectionPipelineTxIntegrationTests extends
|
||||
|
||||
protected List<Object> getResults() {
|
||||
assertNull(connection.exec());
|
||||
List<Object> results = new ArrayList<Object>();
|
||||
List<Object> pipelinedResults = connection.closePipeline();
|
||||
// filter out the return value of exec
|
||||
for (Object result : pipelinedResults) {
|
||||
if (!"OK".equals(result) && !("QUEUED").equals(result)) {
|
||||
results.add(result);
|
||||
}
|
||||
}
|
||||
return results;
|
||||
return connection.closePipeline();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,15 +16,19 @@
|
||||
package org.springframework.data.redis.connection.lettuce;
|
||||
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.test.annotation.IfProfileValue;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
import com.lambdaworks.redis.RedisException;
|
||||
|
||||
/**
|
||||
* Integration test of {@link LettuceConnection} functionality within a
|
||||
* transaction
|
||||
@@ -93,6 +97,27 @@ public class LettuceConnectionTransactionIntegrationTests extends
|
||||
assertNull(getResults());
|
||||
}
|
||||
|
||||
@Test
|
||||
@IfProfileValue(name = "redisVersion", value = "2.6")
|
||||
public void testRestoreBadData() {
|
||||
// Use something other than dump-specific serialization
|
||||
connection.restore("testing".getBytes(), 0, "foo".getBytes());
|
||||
List<Object> results = getResults();
|
||||
assertTrue(results.get(0) instanceof RedisException);
|
||||
}
|
||||
|
||||
@Test
|
||||
@IfProfileValue(name = "redisVersion", value = "2.6")
|
||||
public void testRestoreExistingKey() {
|
||||
connection.set("testing", "12");
|
||||
connection.dump("testing".getBytes());
|
||||
List<Object> results = getResults();
|
||||
initConnection();
|
||||
connection.restore("testing".getBytes(), 0, (byte[]) results.get(1));
|
||||
List<Object> restoreResults = getResults();
|
||||
assertTrue(restoreResults.get(0) instanceof RedisException);
|
||||
}
|
||||
|
||||
protected void initConnection() {
|
||||
connection.multi();
|
||||
}
|
||||
|
||||
@@ -29,8 +29,7 @@ import org.springframework.test.annotation.IfProfileValue;
|
||||
* @author Jennifer Hickey
|
||||
*
|
||||
*/
|
||||
public class SrpConnectionTransactionIntegrationTests extends
|
||||
SrpConnectionPipelineIntegrationTests {
|
||||
public class SrpConnectionTransactionIntegrationTests extends SrpConnectionPipelineIntegrationTests {
|
||||
|
||||
@Ignore
|
||||
public void testMultiDiscard() {
|
||||
@@ -87,7 +86,7 @@ public class SrpConnectionTransactionIntegrationTests extends
|
||||
}
|
||||
|
||||
@Test
|
||||
@IfProfileValue(name = "redisVersion", values = {"2.4", "2.6"})
|
||||
@IfProfileValue(name = "redisVersion", values = { "2.4", "2.6" })
|
||||
public void testGetRangeSetRange() {
|
||||
connection.set("rangekey", "supercalifrag");
|
||||
actual.add(connection.getRange("rangekey", 0l, 2l));
|
||||
@@ -96,6 +95,22 @@ public class SrpConnectionTransactionIntegrationTests extends
|
||||
verifyResults(Arrays.asList(new Object[] { "sup", 13l, "suckrcalifrag" }), actual);
|
||||
}
|
||||
|
||||
@Ignore("https://github.com/spullara/redis-protocol/issues/24")
|
||||
@Test
|
||||
@IfProfileValue(name = "redisVersion", value = "2.6")
|
||||
public void testRestoreBadData() {
|
||||
// SRP issue exec does not report individual ErrorReplys in a MultiBulkReply
|
||||
// as Exceptions
|
||||
}
|
||||
|
||||
@Ignore("https://github.com/spullara/redis-protocol/issues/24")
|
||||
@Test
|
||||
@IfProfileValue(name = "redisVersion", value = "2.6")
|
||||
public void testRestoreExistingKey() {
|
||||
// SRP issue exec does not report individual ErrorReplys in a MultiBulkReply
|
||||
// as Exceptions
|
||||
}
|
||||
|
||||
protected void initConnection() {
|
||||
connection.multi();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user