/*
* 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.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
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.RawObjectFactory;
import org.springframework.data.redis.SettingsUtils;
import org.springframework.data.redis.StringObjectFactory;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettuceTestClientResources;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;
/**
* Integration tests for {@link DefaultReactiveHashOperations}.
*
* @author Mark Paluch
* @author Christoph Strobl
*/
@RunWith(Parameterized.class)
@SuppressWarnings("unchecked")
public class DefaultReactiveHashOperationsIntegrationTests<K, HK, HV> {
private final ReactiveRedisTemplate<K, ?> redisTemplate;
private final ReactiveHashOperations<K, HK, HV> hashOperations;
private final ObjectFactory<K> keyFactory;
private final ObjectFactory<HK> hashKeyFactory;
private final ObjectFactory<HV> hashValueFactory;
@Parameters(name = "{4}")
public static Collection<Object[]> testParams() {
ObjectFactory<String> stringFactory = new StringObjectFactory();
ObjectFactory<byte[]> rawFactory = new RawObjectFactory();
LettuceConnectionFactory lettuceConnectionFactory = new LettuceConnectionFactory();
lettuceConnectionFactory.setClientResources(LettuceTestClientResources.getSharedClientResources());
lettuceConnectionFactory.setPort(SettingsUtils.getPort());
lettuceConnectionFactory.setHostName(SettingsUtils.getHost());
lettuceConnectionFactory.afterPropertiesSet();
RedisSerializationContext<String, String> serializationContext = RedisSerializationContext
.fromSerializer(new StringRedisSerializer());
ReactiveRedisTemplate<String, String> stringTemplate = new ReactiveRedisTemplate<>(lettuceConnectionFactory,
serializationContext);
ReactiveRedisTemplate<byte[], byte[]> rawTemplate = new ReactiveRedisTemplate(lettuceConnectionFactory,
RedisSerializationContext.raw());
return Arrays.asList(new Object[][] { { stringTemplate, stringFactory, stringFactory, stringFactory, "String" },
{ rawTemplate, rawFactory, rawFactory, rawFactory, "raw" } });
}
@AfterClass
public static void cleanUp() {
ConnectionFactoryTracker.cleanUp();
}
public DefaultReactiveHashOperationsIntegrationTests(ReactiveRedisTemplate<K, ?> redisTemplate,
ObjectFactory<K> keyFactory, ObjectFactory<HK> hashKeyFactory, ObjectFactory<HV> hashValueFactory,
String testName) {
this.redisTemplate = redisTemplate;
this.hashOperations = redisTemplate.opsForHash();
this.keyFactory = keyFactory;
this.hashKeyFactory = hashKeyFactory;
this.hashValueFactory = hashValueFactory;
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 remove() {
K key = keyFactory.instance();
HK hashkey1 = hashKeyFactory.instance();
HV hashvalue1 = hashValueFactory.instance();
HK hashkey2 = hashKeyFactory.instance();
HV hashvalue2 = hashValueFactory.instance();
putAll(key, hashkey1, hashvalue1, hashkey2, hashvalue2);
StepVerifier.create(hashOperations.remove(key, hashkey1, hashkey2)) //
.expectNext(2L) //
.verifyComplete();
}
@Test // DATAREDIS-602
public void hasKey() {
K key = keyFactory.instance();
HK hashkey = hashKeyFactory.instance();
HV hashvalue = hashValueFactory.instance();
StepVerifier.create(hashOperations.put(key, hashkey, hashvalue)) //
.expectNext(true) //
.verifyComplete();
StepVerifier.create(hashOperations.hasKey(key, hashkey)) //
.expectNext(true) //
.verifyComplete();
StepVerifier.create(hashOperations.hasKey(key, hashKeyFactory.instance())) //
.expectNext(false) //
.verifyComplete();
}
@Test // DATAREDIS-602
public void get() {
K key = keyFactory.instance();
HK hashkey = hashKeyFactory.instance();
HV hashvalue = hashValueFactory.instance();
StepVerifier.create(hashOperations.put(key, hashkey, hashvalue)) //
.expectNext(true) //
.verifyComplete();
StepVerifier.create(hashOperations.get(key, hashkey)) //
.expectNextCount(1) //
.verifyComplete();
}
@Test // DATAREDIS-602
public void multiGet() {
assumeTrue(hashKeyFactory instanceof StringObjectFactory && hashValueFactory instanceof StringObjectFactory);
K key = keyFactory.instance();
HK hashkey1 = hashKeyFactory.instance();
HV hashvalue1 = hashValueFactory.instance();
HK hashkey2 = hashKeyFactory.instance();
HV hashvalue2 = hashValueFactory.instance();
putAll(key, hashkey1, hashvalue1, hashkey2, hashvalue2);
StepVerifier.create(hashOperations.multiGet(key, Arrays.asList(hashkey1, hashkey2))) //
.consumeNextWith(actual -> {
assertThat(actual).hasSize(2).containsSequence(hashvalue1, hashvalue2);
}) //
.verifyComplete();
}
@Test // DATAREDIS-602
public void increment() {
assumeTrue(hashValueFactory instanceof StringObjectFactory);
K key = keyFactory.instance();
HK hashkey = hashKeyFactory.instance();
HV hashvalue = (HV) "1";
StepVerifier.create(hashOperations.put(key, hashkey, hashvalue)) //
.expectNext(true) //
.verifyComplete();
StepVerifier.create(hashOperations.increment(key, hashkey, 1L)) //
.expectNext(2L) //
.verifyComplete();
StepVerifier.create(hashOperations.get(key, hashkey)) //
.expectNext((HV) "2") //
.verifyComplete();
}
@Test // DATAREDIS-602
@SuppressWarnings("unchecked")
public void incrementDouble() {
assumeTrue(hashValueFactory instanceof StringObjectFactory);
K key = keyFactory.instance();
HK hashkey = hashKeyFactory.instance();
HV hashvalue = (HV) "1";
StepVerifier.create(hashOperations.put(key, hashkey, hashvalue)) //
.expectNext(true) //
.verifyComplete();
StepVerifier.create(hashOperations.increment(key, hashkey, 1.1d)) //
.expectNext(2.1d) //
.verifyComplete();
StepVerifier.create(hashOperations.get(key, hashkey)) //
.expectNext((HV) "2.1") //
.verifyComplete();
}
@Test // DATAREDIS-602
public void keys() {
assumeTrue(hashKeyFactory instanceof StringObjectFactory);
K key = keyFactory.instance();
HK hashkey1 = hashKeyFactory.instance();
HV hashvalue1 = hashValueFactory.instance();
HK hashkey2 = hashKeyFactory.instance();
HV hashvalue2 = hashValueFactory.instance();
putAll(key, hashkey1, hashvalue1, hashkey2, hashvalue2);
StepVerifier.create(hashOperations.keys(key).buffer(2)) //
.consumeNextWith(list -> assertThat(list).containsExactlyInAnyOrder(hashkey1, hashkey2)) //
.verifyComplete();
}
@Test // DATAREDIS-602
public void size() {
K key = keyFactory.instance();
HK hashkey1 = hashKeyFactory.instance();
HV hashvalue1 = hashValueFactory.instance();
HK hashkey2 = hashKeyFactory.instance();
HV hashvalue2 = hashValueFactory.instance();
putAll(key, hashkey1, hashvalue1, hashkey2, hashvalue2);
StepVerifier.create(hashOperations.size(key)) //
.expectNext(2L) //
.verifyComplete();
}
@Test // DATAREDIS-602
public void putAll() {
K key = keyFactory.instance();
HK hashkey1 = hashKeyFactory.instance();
HV hashvalue1 = hashValueFactory.instance();
HK hashkey2 = hashKeyFactory.instance();
HV hashvalue2 = hashValueFactory.instance();
putAll(key, hashkey1, hashvalue1, hashkey2, hashvalue2);
StepVerifier.create(hashOperations.hasKey(key, hashkey1)) //
.expectNext(true) //
.verifyComplete();
StepVerifier.create(hashOperations.hasKey(key, hashkey2)) //
.expectNext(true) //
.verifyComplete();
}
@Test // DATAREDIS-602
public void put() {
K key = keyFactory.instance();
HK hashkey = hashKeyFactory.instance();
HV hashvalue = hashValueFactory.instance();
StepVerifier.create(hashOperations.put(key, hashkey, hashvalue)) //
.expectNext(true) //
.verifyComplete();
}
@Test // DATAREDIS-602
public void putIfAbsent() {
K key = keyFactory.instance();
HK hashkey = hashKeyFactory.instance();
HV hashvalue = hashValueFactory.instance();
HV hashvalue2 = hashValueFactory.instance();
StepVerifier.create(hashOperations.putIfAbsent(key, hashkey, hashvalue)) //
.expectNext(true) //
.verifyComplete();
StepVerifier.create(hashOperations.putIfAbsent(key, hashkey, hashvalue2)) //
.expectNext(false) //
.verifyComplete();
}
@Test // DATAREDIS-602
public void values() {
assumeTrue(hashValueFactory instanceof StringObjectFactory);
K key = keyFactory.instance();
HK hashkey1 = hashKeyFactory.instance();
HV hashvalue1 = hashValueFactory.instance();
HK hashkey2 = hashKeyFactory.instance();
HV hashvalue2 = hashValueFactory.instance();
putAll(key, hashkey1, hashvalue1, hashkey2, hashvalue2);
StepVerifier.create(hashOperations.values(key)) //
.expectNextCount(2) //
.verifyComplete();
}
@Test // DATAREDIS-602
public void entries() {
assumeTrue(hashKeyFactory instanceof StringObjectFactory && hashValueFactory instanceof StringObjectFactory);
K key = keyFactory.instance();
HK hashkey1 = hashKeyFactory.instance();
HV hashvalue1 = hashValueFactory.instance();
HK hashkey2 = hashKeyFactory.instance();
HV hashvalue2 = hashValueFactory.instance();
putAll(key, hashkey1, hashvalue1, hashkey2, hashvalue2);
StepVerifier.create(hashOperations.entries(key).buffer(2)) //
.consumeNextWith(list -> {
Entry<HK, HV> entry1 = Collections.singletonMap(hashkey1, hashvalue1).entrySet().iterator().next();
Entry<HK, HV> entry2 = Collections.singletonMap(hashkey2, hashvalue2).entrySet().iterator().next();
assertThat(list).containsExactlyInAnyOrder(entry1, entry2);
}) //
.verifyComplete();
}
@Test // DATAREDIS-602
public void delete() {
K key = keyFactory.instance();
HK hashkey = hashKeyFactory.instance();
HV hashvalue = hashValueFactory.instance();
StepVerifier.create(hashOperations.put(key, hashkey, hashvalue)) //
.expectNext(true) //
.verifyComplete();
StepVerifier.create(hashOperations.delete(key)) //
.expectNext(true) //
.verifyComplete();
StepVerifier.create(hashOperations.size(key)) //
.expectNext(0L) //
.verifyComplete();
}
private void putAll(K key, HK hashkey1, HV hashvalue1, HK hashkey2, HV hashvalue2) {
Map<HK, HV> map = new HashMap<>();
map.put(hashkey1, hashvalue1);
map.put(hashkey2, hashvalue2);
StepVerifier.create(hashOperations.putAll(key, map)) //
.expectNext(true) //
.verifyComplete();
}
}