/*
* Copyright 2017 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.core;
import static org.assertj.core.api.Assertions.*;
import static org.junit.Assume.*;
import reactor.test.StepVerifier;
import java.nio.ByteBuffer;
import java.time.Duration;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import org.springframework.data.redis.ConnectionFactoryTracker;
import org.springframework.data.redis.ObjectFactory;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
/**
* Integration tests for {@link DefaultReactiveValueOperations}.
*
* @author Mark Paluch
* @author Christoph Strobl
*/
@RunWith(Parameterized.class)
@SuppressWarnings("unchecked")
public class DefaultReactiveValueOperationsIntegrationTests<K, V> {
private final ReactiveRedisTemplate<K, V> redisTemplate;
private final ReactiveValueOperations<K, V> valueOperations;
private final ObjectFactory<K> keyFactory;
private final ObjectFactory<V> valueFactory;
private final RedisSerializer serializer;
@Parameters(name = "{4}")
public static Collection<Object[]> testParams() {
return ReactiveOperationsTestParams.testParams();
}
@AfterClass
public static void cleanUp() {
ConnectionFactoryTracker.cleanUp();
}
/**
* @param redisTemplate
* @param keyFactory
* @param valueFactory
* @param label parameterized test label, no further use besides that.
*/
public DefaultReactiveValueOperationsIntegrationTests(ReactiveRedisTemplate<K, V> redisTemplate,
ObjectFactory<K> keyFactory, ObjectFactory<V> valueFactory, RedisSerializer serializer, String label) {
this.redisTemplate = redisTemplate;
this.valueOperations = redisTemplate.opsForValue();
this.keyFactory = keyFactory;
this.valueFactory = valueFactory;
this.serializer = serializer;
ConnectionFactoryTracker.add(redisTemplate.getConnectionFactory());
}
@Before
public void before() {
RedisConnectionFactory connectionFactory = (RedisConnectionFactory) redisTemplate.getConnectionFactory();
RedisConnection connection = connectionFactory.getConnection();
connection.flushAll();
connection.close();
}
@Test // DATAREDIS-602
public void set() {
K key = keyFactory.instance();
V value = valueFactory.instance();
StepVerifier.create(valueOperations.set(key, value)).expectNext(true).verifyComplete();
StepVerifier.create(valueOperations.get(key)).expectNext(value).verifyComplete();
}
@Test // DATAREDIS-602
public void setWithExpiry() {
K key = keyFactory.instance();
V value = valueFactory.instance();
StepVerifier.create(valueOperations.set(key, value, Duration.ofSeconds(10))).expectNext(true).expectComplete()
.verify();
StepVerifier.create(valueOperations.get(key)).expectNext(value).verifyComplete();
StepVerifier.create(redisTemplate.getExpire(key)) //
.consumeNextWith(actual -> assertThat(actual).isGreaterThan(Duration.ofSeconds(8))) //
.expectComplete() //
.verify();
}
@Test // DATAREDIS-602
public void setIfAbsent() {
K key = keyFactory.instance();
V value = valueFactory.instance();
StepVerifier.create(valueOperations.setIfAbsent(key, value)).expectNext(true).verifyComplete();
StepVerifier.create(valueOperations.setIfAbsent(key, value)).verifyComplete();
}
@Test // DATAREDIS-602
public void setIfPresent() {
K key = keyFactory.instance();
V value = valueFactory.instance();
V laterValue = valueFactory.instance();
StepVerifier.create(valueOperations.setIfPresent(key, value)).verifyComplete();
StepVerifier.create(valueOperations.set(key, value)).expectNext(true).verifyComplete();
StepVerifier.create(valueOperations.setIfPresent(key, laterValue)).expectNext(true).verifyComplete();
StepVerifier.create(valueOperations.get(key)).expectNext(laterValue).verifyComplete();
}
@Test // DATAREDIS-602
public void multiSet() {
K key1 = keyFactory.instance();
K key2 = keyFactory.instance();
V value1 = valueFactory.instance();
V value2 = valueFactory.instance();
Map<K, V> map = new LinkedHashMap<K, V>();
map.put(key1, value1);
map.put(key2, value2);
StepVerifier.create(valueOperations.multiSet(map)).expectNext(true).verifyComplete();
StepVerifier.create(valueOperations.get(key1)).expectNext(value1).verifyComplete();
StepVerifier.create(valueOperations.get(key2)).expectNext(value2).verifyComplete();
}
@Test // DATAREDIS-602
public void multiSetIfAbsent() {
K key1 = keyFactory.instance();
K key2 = keyFactory.instance();
V value1 = valueFactory.instance();
V value2 = valueFactory.instance();
Map<K, V> map = new LinkedHashMap<K, V>();
map.put(key1, value1);
StepVerifier.create(valueOperations.multiSetIfAbsent(map)).expectNext(true).verifyComplete();
map.put(key2, value2);
StepVerifier.create(valueOperations.multiSetIfAbsent(map)).expectNext(false).verifyComplete();
StepVerifier.create(valueOperations.get(key1)).expectNext(value1).verifyComplete();
StepVerifier.create(valueOperations.get(key2)).expectNextCount(0).verifyComplete();
}
@Test // DATAREDIS-602
public void get() {
K key = keyFactory.instance();
V value = valueFactory.instance();
StepVerifier.create(valueOperations.set(key, value)).expectNext(true).verifyComplete();
StepVerifier.create(valueOperations.get(key)).expectNext(value).verifyComplete();
}
@Test // DATAREDIS-602
public void getAndSet() {
K key = keyFactory.instance();
V value = valueFactory.instance();
V nextValue = valueFactory.instance();
StepVerifier.create(valueOperations.set(key, value)).expectNext(true).verifyComplete();
StepVerifier.create(valueOperations.getAndSet(key, nextValue)).expectNext(value).verifyComplete();
StepVerifier.create(valueOperations.get(key)).expectNext(nextValue).verifyComplete();
}
@Test // DATAREDIS-602
public void multiGet() {
K key1 = keyFactory.instance();
K key2 = keyFactory.instance();
K absent = keyFactory.instance();
V value1 = valueFactory.instance();
V value2 = valueFactory.instance();
V absentValue = null;
if (serializer instanceof StringRedisSerializer) {
absentValue = (V) "";
}
if (value1 instanceof ByteBuffer) {
absentValue = (V) ByteBuffer.wrap(new byte[0]);
}
Map<K, V> map = new LinkedHashMap<K, V>();
map.put(key1, value1);
map.put(key2, value2);
StepVerifier.create(valueOperations.multiSet(map)).expectNext(true).verifyComplete();
StepVerifier.create(valueOperations.multiGet(Arrays.asList(key2, key1, absent)))
.expectNext(Arrays.asList(value2, value1, absentValue)).verifyComplete();
}
@Test // DATAREDIS-602
public void append() {
assumeTrue(serializer instanceof StringRedisSerializer);
K key = keyFactory.instance();
V value = valueFactory.instance();
StepVerifier.create(valueOperations.set(key, value)).expectNext(true).verifyComplete();
StepVerifier.create(valueOperations.append(key, "foo")).expectNextCount(1).verifyComplete();
StepVerifier.create(valueOperations.get(key)).expectNext((V) (value + "foo")).verifyComplete();
}
@Test // DATAREDIS-602
public void getRange() {
assumeTrue(serializer instanceof StringRedisSerializer);
K key = keyFactory.instance();
V value = valueFactory.instance();
StepVerifier.create(valueOperations.set(key, value)).expectNext(true).verifyComplete();
String substring = value.toString().substring(1, 5);
StepVerifier.create(valueOperations.get(key, 1, 4)).expectNext(substring).verifyComplete();
}
@Test // DATAREDIS-602
public void setRange() {
assumeTrue(serializer instanceof StringRedisSerializer);
K key = keyFactory.instance();
V value = valueFactory.instance();
StepVerifier.create(valueOperations.set(key, value)).expectNext(true).verifyComplete();
StepVerifier.create(valueOperations.set(key, (V) "boo", 2)).expectNextCount(1).verifyComplete();
StepVerifier.create(valueOperations.get(key)).consumeNextWith(actual -> {
String string = (String) actual;
String prefix = value.toString().substring(0, 2);
assertThat(string).startsWith(prefix + "boo");
}).verifyComplete();
}
@Test // DATAREDIS-602
public void size() {
assumeTrue(serializer instanceof StringRedisSerializer);
K key = keyFactory.instance();
V value = valueFactory.instance();
StepVerifier.create(valueOperations.set(key, value)).expectNext(true).verifyComplete();
StepVerifier.create(valueOperations.size(key)).expectNext((long) value.toString().length()).expectComplete()
.verify();
}
@Test // DATAREDIS-602
public void setBit() {
K key = keyFactory.instance();
StepVerifier.create(valueOperations.setBit(key, 0, true)).expectNext(false).expectComplete();
StepVerifier.create(valueOperations.setBit(key, 2, true)).expectNext(false).expectComplete();
}
@Test // DATAREDIS-602
public void getBit() {
K key = keyFactory.instance();
StepVerifier.create(valueOperations.setBit(key, 0, true)).expectNext(false).expectComplete();
StepVerifier.create(valueOperations.getBit(key, 0)).expectNext(true).expectComplete();
StepVerifier.create(valueOperations.getBit(key, 1)).expectNext(false).expectComplete();
}
@Test // DATAREDIS-602
public void delete() {
K key = keyFactory.instance();
V value = valueFactory.instance();
StepVerifier.create(valueOperations.set(key, value)).expectNext(true).verifyComplete();
StepVerifier.create(valueOperations.delete(key)).expectNext(true).verifyComplete();
StepVerifier.create(valueOperations.size(key)).expectNext(0L).verifyComplete();
}
}