[RM] Feature Add validator's case for field and attribute type compare and field and type attribute length compare
MODIFY
BackEnd/Service/service-ntg/src/main/java/com/exactpro/sf/configuration/dictionary/impl/NTGDictionaryValidator.java
BackEnd/Service/service-ntg/src/main/java/com/exactpro/sf/configuration/dictionary/impl/NTGDictionaryValidator.java
******************************************************************************/
package com.exactpro.sf.configuration.dictionary.impl;
-import static com.exactpro.sf.common.messages.structures.StructureUtils.getAttributeValue;
-import static com.exactpro.sf.services.MessageHelper.FIELD_MESSAGE_TYPE;
-import static com.exactpro.sf.services.ntg.NTGMessageHelper.ATTRIBUTE_MESSAGE_TYPE;
-import static com.exactpro.sf.services.ntg.NTGMessageHelper.FIELD_MESSAGE_LENGTH;
-import static com.exactpro.sf.services.ntg.NTGMessageHelper.FIELD_START_OF_MESSAGE;
-import static com.exactpro.sf.services.ntg.NTGMessageHelper.MESSAGE_HEADER;
-import static com.exactpro.sf.services.ntg.NTGMessageHelper.MESSAGE_HEARTBEAT;
-import static com.exactpro.sf.services.ntg.NTGMessageHelper.MESSAGE_LOGON;
-import static com.exactpro.sf.services.ntg.NTGMessageHelper.MESSAGE_REJECT;
-import static com.exactpro.sf.services.ntg.NTGMessageHelper.MESSAGE_TYPE;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.commons.lang.ArrayUtils;
-
import com.exactpro.sf.common.impl.messages.xml.configuration.JavaType;
import com.exactpro.sf.common.messages.structures.IAttributeStructure;
import com.exactpro.sf.common.messages.structures.IDictionaryStructure;
@@ -48,9 +30,27 @@ import com.exactpro.sf.services.MessageHelper;
import com.exactpro.sf.services.ntg.NTGFieldFormat;
import com.exactpro.sf.services.ntg.NTGProtocolAttribute;
import com.google.common.collect.HashMultimap;
+import com.google.common.collect.ImmutableBiMap;
import com.google.common.collect.ImmutableSetMultimap;
import com.google.common.collect.Multimap;
import com.google.common.collect.SetMultimap;
+import org.apache.commons.lang.ArrayUtils;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import static com.exactpro.sf.common.messages.structures.StructureUtils.getAttributeValue;
+import static com.exactpro.sf.services.MessageHelper.FIELD_MESSAGE_TYPE;
+import static com.exactpro.sf.services.ntg.NTGMessageHelper.ATTRIBUTE_MESSAGE_TYPE;
+import static com.exactpro.sf.services.ntg.NTGMessageHelper.FIELD_MESSAGE_LENGTH;
+import static com.exactpro.sf.services.ntg.NTGMessageHelper.FIELD_START_OF_MESSAGE;
+import static com.exactpro.sf.services.ntg.NTGMessageHelper.MESSAGE_HEADER;
+import static com.exactpro.sf.services.ntg.NTGMessageHelper.MESSAGE_HEARTBEAT;
+import static com.exactpro.sf.services.ntg.NTGMessageHelper.MESSAGE_LOGON;
+import static com.exactpro.sf.services.ntg.NTGMessageHelper.MESSAGE_REJECT;
+import static com.exactpro.sf.services.ntg.NTGMessageHelper.MESSAGE_TYPE;
public class NTGDictionaryValidator extends AbstractDictionaryValidator {
@@ -65,6 +65,18 @@ public class NTGDictionaryValidator extends AbstractDictionaryValidator {
protected static final int lengthLong = 8;
protected static final int[] lengthLocalDateTime = {24};
+ private static final String UINT8 = "UInt8";
+ private static final String UINT16 = "UInt16";
+ private static final String UINT32 = "UInt32";
+ private static final String UINT64 = "UInt64";
+
+ private static final ImmutableBiMap<JavaType, String> POSSIBLE_ATTRIBUTE_TYPE_FOR_FIELD_TYPE = ImmutableBiMap.<JavaType, String>builder()
+ .put(JavaType.JAVA_LANG_SHORT, UINT8)
+ .put(JavaType.JAVA_LANG_INTEGER, UINT16)
+ .put(JavaType.JAVA_LANG_LONG, UINT32)
+ .put(JavaType.JAVA_MATH_BIG_DECIMAL, UINT64)
+ .build();
+
private final Multimap<JavaType, String> typeAllowedFormats = ImmutableSetMultimap.<JavaType, String>builder()
.putAll(JavaType.JAVA_LANG_STRING, NTGFieldFormat.A.name(), NTGFieldFormat.D.name())
.build();
@@ -116,6 +128,10 @@ public class NTGDictionaryValidator extends AbstractDictionaryValidator {
checkFieldOffsets(errors, message, field);
}
+ if (containLength) {
+ checkCompatibilityLengthAndAttributeType(errors, message, field);
+ }
+
if (typeAllowedFormats.containsKey(field.getJavaType())) {
checkFormatAttribute(errors, message, field, typeAllowedFormats.get(field.getJavaType()));
}
@@ -124,6 +140,7 @@ public class NTGDictionaryValidator extends AbstractDictionaryValidator {
return errors;
}
+
private void checkFormatAttribute(List<DictionaryValidationError> errors, IMessageStructure message, IFieldStructure field, Collection<String> allowedFormats) {
if (ValidationHelper.checkRequiredFieldAttribute(errors, message, field, NTGProtocolAttribute.Format.name())) {
String format = getAttributeValue(field, NTGProtocolAttribute.Format.name());
@@ -350,4 +367,89 @@ public class NTGDictionaryValidator extends AbstractDictionaryValidator {
}
}
+ private void checkCompatibilityLengthAndAttributeType(List<DictionaryValidationError> errors, IMessageStructure message, IFieldStructure field) {
+
+ String attributeType = getAttributeValue(field, NTGProtocolAttribute.Type.toString());
+
+ if (attributeType == null) {
+ return;
+ }
+
+ Integer length = getAttributeValue(field, NTGProtocolAttribute.Length.toString());
+
+ switch (attributeType) {
+ case UINT8:
+ checkAttributeTypeSatisfyFieldType(errors, message, field, attributeType);
+
+ if (length == lengthByte) {
+ return;
+ }
+ break;
+
+ case UINT16:
+ checkAttributeTypeSatisfyFieldType(errors, message, field, attributeType);
+
+ if (length == lengthShort) {
+ return;
+ }
+ break;
+
+ case UINT32:
+ checkAttributeTypeSatisfyFieldType(errors, message, field, attributeType);
+
+ if (length == lengthInt) {
+ return;
+ }
+ break;
+
+ case UINT64:
+ checkAttributeTypeSatisfyFieldType(errors, message, field, attributeType);
+
+ if (length == lengthLong) {
+ return;
+ }
+ break;
+
+ default:
+ return;
+
+ }
+ errors.add(
+ new DictionaryValidationError(message == null ? null : message.getName(), field.getName(),
+ String.format("Attribute <strong>\"Type\"</strong> value [%s] has length different from the attribute <strong>\"Length\"</strong> value = [%s]",
+ attributeType, length),
+ DictionaryValidationErrorLevel.FIELD, DictionaryValidationErrorType.ERR_ATTRIBUTES));
+ }
+
+ private void checkAttributeTypeSatisfyFieldType(List<DictionaryValidationError> errors, IMessageStructure message,
+ IFieldStructure field, String attributeType) {
+
+ JavaType fieldType = field.getJavaType();
+
+ String possibleType = POSSIBLE_ATTRIBUTE_TYPE_FOR_FIELD_TYPE.get(fieldType);
+
+ if (possibleType == null || !possibleType.equals(attributeType)) {
+
+ String errorMessage;
+
+ if (fieldType == JavaType.JAVA_LANG_BYTE) {
+
+ String fieldTypeInStringFormat = field.getJavaType().toString();
+
+ errorMessage = String.format("Attribute <strong>\"Type\"</strong> value [%s] doesn't match the field type [%s]. Field type [%s] cannot be matched to any unsigned type. Possible value for field type is [%s]",
+ attributeType, fieldTypeInStringFormat, fieldTypeInStringFormat, POSSIBLE_ATTRIBUTE_TYPE_FOR_FIELD_TYPE.inverse().get(attributeType));
+
+ } else {
+
+ errorMessage = String.format("Attribute <strong>\"Type\"</strong> value [%s] doesn't match the field type [%s]. Possible value for attribute type is [%s]. Possible value for field type is [%s]",
+ attributeType, field.getJavaType().toString(), possibleType, POSSIBLE_ATTRIBUTE_TYPE_FOR_FIELD_TYPE.inverse().get(attributeType));
+ }
+
+ errors.add(
+ new DictionaryValidationError(message == null ? null : message.getName(), field.getName(),
+ errorMessage,
+ DictionaryValidationErrorLevel.FIELD, DictionaryValidationErrorType.ERR_ATTRIBUTES));
+ }
+ }
+
}

MODIFY
BackEnd/Service/service-ntg/src/test/java/com/exactpro/sf/configuration/dictionary/TestNTGDictionaryValidator.java
BackEnd/Service/service-ntg/src/test/java/com/exactpro/sf/configuration/dictionary/TestNTGDictionaryValidator.java
******************************************************************************/
package com.exactpro.sf.configuration.dictionary;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
import com.exactpro.sf.common.messages.structures.IDictionaryStructure;
import com.exactpro.sf.configuration.dictionary.interfaces.IDictionaryValidator;
import com.exactpro.sf.services.ntg.TestNTGHelper;
import com.exactpro.sf.util.AbstractTest;
-
import org.apache.commons.lang3.ArrayUtils;
-import org.junit.Assert;
import org.junit.Test;
import java.io.IOException;
import java.util.List;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
public class TestNTGDictionaryValidator extends AbstractTest {
private final IDictionaryValidator validator = new NTGDictionaryValidatorFactory()
@@ -51,13 +49,19 @@ public class TestNTGDictionaryValidator extends AbstractTest {
List<DictionaryValidationError> errors = validator.validate(dictionary, true, null);
String[] expectedErrors = {
+ "DictionaryValidationError[message=Logon,field=MessageVersion,error=Attribute <strong>\"Type\"</strong> value [UInt8] doesn't match the field type [JAVA_LANG_BYTE]. Field type [JAVA_LANG_BYTE] cannot be matched to any unsigned type. Possible value for field type is [JAVA_LANG_SHORT],level=FIELD,type=ERR_ATTRIBUTES]",
+ "DictionaryValidationError[message=Reject,field=RejectCode,error=Attribute <strong>\"Type\"</strong> value [UInt32] doesn't match the field type [JAVA_LANG_INTEGER]. Possible value for attribute type is [UInt16]. Possible value for field type is [JAVA_LANG_LONG],level=FIELD,type=ERR_ATTRIBUTES]",
"DictionaryValidationError[message=Reject,field=<null>,error=Message <strong>\"Reject\"</strong> doesn't contain IsAdmin attribute,level=MESSAGE,type=ERR_ATTRIBUTES]",
"DictionaryValidationError[message=AnotherTestMessage,field=OrderType,error=Attribute <strong>\"Length\"</strong> has incorrect value = [8]. Must be one of [1, 2, 4],level=FIELD,type=ERR_ATTRIBUTES]",
+ "DictionaryValidationError[message=AnotherTestMessage,field=OrderType,error=Attribute <strong>\"Type\"</strong> value [UInt64] doesn't match the field type [JAVA_LANG_INTEGER]. Possible value for attribute type is [UInt16]. Possible value for field type is [JAVA_MATH_BIG_DECIMAL],level=FIELD,type=ERR_ATTRIBUTES]",
"DictionaryValidationError[message=AnotherTestMessage,field=AnotherOrderType,error=Attribute <strong>\"Length\"</strong> has incorrect value = [1]. Must be one of [4, 8],level=FIELD,type=ERR_ATTRIBUTES]",
+ "DictionaryValidationError[message=AnotherTestMessage,field=AnotherOrderType,error=Attribute <strong>\"Type\"</strong> value [UInt64] doesn't match the field type [JAVA_LANG_LONG]. Possible value for attribute type is [UInt32]. Possible value for field type is [JAVA_MATH_BIG_DECIMAL],level=FIELD,type=ERR_ATTRIBUTES]",
+ "DictionaryValidationError[message=AnotherTestMessage,field=AnotherOrderType,error=Attribute <strong>\"Type\"</strong> value [UInt64] has length different from the attribute <strong>\"Length\"</strong> value = [1],level=FIELD,type=ERR_ATTRIBUTES]",
"DictionaryValidationError[message=TestMessage,field=ClOrdID,error=Attribute <strong>Format</strong> must have one of the next values [A,D] for field with type [java.lang.String] but has [S],level=FIELD,type=ERR_ATTRIBUTES]",
"DictionaryValidationError[message=TestMessage,field=OrderType,error=Offset attribute is incorrect. actual - 50; expected - 54,level=FIELD,type=ERR_ATTRIBUTES]",
"DictionaryValidationError[message=<null>,field=<null>,error=Message <strong>\"Heartbeat\"</strong> is missing in dictionary,level=DICTIONARY,type=ERR_REQUIRED_FIELD]",
"DictionaryValidationError[message=Reject,field=<null>,error=MessageType attribute value is not exist in enum. Value [52],level=MESSAGE,type=ERR_ATTRIBUTES]"
+
};
assertEquals("Wrong errors count", expectedErrors.length, errors.size());

MODIFY
BackEnd/Service/service-ntg/src/test/plugin/cfg/dictionaries/ntg_errors.xml
BackEnd/Service/service-ntg/src/test/plugin/cfg/dictionaries/ntg_errors.xml
<field type="java.lang.Byte" name="MessageVersion">
<attribute type="java.lang.Integer" name="Offset">79</attribute>
<attribute type="java.lang.Integer" name="Length">1</attribute>
+ <attribute type="java.lang.String" name="Type">UInt8</attribute>
</field>
</message>
<message name="Reject">
<field type="java.lang.Integer" name="RejectCode">
<attribute type="java.lang.Integer" name="Offset">4</attribute>
<attribute type="java.lang.Integer" name="Length">4</attribute>
+ <attribute type="java.lang.String" name="Type">UInt32</attribute>
</field>
<field type="java.lang.String" name="RejectReason">
<attribute type="java.lang.String" name="Format">A</attribute>
<field defaultvalue="0" type="java.lang.Integer" name="OrderType">
<attribute type="java.lang.Integer" name="Length">8</attribute>
<attribute type="java.lang.Integer" name="Offset">54</attribute>
+ <attribute type="java.lang.String" name="Type">UInt64</attribute>
</field>
<field defaultvalue="1" type="java.lang.Long" name="AnotherOrderType">
<attribute type="java.lang.Integer" name="Length">1</attribute>
<attribute type="java.lang.Integer" name="Offset">62</attribute>
+ <attribute type="java.lang.String" name="Type">UInt64</attribute>
</field>
</message>
</messages>

[RM] Feature #71201. Add validator's case for field and attribute type compare and field and type attribute length compare

Change-Id: Ibc88761a4d868bc5f557e4cd114532e0cd289ee5