/*
* Copyright 2011-2016 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 com.lambdaworks.redis.protocol;
import static com.lambdaworks.redis.protocol.RedisStateMachine.State;
import static org.assertj.core.api.Assertions.assertThat;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.List;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.config.LoggerConfig;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import com.lambdaworks.redis.RedisException;
import com.lambdaworks.redis.codec.RedisCodec;
import com.lambdaworks.redis.codec.Utf8StringCodec;
import com.lambdaworks.redis.output.*;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
/**
* @author Will Glozer
* @author Mark Paluch
*/
public class StateMachineTest {
protected RedisCodec<String, String> codec = new Utf8StringCodec();
protected Charset charset = Charset.forName("UTF-8");
protected CommandOutput<String, String, String> output;
protected RedisStateMachine<String, String> rsm;
@BeforeClass
public static void beforeClass() {
LoggerContext ctx = (LoggerContext) LogManager.getContext();
Configuration config = ctx.getConfiguration();
LoggerConfig loggerConfig = config.getLoggerConfig(RedisStateMachine.class.getName());
loggerConfig.setLevel(Level.ALL);
}
@AfterClass
public static void afterClass() {
LoggerContext ctx = (LoggerContext) LogManager.getContext();
Configuration config = ctx.getConfiguration();
LoggerConfig loggerConfig = config.getLoggerConfig(RedisStateMachine.class.getName());
loggerConfig.setLevel(null);
}
@Before
public final void createStateMachine() throws Exception {
output = new StatusOutput<>(codec);
rsm = new RedisStateMachine<>();
}
@Test
public void single() throws Exception {
assertThat(rsm.decode(buffer("+OK\r\n"), output)).isTrue();
assertThat(output.get()).isEqualTo("OK");
}
@Test
public void error() throws Exception {
assertThat(rsm.decode(buffer("-ERR\r\n"), output)).isTrue();
assertThat(output.getError()).isEqualTo("ERR");
}
@Test
public void errorWithoutLineBreak() throws Exception {
assertThat(rsm.decode(buffer("-ERR"), output)).isFalse();
assertThat(rsm.decode(buffer("\r\n"), output)).isTrue();
assertThat(output.getError()).isEqualTo("");
}
@Test
public void integer() throws Exception {
CommandOutput<String, String, Long> output = new IntegerOutput<>(codec);
assertThat(rsm.decode(buffer(":1\r\n"), output)).isTrue();
assertThat((long) output.get()).isEqualTo(1);
}
@Test
public void bulk() throws Exception {
CommandOutput<String, String, String> output = new ValueOutput<>(codec);
assertThat(rsm.decode(buffer("$-1\r\n"), output)).isTrue();
assertThat(output.get()).isNull();
assertThat(rsm.decode(buffer("$3\r\nfoo\r\n"), output)).isTrue();
assertThat(output.get()).isEqualTo("foo");
}
@Test
public void multi() throws Exception {
CommandOutput<String, String, List<String>> output = new ValueListOutput<>(codec);
ByteBuf buffer = buffer("*2\r\n$-1\r\n$2\r\nok\r\n");
assertThat(rsm.decode(buffer, output)).isTrue();
assertThat(output.get()).isEqualTo(Arrays.asList(null, "ok"));
}
@Test
public void multiEmptyArray1() throws Exception {
CommandOutput<String, String, List<Object>> output = new NestedMultiOutput<>(codec);
ByteBuf buffer = buffer("*2\r\n$3\r\nABC\r\n*0\r\n");
assertThat(rsm.decode(buffer, output)).isTrue();
assertThat(output.get().get(0)).isEqualTo("ABC");
assertThat(output.get().get(1)).isEqualTo(Arrays.asList());
assertThat(output.get().size()).isEqualTo(2);
}
@Test
public void multiEmptyArray2() throws Exception {
CommandOutput<String, String, List<Object>> output = new NestedMultiOutput<>(codec);
ByteBuf buffer = buffer("*2\r\n*0\r\n$3\r\nABC\r\n");
assertThat(rsm.decode(buffer, output)).isTrue();
assertThat(output.get().get(0)).isEqualTo(Arrays.asList());
assertThat(output.get().get(1)).isEqualTo("ABC");
assertThat(output.get().size()).isEqualTo(2);
}
@Test
public void multiEmptyArray3() throws Exception {
CommandOutput<String, String, List<Object>> output = new NestedMultiOutput<>(codec);
ByteBuf buffer = buffer("*2\r\n*2\r\n$2\r\nAB\r\n$2\r\nXY\r\n*0\r\n");
assertThat(rsm.decode(buffer, output)).isTrue();
assertThat(output.get().get(0)).isEqualTo(Arrays.asList("AB", "XY"));
assertThat(output.get().get(1)).isEqualTo(Arrays.asList());
assertThat(output.get().size()).isEqualTo(2);
}
@Test
public void partialFirstLine() throws Exception {
assertThat(rsm.decode(buffer("+"), output)).isFalse();
assertThat(rsm.decode(buffer("-"), output)).isFalse();
assertThat(rsm.decode(buffer(":"), output)).isFalse();
assertThat(rsm.decode(buffer("$"), output)).isFalse();
assertThat(rsm.decode(buffer("*"), output)).isFalse();
}
@Test(expected = RedisException.class)
public void invalidReplyType() throws Exception {
rsm.decode(buffer("="), output);
}
@Test
public void sillyTestsForEmmaCoverage() throws Exception {
assertThat(State.Type.valueOf("SINGLE")).isEqualTo(State.Type.SINGLE);
}
protected ByteBuf buffer(String content) {
return Unpooled.copiedBuffer(content, charset);
}
}