/*
* Copyright 2016-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.connection.lettuce;
import static org.hamcrest.collection.IsIterableContainingInOrder.*;
import static org.hamcrest.core.Is.*;
import static org.hamcrest.core.IsEqual.*;
import static org.hamcrest.core.IsNull.*;
import static org.junit.Assert.*;
import static org.junit.Assume.assumeThat;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.junit.Test;
import org.springframework.data.redis.connection.ReactiveRedisConnection.BooleanResponse;
import org.springframework.data.redis.connection.ReactiveRedisConnection.ByteBufferResponse;
import org.springframework.data.redis.connection.ReactiveRedisConnection.KeyCommand;
import org.springframework.data.redis.connection.ReactiveRedisConnection.MultiValueResponse;
import org.springframework.data.redis.connection.ReactiveStringCommands.SetCommand;
import org.springframework.data.redis.connection.RedisStringCommands.BitOperation;
import org.springframework.data.redis.core.types.Expiration;
import org.springframework.data.redis.test.util.LettuceRedisClientProvider;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.test.TestSubscriber;
/**
* @author Christoph Strobl
*/
public class LettuceReactiveStringCommandsTests extends LettuceReactiveCommandsTestsBase {
@Test // DATAREDIS-525
public void getSetShouldReturnPreviousValueCorrectly() {
nativeCommands.set(KEY_1, VALUE_1);
Mono<ByteBuffer> result = connection.stringCommands().getSet(KEY_1_BBUFFER, VALUE_2_BBUFFER);
assertThat(result.block(), is(equalTo(VALUE_1_BBUFFER)));
assertThat(nativeCommands.get(KEY_1), is(equalTo(VALUE_2)));
}
@Test // DATAREDIS-525
public void getSetShouldReturnPreviousValueCorrectlyWhenNoExists() {
Mono<ByteBuffer> result = connection.stringCommands().getSet(KEY_1_BBUFFER, VALUE_2_BBUFFER);
ByteBuffer value = result.block();
assertThat(value, is(notNullValue()));
assertThat(value, is(equalTo(ByteBuffer.allocate(0))));
assertThat(nativeCommands.get(KEY_1), is(equalTo(VALUE_2)));
}
@Test // DATAREDIS-525
public void setShouldAddValueCorrectly() {
Mono<Boolean> result = connection.stringCommands().set(KEY_1_BBUFFER, VALUE_1_BBUFFER);
assertThat(result.block(), is(true));
assertThat(nativeCommands.get(KEY_1), is(equalTo(VALUE_1)));
}
@Test // DATAREDIS-525
public void setShouldAddValuesCorrectly() {
Flux<BooleanResponse<SetCommand>> result = connection.stringCommands()
.set(Flux.fromIterable(Arrays.asList(SetCommand.set(KEY_1_BBUFFER).value(VALUE_1_BBUFFER),
SetCommand.set(KEY_2_BBUFFER).value(VALUE_2_BBUFFER))));
TestSubscriber<BooleanResponse<SetCommand>> subscriber = TestSubscriber.create();
result.subscribe(subscriber);
subscriber.await();
subscriber.assertValueCount(2);
assertThat(nativeCommands.get(KEY_1), is(equalTo(VALUE_1)));
assertThat(nativeCommands.get(KEY_2), is(equalTo(VALUE_2)));
}
@Test // DATAREDIS-525
public void getShouldRetriveValueCorrectly() {
nativeCommands.set(KEY_1, VALUE_1);
Mono<ByteBuffer> result = connection.stringCommands().get(KEY_1_BBUFFER);
assertThat(result.block(), is(equalTo(VALUE_1_BBUFFER)));
}
@Test // DATAREDIS-525
public void getShouldRetriveNullValueCorrectly() {
Mono<ByteBuffer> result = connection.stringCommands().get(KEY_1_BBUFFER);
assertThat(result.block(), is(equalTo(ByteBuffer.allocate(0))));
}
@Test // DATAREDIS-525
public void getShouldRetriveValuesCorrectly() {
nativeCommands.set(KEY_1, VALUE_1);
nativeCommands.set(KEY_2, VALUE_2);
Flux<ByteBufferResponse<KeyCommand>> result = connection.stringCommands()
.get(Flux.fromStream(Arrays.asList(new KeyCommand(KEY_1_BBUFFER), new KeyCommand(KEY_2_BBUFFER)).stream()));
TestSubscriber<ByteBufferResponse<KeyCommand>> subscriber = TestSubscriber.create();
result.subscribe(subscriber);
subscriber.await();
subscriber.assertValueCount(2);
}
@Test // DATAREDIS-525
public void getShouldRetriveValuesWithNullCorrectly() {
nativeCommands.set(KEY_1, VALUE_1);
nativeCommands.set(KEY_3, VALUE_3);
Flux<ByteBufferResponse<KeyCommand>> result = connection.stringCommands().get(Flux.fromStream(Arrays
.asList(new KeyCommand(KEY_1_BBUFFER), new KeyCommand(KEY_2_BBUFFER), new KeyCommand(KEY_3_BBUFFER)).stream()));
TestSubscriber<ByteBufferResponse<KeyCommand>> subscriber = TestSubscriber.create();
result.subscribe(subscriber);
subscriber.await();
subscriber.assertValueCount(3);
}
@Test // DATAREDIS-525
public void mGetShouldRetriveValueCorrectly() {
nativeCommands.set(KEY_1, VALUE_1);
nativeCommands.set(KEY_2, VALUE_2);
Mono<List<ByteBuffer>> result = connection.stringCommands().mGet(Arrays.asList(KEY_1_BBUFFER, KEY_2_BBUFFER));
assertThat(result.block(), contains(VALUE_1_BBUFFER, VALUE_2_BBUFFER));
}
@Test // DATAREDIS-525
public void mGetShouldRetriveNullValueCorrectly() {
nativeCommands.set(KEY_1, VALUE_1);
nativeCommands.set(KEY_3, VALUE_3);
Mono<List<ByteBuffer>> result = connection.stringCommands()
.mGet(Arrays.asList(KEY_1_BBUFFER, KEY_2_BBUFFER, KEY_3_BBUFFER));
assertThat(result.block(), contains(VALUE_1_BBUFFER, ByteBuffer.allocate(0), VALUE_3_BBUFFER));
}
@Test // DATAREDIS-525
public void mGetShouldRetriveValuesCorrectly() {
nativeCommands.set(KEY_1, VALUE_1);
nativeCommands.set(KEY_2, VALUE_2);
Flux<List<ByteBuffer>> result = connection.stringCommands()
.mGet(
Flux.fromIterable(Arrays.asList(Arrays.asList(KEY_1_BBUFFER, KEY_2_BBUFFER), Arrays.asList(KEY_2_BBUFFER))))
.map(MultiValueResponse::getOutput);
TestSubscriber<List<ByteBuffer>> subscriber = TestSubscriber.create();
result.subscribe(subscriber);
subscriber.await();
subscriber.assertValueCount(2);
subscriber.assertContainValues(
new HashSet<>(Arrays.asList(Arrays.asList(VALUE_1_BBUFFER, VALUE_2_BBUFFER), Arrays.asList(VALUE_2_BBUFFER))));
}
@Test // DATAREDIS-525
public void setNXshouldOnlySetValueWhenNotPresent() {
assertThat(connection.stringCommands().setNX(KEY_1_BBUFFER, VALUE_1_BBUFFER).block(), is(true));
}
@Test // DATAREDIS-525
public void setNXshouldNotSetValueWhenAlreadyPresent() {
nativeCommands.setnx(KEY_1, VALUE_1);
assertThat(connection.stringCommands().setNX(KEY_1_BBUFFER, VALUE_2_BBUFFER).block(), is(false));
}
@Test // DATAREDIS-525
public void setEXshouldSetKeyAndExpirationTime() {
connection.stringCommands().setEX(KEY_1_BBUFFER, VALUE_1_BBUFFER, Expiration.seconds(3)).block();
assertThat(nativeCommands.ttl(KEY_1) > 1, is(true));
}
@Test // DATAREDIS-525
public void pSetEXshouldSetKeyAndExpirationTime() {
connection.stringCommands().pSetEX(KEY_1_BBUFFER, VALUE_1_BBUFFER, Expiration.milliseconds(600)).block();
assertThat(nativeCommands.pttl(KEY_1) > 1, is(true));
}
@Test // DATAREDIS-525
public void mSetShouldAddMultipleKeyValueParis() {
Map<ByteBuffer, ByteBuffer> map = new LinkedHashMap<>();
map.put(KEY_1_BBUFFER, VALUE_1_BBUFFER);
map.put(KEY_2_BBUFFER, VALUE_2_BBUFFER);
connection.stringCommands().mSet(map).block();
assertThat(nativeCommands.get(KEY_1), is(equalTo(VALUE_1)));
assertThat(nativeCommands.get(KEY_2), is(equalTo(VALUE_2)));
}
@Test // DATAREDIS-525
public void mSetNXShouldAddMultipleKeyValueParis() {
assumeThat(clientProvider instanceof LettuceRedisClientProvider, is(true));
Map<ByteBuffer, ByteBuffer> map = new LinkedHashMap<>();
map.put(KEY_1_BBUFFER, VALUE_1_BBUFFER);
map.put(KEY_2_BBUFFER, VALUE_2_BBUFFER);
connection.stringCommands().mSetNX(map).block();
assertThat(nativeCommands.get(KEY_1), is(equalTo(VALUE_1)));
assertThat(nativeCommands.get(KEY_2), is(equalTo(VALUE_2)));
}
@Test // DATAREDIS-525
public void mSetNXShouldNotAddMultipleKeyValueParisWhenAlreadyExit() {
assumeThat(clientProvider instanceof LettuceRedisClientProvider, is(true));
nativeCommands.set(KEY_2, VALUE_2);
Map<ByteBuffer, ByteBuffer> map = new LinkedHashMap<>();
map.put(KEY_1_BBUFFER, VALUE_1_BBUFFER);
map.put(KEY_2_BBUFFER, VALUE_2_BBUFFER);
assertThat(connection.stringCommands().mSetNX(map).block(), is(false));
assertThat(nativeCommands.exists(KEY_1), is(0L));
assertThat(nativeCommands.get(KEY_2), is(equalTo(VALUE_2)));
}
@Test // DATAREDIS-525
public void appendShouldDoItsThing() {
assertThat(connection.stringCommands().append(KEY_1_BBUFFER, VALUE_1_BBUFFER).block(), is(7L));
assertThat(connection.stringCommands().append(KEY_1_BBUFFER, VALUE_2_BBUFFER).block(), is(14L));
}
@Test // DATAREDIS-525
public void getRangeShouldReturnSubstringCorrectly() {
nativeCommands.set(KEY_1, VALUE_1);
assertThat(connection.stringCommands().getRange(KEY_1_BBUFFER, 2, 3).block(),
is(equalTo(ByteBuffer.wrap("lu".getBytes()))));
}
@Test // DATAREDIS-525
public void setRangeShouldReturnNewStringLengthCorrectly() {
nativeCommands.set(KEY_1, VALUE_1);
assertThat(connection.stringCommands().setRange(KEY_1_BBUFFER, VALUE_2_BBUFFER, 3).block(), is(10L));
}
@Test // DATAREDIS-525
public void getBitShouldReturnValueCorrectly() {
nativeCommands.set(KEY_1, VALUE_1);
assertThat(connection.stringCommands().getBit(KEY_1_BBUFFER, 1).block(), is(true));
assertThat(connection.stringCommands().getBit(KEY_1_BBUFFER, 7).block(), is(false));
}
@Test // DATAREDIS-525
public void setBitShouldReturnValueCorrectly() {
nativeCommands.set(KEY_1, VALUE_1);
assertThat(connection.stringCommands().setBit(KEY_1_BBUFFER, 1, false).block(), is(true));
assertThat(nativeCommands.getbit(KEY_1, 1), is(0L));
}
@Test // DATAREDIS-525
public void bitCountShouldReturnValueCorrectly() {
nativeCommands.set(KEY_1, VALUE_1);
assertThat(connection.stringCommands().bitCount(KEY_1_BBUFFER).block(), is(28L));
}
@Test // DATAREDIS-525
public void bitCountShouldCountInRangeCorrectly() {
nativeCommands.set(KEY_1, VALUE_1);
assertThat(connection.stringCommands().bitCount(KEY_1_BBUFFER, 2, 4).block(), is(13L));
}
@Test // DATAREDIS-525
public void bitOpAndShouldWorkAsExpected() {
assumeThat(clientProvider instanceof LettuceRedisClientProvider, is(true));
nativeCommands.set(KEY_1, VALUE_1);
nativeCommands.set(KEY_2, VALUE_2);
assertThat(connection.stringCommands()
.bitOp(Arrays.asList(KEY_1_BBUFFER, KEY_2_BBUFFER), BitOperation.AND, KEY_3_BBUFFER).block(), is(7L));
assertThat(nativeCommands.get(KEY_3), is(equalTo("value-0")));
}
@Test // DATAREDIS-525
public void bitOpOrShouldWorkAsExpected() {
assumeThat(clientProvider instanceof LettuceRedisClientProvider, is(true));
nativeCommands.set(KEY_1, VALUE_1);
nativeCommands.set(KEY_2, VALUE_2);
assertThat(connection.stringCommands()
.bitOp(Arrays.asList(KEY_1_BBUFFER, KEY_2_BBUFFER), BitOperation.OR, KEY_3_BBUFFER).block(), is(7L));
assertThat(nativeCommands.get(KEY_3), is(equalTo(VALUE_3)));
}
@Test(expected = IllegalArgumentException.class) // DATAREDIS-525
public void bitNotShouldThrowExceptionWhenMoreThanOnSourceKey() {
assumeThat(clientProvider instanceof LettuceRedisClientProvider, is(true));
connection.stringCommands().bitOp(Arrays.asList(KEY_1_BBUFFER, KEY_2_BBUFFER), BitOperation.NOT, KEY_3_BBUFFER)
.block();
}
@Test // DATAREDIS-525
public void strLenShouldReturnValueCorrectly() {
nativeCommands.set(KEY_1, VALUE_1);
assertThat(connection.stringCommands().strLen(KEY_1_BBUFFER).block(), is(7L));
}
}