From 91675effe6942fc5e7e460f96639199f5b36b839 Mon Sep 17 00:00:00 2001 From: iskl Date: Mon, 16 Jan 2017 17:25:04 +0800 Subject: [PATCH] [ROCKETMQ-38] Polish unit tests for remoting module, closes apache/incubator-rocketmq#37 --- pom.xml | 6 + remoting/pom.xml | 5 + .../protocol/RemotingCommandTest.java | 220 ++++++++++++++++++ .../protocol/RemotingSerializableTest.java | 162 +++++++++++++ .../protocol/RocketMQSerializableTest.java | 151 ++++++++++++ 5 files changed, 544 insertions(+) create mode 100644 remoting/src/test/java/org/apache/rocketmq/remoting/protocol/RemotingCommandTest.java create mode 100644 remoting/src/test/java/org/apache/rocketmq/remoting/protocol/RemotingSerializableTest.java create mode 100644 remoting/src/test/java/org/apache/rocketmq/remoting/protocol/RocketMQSerializableTest.java diff --git a/pom.xml b/pom.xml index 6bdf8ffa..9484b0fe 100644 --- a/pom.xml +++ b/pom.xml @@ -459,6 +459,12 @@ 4.11 test + + org.assertj + assertj-core + 2.6.0 + test + org.slf4j slf4j-api diff --git a/remoting/pom.xml b/remoting/pom.xml index 5b983654..050be172 100644 --- a/remoting/pom.xml +++ b/remoting/pom.xml @@ -35,6 +35,11 @@ junit test + + org.assertj + assertj-core + test + com.alibaba fastjson diff --git a/remoting/src/test/java/org/apache/rocketmq/remoting/protocol/RemotingCommandTest.java b/remoting/src/test/java/org/apache/rocketmq/remoting/protocol/RemotingCommandTest.java new file mode 100644 index 00000000..0f5da6e1 --- /dev/null +++ b/remoting/src/test/java/org/apache/rocketmq/remoting/protocol/RemotingCommandTest.java @@ -0,0 +1,220 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.rocketmq.remoting.protocol; + +import java.nio.ByteBuffer; +import org.apache.rocketmq.remoting.CommandCustomHeader; +import org.apache.rocketmq.remoting.exception.RemotingCommandException; +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class RemotingCommandTest { + @Test + public void testMarkProtocolType_JSONProtocolType() { + int source = 261; + SerializeType type = SerializeType.JSON; + byte[] result = RemotingCommand.markProtocolType(source, type); + assertThat(result).isEqualTo(new byte[]{0, 0, 1, 5}); + } + + @Test + public void testMarkProtocolType_ROCKETMQProtocolType() { + int source = 16777215; + SerializeType type = SerializeType.ROCKETMQ; + byte[] result = RemotingCommand.markProtocolType(source, type); + assertThat(result).isEqualTo(new byte[]{1, -1, -1, -1}); + } + + @Test + public void testCreateRequestCommand_RegisterBroker() { + System.setProperty(RemotingCommand.REMOTING_VERSION_KEY, "2333"); + + int code = 103; //org.apache.rocketmq.common.protocol.RequestCode.REGISTER_BROKER + CommandCustomHeader header = new SampleCommandCustomHeader(); + RemotingCommand cmd = RemotingCommand.createRequestCommand(code, header); + assertThat(cmd.getCode()).isEqualTo(code); + assertThat(cmd.getVersion()).isEqualTo(2333); + assertThat(cmd.getFlag() & 0x01).isEqualTo(0); //flag bit 0: 0 presents request + } + + @Test + public void testCreateResponseCommand_SuccessWithHeader() { + System.setProperty(RemotingCommand.REMOTING_VERSION_KEY, "2333"); + + int code = RemotingSysResponseCode.SUCCESS; + String remark = "Sample remark"; + RemotingCommand cmd = RemotingCommand.createResponseCommand(code ,remark, SampleCommandCustomHeader.class); + assertThat(cmd.getCode()).isEqualTo(code); + assertThat(cmd.getVersion()).isEqualTo(2333); + assertThat(cmd.getRemark()).isEqualTo(remark); + assertThat(cmd.getFlag() & 0x01).isEqualTo(1); //flag bit 0: 1 presents response + } + + @Test + public void testCreateResponseCommand_SuccessWithoutHeader() { + System.setProperty(RemotingCommand.REMOTING_VERSION_KEY, "2333"); + + int code = RemotingSysResponseCode.SUCCESS; + String remark = "Sample remark"; + RemotingCommand cmd = RemotingCommand.createResponseCommand(code ,remark); + assertThat(cmd.getCode()).isEqualTo(code); + assertThat(cmd.getVersion()).isEqualTo(2333); + assertThat(cmd.getRemark()).isEqualTo(remark); + assertThat(cmd.getFlag() & 0x01).isEqualTo(1); //flag bit 0: 1 presents response + } + + @Test + public void testCreateResponseCommand_FailToCreateCommand() { + System.setProperty(RemotingCommand.REMOTING_VERSION_KEY, "2333"); + + int code = RemotingSysResponseCode.SUCCESS; + String remark = "Sample remark"; + RemotingCommand cmd = RemotingCommand.createResponseCommand(code ,remark, CommandCustomHeader.class); + assertThat(cmd).isNull(); + } + + @Test + public void testCreateResponseCommand_SystemError() { + System.setProperty(RemotingCommand.REMOTING_VERSION_KEY, "2333"); + + RemotingCommand cmd = RemotingCommand.createResponseCommand(SampleCommandCustomHeader.class); + assertThat(cmd.getCode()).isEqualTo(RemotingSysResponseCode.SYSTEM_ERROR); + assertThat(cmd.getVersion()).isEqualTo(2333); + assertThat(cmd.getRemark()).contains("not set any response code"); + assertThat(cmd.getFlag() & 0x01).isEqualTo(1); //flag bit 0: 1 presents response + } + + @Test + public void testEncodeAndDecode_EmptyBody() { + System.setProperty(RemotingCommand.REMOTING_VERSION_KEY, "2333"); + + int code = 103; //org.apache.rocketmq.common.protocol.RequestCode.REGISTER_BROKER + CommandCustomHeader header = new SampleCommandCustomHeader(); + RemotingCommand cmd = RemotingCommand.createRequestCommand(code, header); + + ByteBuffer buffer = cmd.encode(); + + //Simulate buffer being read in NettyDecoder + buffer.getInt(); + byte[] bytes = new byte[buffer.limit() - 4]; + buffer.get(bytes, 0, buffer.limit() - 4); + buffer = ByteBuffer.wrap(bytes); + + RemotingCommand decodedCommand = RemotingCommand.decode(buffer); + + assertThat(decodedCommand.getSerializeTypeCurrentRPC()).isEqualTo(SerializeType.JSON); + assertThat(decodedCommand.getBody()).isNull(); + } + + @Test + public void testEncodeAndDecode_FilledBody() { + System.setProperty(RemotingCommand.REMOTING_VERSION_KEY, "2333"); + + int code = 103; //org.apache.rocketmq.common.protocol.RequestCode.REGISTER_BROKER + CommandCustomHeader header = new SampleCommandCustomHeader(); + RemotingCommand cmd = RemotingCommand.createRequestCommand(code, header); + cmd.setBody(new byte[] { 0, 1, 2, 3, 4}); + + ByteBuffer buffer = cmd.encode(); + + //Simulate buffer being read in NettyDecoder + buffer.getInt(); + byte[] bytes = new byte[buffer.limit() - 4]; + buffer.get(bytes, 0, buffer.limit() - 4); + buffer = ByteBuffer.wrap(bytes); + + RemotingCommand decodedCommand = RemotingCommand.decode(buffer); + + assertThat(decodedCommand.getSerializeTypeCurrentRPC()).isEqualTo(SerializeType.JSON); + assertThat(decodedCommand.getBody()).isEqualTo(new byte[]{ 0, 1, 2, 3, 4}); + } + + @Test + public void testEncodeAndDecode_FilledBodyWithExtFields() throws RemotingCommandException { + System.setProperty(RemotingCommand.REMOTING_VERSION_KEY, "2333"); + + int code = 103; //org.apache.rocketmq.common.protocol.RequestCode.REGISTER_BROKER + CommandCustomHeader header = new ExtFieldsHeader(); + RemotingCommand cmd = RemotingCommand.createRequestCommand(code, header); + + cmd.addExtField("key", "value"); + + ByteBuffer buffer = cmd.encode(); + + //Simulate buffer being read in NettyDecoder + buffer.getInt(); + byte[] bytes = new byte[buffer.limit() - 4]; + buffer.get(bytes, 0, buffer.limit() - 4); + buffer = ByteBuffer.wrap(bytes); + + RemotingCommand decodedCommand = RemotingCommand.decode(buffer); + + assertThat(decodedCommand.getExtFields().get("stringValue")).isEqualTo("bilibili"); + assertThat(decodedCommand.getExtFields().get("intValue")).isEqualTo("2333"); + assertThat(decodedCommand.getExtFields().get("longValue")).isEqualTo("23333333"); + assertThat(decodedCommand.getExtFields().get("booleanValue")).isEqualTo("true"); + assertThat(decodedCommand.getExtFields().get("doubleValue")).isEqualTo("0.618"); + + assertThat(decodedCommand.getExtFields().get("key")).isEqualTo("value"); + + CommandCustomHeader decodedHeader = decodedCommand.decodeCommandCustomHeader(ExtFieldsHeader.class); + assertThat(((ExtFieldsHeader) decodedHeader).getStringValue()).isEqualTo("bilibili"); + assertThat(((ExtFieldsHeader) decodedHeader).getIntValue()).isEqualTo(2333); + assertThat(((ExtFieldsHeader) decodedHeader).getLongValue()).isEqualTo(23333333l); + assertThat(((ExtFieldsHeader) decodedHeader).isBooleanValue()).isEqualTo(true); + assertThat(((ExtFieldsHeader) decodedHeader).getDoubleValue()).isBetween(0.617, 0.619); + } +} + +class SampleCommandCustomHeader implements CommandCustomHeader { + @Override + public void checkFields() throws RemotingCommandException { + } +} + +class ExtFieldsHeader implements CommandCustomHeader { + private String stringValue = "bilibili"; + private int intValue = 2333; + private long longValue = 23333333l; + private boolean booleanValue = true; + private double doubleValue = 0.618; + + @Override + public void checkFields() throws RemotingCommandException { + } + + public String getStringValue() { + return stringValue; + } + + public int getIntValue() { + return intValue; + } + + public long getLongValue() { + return longValue; + } + + public boolean isBooleanValue() { + return booleanValue; + } + + public double getDoubleValue() { + return doubleValue; + } +} \ No newline at end of file diff --git a/remoting/src/test/java/org/apache/rocketmq/remoting/protocol/RemotingSerializableTest.java b/remoting/src/test/java/org/apache/rocketmq/remoting/protocol/RemotingSerializableTest.java new file mode 100644 index 00000000..38548cd8 --- /dev/null +++ b/remoting/src/test/java/org/apache/rocketmq/remoting/protocol/RemotingSerializableTest.java @@ -0,0 +1,162 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.rocketmq.remoting.protocol; + +import java.util.Arrays; +import java.util.List; +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class RemotingSerializableTest { + @Test + public void testEncodeAndDecode_HeterogeneousClass() { + Sample sample = new Sample(); + + byte[] bytes = RemotingSerializable.encode(sample); + Sample decodedSample = RemotingSerializable.decode(bytes, Sample.class); + + assertThat(decodedSample).isEqualTo(sample); + } + + @Test + public void testToJson_normalString() { + RemotingSerializable serializable = new RemotingSerializable() { + private List stringList = Arrays.asList("a", "o", "e", "i", "u", "v"); + + public List getStringList() { + return stringList; + } + + public void setStringList(List stringList) { + this.stringList = stringList; + } + }; + + String string = serializable.toJson(); + + assertThat(string).isEqualTo("{\"stringList\":[\"a\",\"o\",\"e\",\"i\",\"u\",\"v\"]}"); + } + + @Test + public void testToJson_prettyString() { + RemotingSerializable serializable = new RemotingSerializable() { + private List stringList = Arrays.asList("a", "o", "e", "i", "u", "v"); + + public List getStringList() { + return stringList; + } + + public void setStringList(List stringList) { + this.stringList = stringList; + } + }; + + String prettyString = serializable.toJson(true); + + assertThat(prettyString).isEqualTo("{\n" + + "\t\"stringList\":[\n" + + "\t\t\"a\",\n" + + "\t\t\"o\",\n" + + "\t\t\"e\",\n" + + "\t\t\"i\",\n" + + "\t\t\"u\",\n" + + "\t\t\"v\"\n" + + "\t]\n" + + "}"); + } + +} + +class Sample { + private String stringValue = "string"; + private int intValue = 2333; + private Integer integerValue = 666; + private double[] doubleArray = new double[]{0.618, 1.618}; + private List stringList = Arrays.asList("a", "o", "e", "i", "u", "v"); + + public String getStringValue() { + return stringValue; + } + + public void setStringValue(String stringValue) { + this.stringValue = stringValue; + } + + public int getIntValue() { + return intValue; + } + + public void setIntValue(int intValue) { + this.intValue = intValue; + } + + public Integer getIntegerValue() { + return integerValue; + } + + public void setIntegerValue(Integer integerValue) { + this.integerValue = integerValue; + } + + public double[] getDoubleArray() { + return doubleArray; + } + + public void setDoubleArray(double[] doubleArray) { + this.doubleArray = doubleArray; + } + + public List getStringList() { + return stringList; + } + + public void setStringList(List stringList) { + this.stringList = stringList; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + + Sample sample = (Sample)o; + + if (intValue != sample.intValue) + return false; + if (stringValue != null ? !stringValue.equals(sample.stringValue) : sample.stringValue != null) + return false; + if (integerValue != null ? !integerValue.equals(sample.integerValue) : sample.integerValue != null) + return false; + if (!Arrays.equals(doubleArray, sample.doubleArray)) + return false; + return stringList != null ? stringList.equals(sample.stringList) : sample.stringList == null; + + } + + @Override + public int hashCode() { + int result = stringValue != null ? stringValue.hashCode() : 0; + result = 31 * result + intValue; + result = 31 * result + (integerValue != null ? integerValue.hashCode() : 0); + result = 31 * result + Arrays.hashCode(doubleArray); + result = 31 * result + (stringList != null ? stringList.hashCode() : 0); + return result; + } +} \ No newline at end of file diff --git a/remoting/src/test/java/org/apache/rocketmq/remoting/protocol/RocketMQSerializableTest.java b/remoting/src/test/java/org/apache/rocketmq/remoting/protocol/RocketMQSerializableTest.java new file mode 100644 index 00000000..e49a0d72 --- /dev/null +++ b/remoting/src/test/java/org/apache/rocketmq/remoting/protocol/RocketMQSerializableTest.java @@ -0,0 +1,151 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.rocketmq.remoting.protocol; + +import java.util.HashMap; +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class RocketMQSerializableTest { + @Test + public void testRocketMQProtocolEncodeAndDecode_WithoutRemarkWithoutExtFields() { + System.setProperty(RemotingCommand.REMOTING_VERSION_KEY, "2333"); + + int code = 103; //org.apache.rocketmq.common.protocol.RequestCode.REGISTER_BROKER + RemotingCommand cmd = RemotingCommand.createRequestCommand(code, + new SampleCommandCustomHeader()); + cmd.setSerializeTypeCurrentRPC(SerializeType.ROCKETMQ); + + byte[] result = RocketMQSerializable.rocketMQProtocolEncode(cmd); + int opaque = cmd.getOpaque(); + + assertThat(result).hasSize(21); + assertThat(parseToShort(result, 0)).isEqualTo((short) code); //code + assertThat(result[2]).isEqualTo(LanguageCode.JAVA.getCode()); //language + assertThat(parseToShort(result, 3)).isEqualTo((short) 2333); //version + assertThat(parseToInt(result, 9)).isEqualTo(0); //flag + assertThat(parseToInt(result, 13)).isEqualTo(0); //empty remark + assertThat(parseToInt(result, 17)).isEqualTo(0); //empty extFields + + RemotingCommand decodedCommand = RocketMQSerializable.rocketMQProtocolDecode(result); + + assertThat(decodedCommand.getCode()).isEqualTo(code); + assertThat(decodedCommand.getLanguage()).isEqualTo(LanguageCode.JAVA); + assertThat(decodedCommand.getVersion()).isEqualTo(2333); + assertThat(decodedCommand.getOpaque()).isEqualTo(opaque); + assertThat(decodedCommand.getFlag()).isEqualTo(0); + assertThat(decodedCommand.getRemark()).isNull(); + assertThat(decodedCommand.getExtFields()).isNull(); + } + + @Test + public void testRocketMQProtocolEncodeAndDecode_WithRemarkWithoutExtFields() { + System.setProperty(RemotingCommand.REMOTING_VERSION_KEY, "2333"); + + int code = 103; //org.apache.rocketmq.common.protocol.RequestCode.REGISTER_BROKER + RemotingCommand cmd = RemotingCommand.createRequestCommand(code, + new SampleCommandCustomHeader()); + cmd.setSerializeTypeCurrentRPC(SerializeType.ROCKETMQ); + cmd.setRemark("Sample Remark"); + + byte[] result = RocketMQSerializable.rocketMQProtocolEncode(cmd); + int opaque = cmd.getOpaque(); + + assertThat(result).hasSize(34); + assertThat(parseToShort(result, 0)).isEqualTo((short) code); //code + assertThat(result[2]).isEqualTo(LanguageCode.JAVA.getCode()); //language + assertThat(parseToShort(result, 3)).isEqualTo((short) 2333); //version + assertThat(parseToInt(result, 9)).isEqualTo(0); //flag + assertThat(parseToInt(result, 13)).isEqualTo(13); //remark length + + byte[] remarkArray = new byte[13]; + System.arraycopy(result, 17, remarkArray, 0, 13); + assertThat(new String(remarkArray)).isEqualTo("Sample Remark"); + + assertThat(parseToInt(result, 30)).isEqualTo(0); //empty extFields + + RemotingCommand decodedCommand = RocketMQSerializable.rocketMQProtocolDecode(result); + + assertThat(decodedCommand.getCode()).isEqualTo(code); + assertThat(decodedCommand.getLanguage()).isEqualTo(LanguageCode.JAVA); + assertThat(decodedCommand.getVersion()).isEqualTo(2333); + assertThat(decodedCommand.getOpaque()).isEqualTo(opaque); + assertThat(decodedCommand.getFlag()).isEqualTo(0); + assertThat(decodedCommand.getRemark()).contains("Sample Remark"); + assertThat(decodedCommand.getExtFields()).isNull(); + } + + @Test + public void testRocketMQProtocolEncodeAndDecode_WithoutRemarkWithExtFields() { + System.setProperty(RemotingCommand.REMOTING_VERSION_KEY, "2333"); + + int code = 103; //org.apache.rocketmq.common.protocol.RequestCode.REGISTER_BROKER + RemotingCommand cmd = RemotingCommand.createRequestCommand(code, + new SampleCommandCustomHeader()); + cmd.setSerializeTypeCurrentRPC(SerializeType.ROCKETMQ); + cmd.addExtField("key", "value"); + + byte[] result = RocketMQSerializable.rocketMQProtocolEncode(cmd); + int opaque = cmd.getOpaque(); + + assertThat(result).hasSize(35); + assertThat(parseToShort(result, 0)).isEqualTo((short) code); //code + assertThat(result[2]).isEqualTo(LanguageCode.JAVA.getCode()); //language + assertThat(parseToShort(result, 3)).isEqualTo((short) 2333); //version + assertThat(parseToInt(result, 9)).isEqualTo(0); //flag + assertThat(parseToInt(result, 13)).isEqualTo(0); //empty remark + assertThat(parseToInt(result, 17)).isEqualTo(14); //extFields length + + byte[] extFieldsArray = new byte[14]; + System.arraycopy(result, 21, extFieldsArray, 0, 14); + HashMap extFields = RocketMQSerializable.mapDeserialize(extFieldsArray); + assertThat(extFields).contains(new HashMap.SimpleEntry("key", "value")); + + RemotingCommand decodedCommand = RocketMQSerializable.rocketMQProtocolDecode(result); + + assertThat(decodedCommand.getCode()).isEqualTo(code); + assertThat(decodedCommand.getLanguage()).isEqualTo(LanguageCode.JAVA); + assertThat(decodedCommand.getVersion()).isEqualTo(2333); + assertThat(decodedCommand.getOpaque()).isEqualTo(opaque); + assertThat(decodedCommand.getFlag()).isEqualTo(0); + assertThat(decodedCommand.getRemark()).isNull(); + assertThat(decodedCommand.getExtFields()).contains(new HashMap.SimpleEntry("key", "value")); + } + + @Test + public void testIsBlank_NotBlank() { + assertThat(RocketMQSerializable.isBlank("aeiou")).isFalse(); + assertThat(RocketMQSerializable.isBlank(" A ")).isFalse(); + } + + @Test + public void testIsBlank_Blank() { + assertThat(RocketMQSerializable.isBlank(null)).isTrue(); + assertThat(RocketMQSerializable.isBlank("")).isTrue(); + assertThat(RocketMQSerializable.isBlank(" ")).isTrue(); + } + + private short parseToShort(byte[] array, int index) { + return (short) (array[index] * 256 + array[++index]); + } + + private int parseToInt(byte[] array, int index) { + return array[index] * 16777216 + array[++index] * 65536 + array[++index] * 256 + + array[++index]; + } +} \ No newline at end of file -- GitLab