Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 858d72c4de | |||
| 9860f31d83 |
@@ -211,6 +211,32 @@ public class Converter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isValid(String value, int length, int pointLength) {
|
||||||
|
String normalized = value.replaceAll(" ", "");
|
||||||
|
if (SystemKeys.isScientificNormalizeEnabled()) {
|
||||||
|
try {
|
||||||
|
normalized = new BigDecimal(normalized).toPlainString();
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String[] data = normalized.split("[.]");
|
||||||
|
if (pointLength > 0) {
|
||||||
|
if (data.length == 1) {
|
||||||
|
if (data[0].length() > length - pointLength - 1) return false;
|
||||||
|
} else if (data.length == 2) {
|
||||||
|
if (data[0].length() > length - pointLength - 1) return false;
|
||||||
|
if (data[1].length() > pointLength) return false;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (data.length != 1) return false;
|
||||||
|
if (data[0].length() > length) return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public static String addPoint(String dpNum, int tLen , int dLen) {
|
public static String addPoint(String dpNum, int tLen , int dLen) {
|
||||||
if (dpNum == null || dpNum.trim().length() ==0 ){
|
if (dpNum == null || dpNum.trim().length() ==0 ){
|
||||||
return "0";
|
return "0";
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import java.util.Stack;
|
|||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import com.eactive.eai.transformer.SystemKeys;
|
import com.eactive.eai.transformer.SystemKeys;
|
||||||
|
import com.eactive.eai.transformer.layout.Converter;
|
||||||
import com.eactive.eai.transformer.layout.InvalidNodeException;
|
import com.eactive.eai.transformer.layout.InvalidNodeException;
|
||||||
import com.eactive.eai.transformer.layout.Item;
|
import com.eactive.eai.transformer.layout.Item;
|
||||||
import com.eactive.eai.transformer.layout.Types;
|
import com.eactive.eai.transformer.layout.Types;
|
||||||
@@ -268,7 +269,7 @@ public class JSONMessage extends Message {
|
|||||||
setLong( itemPath, new Long(value) );
|
setLong( itemPath, new Long(value) );
|
||||||
break;
|
break;
|
||||||
case Types.TYPE_BIGDECIMAL :
|
case Types.TYPE_BIGDECIMAL :
|
||||||
if (SystemKeys.isValidationEnabled() && !isValid(value, item.getLength(), item.getDecimalPointLength())) {
|
if (SystemKeys.isValidationEnabled() && !Converter.isValid(value, item.getLength(), item.getDecimalPointLength())) {
|
||||||
throw new InvalidAccessException(
|
throw new InvalidAccessException(
|
||||||
String.format("Invalid decimal point format Error value=%s,length=%d,pointLength=%d",
|
String.format("Invalid decimal point format Error value=%s,length=%d,pointLength=%d",
|
||||||
value, item.getLength(), item.getDecimalPointLength()),
|
value, item.getLength(), item.getDecimalPointLength()),
|
||||||
@@ -662,7 +663,7 @@ public class JSONMessage extends Message {
|
|||||||
|
|
||||||
private String getFormat(String value, int length, int pointLength, boolean isValidation) throws Exception{
|
private String getFormat(String value, int length, int pointLength, boolean isValidation) throws Exception{
|
||||||
if(isValidation) {
|
if(isValidation) {
|
||||||
if (!isValid(value,length,pointLength)){
|
if (!Converter.isValid(value,length,pointLength)){
|
||||||
throw new Exception(String.format("Invalid decimal point format Error value=%s,length=%d,pointLength=%d"
|
throw new Exception(String.format("Invalid decimal point format Error value=%s,length=%d,pointLength=%d"
|
||||||
, value,length,pointLength)
|
, value,length,pointLength)
|
||||||
);
|
);
|
||||||
@@ -702,44 +703,6 @@ public class JSONMessage extends Message {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isValid(String value,int length,int pointLength){
|
|
||||||
String normalized = value.replaceAll(" ", "");
|
|
||||||
if (SystemKeys.isScientificNormalizeEnabled()) {
|
|
||||||
try {
|
|
||||||
normalized = new BigDecimal(normalized).toPlainString();
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
String[] data = normalized.split("[.]");
|
|
||||||
if (pointLength > 0 ){
|
|
||||||
if (data.length ==1){
|
|
||||||
if (data[0].length() > length - pointLength - 1 ){ //정수부 오류
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}else if (data.length ==2){
|
|
||||||
if (data[0].length() > length - pointLength - 1 ){ //정수부 오류
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (data[1].length() > pointLength ){ //실수부 오류
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
//오류
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}else{
|
|
||||||
if (data.length != 1){ //소수점이 들어와서 오류
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (data[0].length() > length){ //정수부 오류
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// private Object toJsonObjectType(int itemType, String value) {
|
// private Object toJsonObjectType(int itemType, String value) {
|
||||||
// Object jsonValueObject = null;
|
// Object jsonValueObject = null;
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import org.dom4j.Namespace;
|
|||||||
import org.dom4j.QName;
|
import org.dom4j.QName;
|
||||||
|
|
||||||
import com.eactive.eai.transformer.SystemKeys;
|
import com.eactive.eai.transformer.SystemKeys;
|
||||||
|
import com.eactive.eai.transformer.layout.Converter;
|
||||||
import com.eactive.eai.transformer.layout.InvalidNodeException;
|
import com.eactive.eai.transformer.layout.InvalidNodeException;
|
||||||
import com.eactive.eai.transformer.layout.Item;
|
import com.eactive.eai.transformer.layout.Item;
|
||||||
import com.eactive.eai.transformer.layout.Layout;
|
import com.eactive.eai.transformer.layout.Layout;
|
||||||
@@ -198,8 +199,17 @@ public class XMLMessage extends Message {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (item.isField()) {
|
else if (item.isField()) {
|
||||||
Object data = child.getData();
|
Object data = child.getData();
|
||||||
|
if (data instanceof String
|
||||||
|
&& item.getDataTypeId() == Types.TYPE_BIGDECIMAL
|
||||||
|
&& SystemKeys.isValidationEnabled()
|
||||||
|
&& !Converter.isValid((String) data, item.getLength(), item.getDecimalPointLength())) {
|
||||||
|
throw new InvalidAccessException(
|
||||||
|
String.format("Invalid decimal point format Error value=%s,length=%d,pointLength=%d",
|
||||||
|
data, item.getLength(), item.getDecimalPointLength()),
|
||||||
|
childPath);
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
if (data instanceof String){
|
if (data instanceof String){
|
||||||
setString(childPath, (String) data);
|
setString(childPath, (String) data);
|
||||||
|
|||||||
@@ -0,0 +1,193 @@
|
|||||||
|
package com.eactive.eai.transformer;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
import static org.junit.jupiter.api.Assumptions.assumeTrue;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.DisplayName;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
|
||||||
|
import org.springframework.test.context.ContextConfiguration;
|
||||||
|
import org.springframework.test.context.jdbc.Sql;
|
||||||
|
|
||||||
|
import com.eactive.eai.transformer.engine.TransformEngine;
|
||||||
|
import com.eactive.eai.transformer.function.jpa.TransformJPATestConfiguration;
|
||||||
|
import com.eactive.eai.transformer.message.Message;
|
||||||
|
import com.eactive.eai.transformer.message.MessageFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* BytesMessage 필드 validation 영향도 단위테스트
|
||||||
|
*
|
||||||
|
* 테스트 대상 레이아웃: EAI_UBYTESTYPE_REQ1 (BYTES 타입, 전문길이=35)
|
||||||
|
* - INT_VALUE : TYPE_BYTEARRAY(2113), length=5, decimal=0
|
||||||
|
* - BIG_VALUE : TYPE_BYTEARRAY(2113), length=10, decimal=5
|
||||||
|
* - STR_VALUE : TYPE_BYTEARRAY(2113), length=20, decimal=0
|
||||||
|
*
|
||||||
|
* 검증 목적
|
||||||
|
* BytesMessage 필드는 Converter.convert()의 TYPE_BYTEARRAY(2113) 분기를 사용하며,
|
||||||
|
* 변경 대상인 TYPE_BIGDECIMAL(2118) + String 분기와 완전히 분리되어 있음을 확인한다.
|
||||||
|
*
|
||||||
|
* 시나리오
|
||||||
|
* A) setData(byte[]) 경로 — TYPE_BYTEARRAY 분기, 변경 전후 동일
|
||||||
|
* B) setString() 경로 — TYPE_BYTEARRAY 분기, 변경 전후 동일
|
||||||
|
* B-1) 정상 숫자 문자열 → 예외 없음 (bytes로 저장)
|
||||||
|
* B-2) 비숫자 문자열 → 예외 없음 (bytes로 저장, BigDecimal 변환 없음)
|
||||||
|
* B-3) 자릿수 초과 문자열, validation=true → 예외 없음 (TYPE_BYTEARRAY는 validation 대상 아님)
|
||||||
|
* B-4) 자릿수 초과 문자열, validation=false → 예외 없음
|
||||||
|
*/
|
||||||
|
@DataJpaTest
|
||||||
|
@ContextConfiguration(classes = { TransformJPATestConfiguration.class })
|
||||||
|
@Sql({
|
||||||
|
"/com/eactive/eai/transformer/init_tseaitr06.sql",
|
||||||
|
"/com/eactive/eai/transformer/init_bytes_validation.sql"
|
||||||
|
})
|
||||||
|
@DisplayName("BytesMessage Validation 영향도 테스트")
|
||||||
|
class BytesMessageValidationTest {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
TransformEngine engine;
|
||||||
|
|
||||||
|
// 전문 구조: INT_VALUE(5) + BIG_VALUE(10) + STR_VALUE(20) = 35 bytes
|
||||||
|
// BytesMessage는 소수점 없이 숫자만 저장 (decimal=5이면 끝 5자리가 소수부)
|
||||||
|
private static final String VALID_RAW =
|
||||||
|
"00042" // INT_VALUE : 5자리 정수
|
||||||
|
+ "0012312345" // BIG_VALUE : 10자리 (정수부5 + 소수부5, 소수점 제외)
|
||||||
|
+ "HELLO WORLD "; // STR_VALUE : 20자리 문자열
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setUp() {
|
||||||
|
try {
|
||||||
|
if (!engine.isStarted()) {
|
||||||
|
engine.start();
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
assumeTrue(false, "TransformEngine 시작 실패: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
void tearDown() {
|
||||||
|
System.setProperty(SystemKeys.TRANSFROMER_VALIDATION, "false");
|
||||||
|
System.setProperty(SystemKeys.TRANSFROMER_SCIENTIFIC_NORMALIZE, "false");
|
||||||
|
SystemKeys.reload();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─────────────────────────────────────────────────────────────────
|
||||||
|
// A. setData(byte[]) 경로 — TYPE_BYTEARRAY 분기 직접 사용
|
||||||
|
// Converter TYPE_BIGDECIMAL 분기와 완전히 무관
|
||||||
|
// ─────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("[A] 정상 전문(byte[]) setData → 정상 처리")
|
||||||
|
void testSetDataWithValidBytes() {
|
||||||
|
byte[] raw = VALID_RAW.getBytes();
|
||||||
|
Message msg = MessageFactory.getFactory().getMessage("EAI_UBYTESTYPE_REQ1");
|
||||||
|
|
||||||
|
assertDoesNotThrow(() -> msg.setData(raw),
|
||||||
|
"정상 전문 byte[] setData는 예외가 발생하지 않아야 합니다");
|
||||||
|
|
||||||
|
byte[] result = (byte[]) msg.getData();
|
||||||
|
assertNotNull(result, "getData() 결과가 null이 아니어야 합니다");
|
||||||
|
assertArrayEquals(raw, result, "입력 전문과 출력 전문이 동일해야 합니다");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("[A] validation=true 상태에서 byte[] setData → 영향 없음")
|
||||||
|
void testSetDataWithValidationEnabled() {
|
||||||
|
enableValidation();
|
||||||
|
byte[] raw = VALID_RAW.getBytes();
|
||||||
|
Message msg = MessageFactory.getFactory().getMessage("EAI_UBYTESTYPE_REQ1");
|
||||||
|
|
||||||
|
assertDoesNotThrow(() -> msg.setData(raw),
|
||||||
|
"validation=true 설정이 BytesMessage setData(byte[])에 영향을 주지 않아야 합니다");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─────────────────────────────────────────────────────────────────
|
||||||
|
// B-1. setString() — 정상 숫자 문자열
|
||||||
|
// TYPE_BYTEARRAY 분기 → String.getBytes() 저장, BigDecimal 변환 없음
|
||||||
|
// ─────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("[B-1] BIG_VALUE에 정상 숫자 문자열 setString → 예외 없음")
|
||||||
|
void testSetStringWithValidDecimal() {
|
||||||
|
byte[] raw = VALID_RAW.getBytes();
|
||||||
|
Message msg = MessageFactory.getFactory().getMessage("EAI_UBYTESTYPE_REQ1");
|
||||||
|
assertDoesNotThrow(() -> msg.setData(raw));
|
||||||
|
|
||||||
|
assertDoesNotThrow(
|
||||||
|
() -> msg.setString("EAI_UBYTESTYPE_REQ1.BIG_VALUE[0]", "1234.12345"),
|
||||||
|
"정상 숫자 문자열 setString은 예외가 발생하지 않아야 합니다");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─────────────────────────────────────────────────────────────────
|
||||||
|
// B-2. setString() — 비숫자 문자열
|
||||||
|
// TYPE_BYTEARRAY 분기 → String.getBytes() 저장
|
||||||
|
// BigDecimal 변환이 없으므로 NumberFormatException 발생 안 함
|
||||||
|
// (JSONMessage와 다른 동작: JSONMessage는 Converter TYPE_BIGDECIMAL 분기 → 예외)
|
||||||
|
// ─────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("[B-2] BIG_VALUE에 비숫자 문자열 setString → TYPE_BYTEARRAY이므로 예외 없음")
|
||||||
|
void testSetStringWithNonNumeric() {
|
||||||
|
byte[] raw = VALID_RAW.getBytes();
|
||||||
|
Message msg = MessageFactory.getFactory().getMessage("EAI_UBYTESTYPE_REQ1");
|
||||||
|
assertDoesNotThrow(() -> msg.setData(raw));
|
||||||
|
|
||||||
|
assertDoesNotThrow(
|
||||||
|
() -> msg.setString("EAI_UBYTESTYPE_REQ1.BIG_VALUE[0]", "not-a-number"),
|
||||||
|
"TYPE_BYTEARRAY 필드는 비숫자 문자열도 bytes로 저장하므로 예외가 발생하지 않아야 합니다");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─────────────────────────────────────────────────────────────────
|
||||||
|
// B-3. setString() — 자릿수 초과 문자열 + validation=true
|
||||||
|
// TYPE_BYTEARRAY 분기는 자릿수 검증 자체가 없음
|
||||||
|
// → validation 설정과 무관하게 예외 발생 안 함
|
||||||
|
// ★ 이 동작은 Converter TYPE_BIGDECIMAL 분기 수정 후에도 동일해야 함 ★
|
||||||
|
// ─────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("[B-3] BIG_VALUE 자릿수 초과 + validation=true → TYPE_BYTEARRAY이므로 예외 없음")
|
||||||
|
void testSetStringOverflowWithValidationEnabled() {
|
||||||
|
enableValidation();
|
||||||
|
byte[] raw = VALID_RAW.getBytes();
|
||||||
|
Message msg = MessageFactory.getFactory().getMessage("EAI_UBYTESTYPE_REQ1");
|
||||||
|
assertDoesNotThrow(() -> msg.setData(raw));
|
||||||
|
|
||||||
|
// 정수부 5자리(12345) > BIG_VALUE decimal=5 기준 제한(4자리) 초과
|
||||||
|
// → TYPE_BIGDECIMAL이었다면 validation 오류, TYPE_BYTEARRAY이므로 통과
|
||||||
|
assertDoesNotThrow(
|
||||||
|
() -> msg.setString("EAI_UBYTESTYPE_REQ1.BIG_VALUE[0]", "12345.123456"),
|
||||||
|
"TYPE_BYTEARRAY 필드는 validation 대상이 아니므로 자릿수 초과에도 예외가 발생하지 않아야 합니다");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─────────────────────────────────────────────────────────────────
|
||||||
|
// B-4. setString() — 자릿수 초과 문자열 + validation=false
|
||||||
|
// validation 설정과 무관하게 예외 없음 (B-3과 결과 동일)
|
||||||
|
// ─────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("[B-4] BIG_VALUE 자릿수 초과 + validation=false → 예외 없음")
|
||||||
|
void testSetStringOverflowWithValidationDisabled() {
|
||||||
|
// validation=false (기본값)
|
||||||
|
byte[] raw = VALID_RAW.getBytes();
|
||||||
|
Message msg = MessageFactory.getFactory().getMessage("EAI_UBYTESTYPE_REQ1");
|
||||||
|
assertDoesNotThrow(() -> msg.setData(raw));
|
||||||
|
|
||||||
|
assertDoesNotThrow(
|
||||||
|
() -> msg.setString("EAI_UBYTESTYPE_REQ1.BIG_VALUE[0]", "12345.123456"),
|
||||||
|
"validation=false(기본값) 상태에서 TYPE_BYTEARRAY 필드는 자릿수 초과에 예외가 발생하지 않아야 합니다");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─────────────────────────────────────────────────────────────────
|
||||||
|
// 유틸 메서드
|
||||||
|
// ─────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
private void enableValidation() {
|
||||||
|
System.setProperty(SystemKeys.TRANSFROMER_VALIDATION, "true");
|
||||||
|
SystemKeys.reload();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,253 @@
|
|||||||
|
package com.eactive.eai.transformer;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
import static org.junit.jupiter.api.Assumptions.assumeTrue;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.DisplayName;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
|
||||||
|
import org.springframework.test.context.ContextConfiguration;
|
||||||
|
import org.springframework.test.context.jdbc.Sql;
|
||||||
|
|
||||||
|
import com.eactive.eai.transformer.engine.TransformEngine;
|
||||||
|
import com.eactive.eai.transformer.function.jpa.TransformJPATestConfiguration;
|
||||||
|
import com.eactive.eai.transformer.message.Message;
|
||||||
|
import com.eactive.eai.transformer.message.MessageFactory;
|
||||||
|
import com.eactive.eai.transformer.message.MessageSetDataException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* XMLMessage BIGDECIMAL validation 단위테스트
|
||||||
|
*
|
||||||
|
* 테스트 대상 레이아웃: EAI_UXMLTYPE_REQ1 (XML 타입)
|
||||||
|
* - BIG_VALUE : TYPE_BIGDECIMAL(2118), length=10, decimal=5 → 정수부 최대 4자리
|
||||||
|
* - BIG15_VALUE : TYPE_BIGDECIMAL(2118), length=15, decimal=0 → 정수부 최대 15자리
|
||||||
|
* - STR_VALUE : TYPE_STRING(2101), length=20
|
||||||
|
*
|
||||||
|
* 검증 흐름
|
||||||
|
* setData(xmlString) → doSetData() → setValue(Element) → doSetValue()
|
||||||
|
* → TYPE_BIGDECIMAL 필드 + validation=true + 자릿수 초과 → InvalidAccessException
|
||||||
|
* → doSetData() catch → MessageSetDataException
|
||||||
|
*
|
||||||
|
* 시나리오
|
||||||
|
* A) 정상 XML → 예외 없음
|
||||||
|
* B) 정상 XML + validation=true → 예외 없음
|
||||||
|
* C-1) BIG_VALUE 정수부 초과(5자리) + validation=true → MessageSetDataException
|
||||||
|
* C-2) BIG_VALUE 정수부 초과(5자리) + validation=false → 예외 없음
|
||||||
|
* D-1) BIG15_VALUE 소수점 포함(decimal=0 필드) + validation=true → MessageSetDataException
|
||||||
|
* D-2) BIG15_VALUE 정수부 초과(16자리) + validation=true → MessageSetDataException
|
||||||
|
* E) BIG15_VALUE 정상 정수(≤15자리) + validation=true → 예외 없음
|
||||||
|
*/
|
||||||
|
@DataJpaTest
|
||||||
|
@ContextConfiguration(classes = { TransformJPATestConfiguration.class })
|
||||||
|
@Sql({
|
||||||
|
"/com/eactive/eai/transformer/init_tseaitr06.sql",
|
||||||
|
"/com/eactive/eai/transformer/init_xml_validation.sql"
|
||||||
|
})
|
||||||
|
@DisplayName("XMLMessage BIGDECIMAL Validation 테스트")
|
||||||
|
class XMLMessageValidationTest {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
TransformEngine engine;
|
||||||
|
|
||||||
|
// BIG_VALUE: length=10, decimal=5 → 정수부 최대 4자리, 소수부 최대 5자리
|
||||||
|
// BIG15_VALUE: length=15, decimal=0 → 정수부 최대 15자리, 소수점 없음
|
||||||
|
private static final String VALID_XML =
|
||||||
|
"<EAI_UXMLTYPE_REQ1>" +
|
||||||
|
"<BIG_VALUE>1234.12345</BIG_VALUE>" +
|
||||||
|
"<BIG15_VALUE>123000</BIG15_VALUE>" +
|
||||||
|
"<STR_VALUE>HELLO</STR_VALUE>" +
|
||||||
|
"</EAI_UXMLTYPE_REQ1>";
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setUp() {
|
||||||
|
try {
|
||||||
|
if (!engine.isStarted()) {
|
||||||
|
engine.start();
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
assumeTrue(false, "TransformEngine 시작 실패: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
void tearDown() {
|
||||||
|
System.setProperty(SystemKeys.TRANSFROMER_VALIDATION, "false");
|
||||||
|
System.setProperty(SystemKeys.TRANSFROMER_SCIENTIFIC_NORMALIZE, "false");
|
||||||
|
SystemKeys.reload();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─────────────────────────────────────────────────────────────────
|
||||||
|
// A. 정상 XML — validation 설정 무관
|
||||||
|
// ─────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("[A] 정상 XML → 예외 없음")
|
||||||
|
void testValidXml() {
|
||||||
|
Message msg = MessageFactory.getFactory().getMessage("EAI_UXMLTYPE_REQ1");
|
||||||
|
assertDoesNotThrow(() -> msg.setData(VALID_XML),
|
||||||
|
"정상 XML 파싱은 예외가 발생하지 않아야 합니다");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("[B] 정상 XML + validation=true → 예외 없음")
|
||||||
|
void testValidXml_withValidation() {
|
||||||
|
enableValidation();
|
||||||
|
Message msg = MessageFactory.getFactory().getMessage("EAI_UXMLTYPE_REQ1");
|
||||||
|
assertDoesNotThrow(() -> msg.setData(VALID_XML),
|
||||||
|
"정상값은 validation=true에서도 예외가 발생하지 않아야 합니다");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─────────────────────────────────────────────────────────────────
|
||||||
|
// C. BIG_VALUE 정수부 초과 — validation 설정에 따른 동작 분기
|
||||||
|
// BIG_VALUE: length=10, decimal=5 → 정수부 최대 4자리
|
||||||
|
// "12345.12345" → 정수부 5자리 초과
|
||||||
|
// ─────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("[C-1] BIG_VALUE 정수부 초과(5자리) + validation=true → MessageSetDataException")
|
||||||
|
void testBigValueIntegerOverflow_withValidation() {
|
||||||
|
enableValidation();
|
||||||
|
String xml =
|
||||||
|
"<EAI_UXMLTYPE_REQ1>" +
|
||||||
|
"<BIG_VALUE>12345.12345</BIG_VALUE>" +
|
||||||
|
"<BIG15_VALUE>123000</BIG15_VALUE>" +
|
||||||
|
"<STR_VALUE>HELLO</STR_VALUE>" +
|
||||||
|
"</EAI_UXMLTYPE_REQ1>";
|
||||||
|
Message msg = MessageFactory.getFactory().getMessage("EAI_UXMLTYPE_REQ1");
|
||||||
|
assertThrows(MessageSetDataException.class, () -> msg.setData(xml),
|
||||||
|
"정수부 자릿수 초과 시 validation=true이면 MessageSetDataException이 발생해야 합니다");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("[C-2] BIG_VALUE 정수부 초과(5자리) + validation=false → 예외 없음")
|
||||||
|
void testBigValueIntegerOverflow_withoutValidation() {
|
||||||
|
// validation=false (기본값)
|
||||||
|
String xml =
|
||||||
|
"<EAI_UXMLTYPE_REQ1>" +
|
||||||
|
"<BIG_VALUE>12345.12345</BIG_VALUE>" +
|
||||||
|
"<BIG15_VALUE>123000</BIG15_VALUE>" +
|
||||||
|
"<STR_VALUE>HELLO</STR_VALUE>" +
|
||||||
|
"</EAI_UXMLTYPE_REQ1>";
|
||||||
|
Message msg = MessageFactory.getFactory().getMessage("EAI_UXMLTYPE_REQ1");
|
||||||
|
assertDoesNotThrow(() -> msg.setData(xml),
|
||||||
|
"validation=false(기본값) 상태에서는 자릿수 초과에도 예외가 발생하지 않아야 합니다");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─────────────────────────────────────────────────────────────────
|
||||||
|
// D. BIG15_VALUE (decimal=0 필드) 오류 케이스
|
||||||
|
// D-1) 소수점 포함값 — decimal=0은 정수 전용, 소수점 자체가 오류
|
||||||
|
// D-2) 정수부 초과 — 16자리 > 15자리 제한
|
||||||
|
// ─────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("[D-1] BIG15_VALUE decimal=0 필드에 소수점 포함값 + validation=true → MessageSetDataException")
|
||||||
|
void testBig15ValueWithDecimalPoint_withValidation() {
|
||||||
|
enableValidation();
|
||||||
|
String xml =
|
||||||
|
"<EAI_UXMLTYPE_REQ1>" +
|
||||||
|
"<BIG_VALUE>1234.12345</BIG_VALUE>" +
|
||||||
|
"<BIG15_VALUE>123.456</BIG15_VALUE>" +
|
||||||
|
"<STR_VALUE>HELLO</STR_VALUE>" +
|
||||||
|
"</EAI_UXMLTYPE_REQ1>";
|
||||||
|
Message msg = MessageFactory.getFactory().getMessage("EAI_UXMLTYPE_REQ1");
|
||||||
|
assertThrows(MessageSetDataException.class, () -> msg.setData(xml),
|
||||||
|
"decimal=0 필드에 소수점 포함값 입력 시 validation=true이면 MessageSetDataException이 발생해야 합니다");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("[D-2] BIG15_VALUE 정수부 초과(16자리) + validation=true → MessageSetDataException")
|
||||||
|
void testBig15ValueIntegerOverflow_withValidation() {
|
||||||
|
enableValidation();
|
||||||
|
String xml =
|
||||||
|
"<EAI_UXMLTYPE_REQ1>" +
|
||||||
|
"<BIG_VALUE>1234.12345</BIG_VALUE>" +
|
||||||
|
"<BIG15_VALUE>1234567890123456</BIG15_VALUE>" +
|
||||||
|
"<STR_VALUE>HELLO</STR_VALUE>" +
|
||||||
|
"</EAI_UXMLTYPE_REQ1>";
|
||||||
|
Message msg = MessageFactory.getFactory().getMessage("EAI_UXMLTYPE_REQ1");
|
||||||
|
assertThrows(MessageSetDataException.class, () -> msg.setData(xml),
|
||||||
|
"정수부 16자리(>15) 초과 시 validation=true이면 MessageSetDataException이 발생해야 합니다");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─────────────────────────────────────────────────────────────────
|
||||||
|
// E. BIG15_VALUE 정상 정수 (≤15자리) + validation=true → 예외 없음
|
||||||
|
// ─────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("[E] BIG15_VALUE 정상 정수(≤15자리) + validation=true → 예외 없음")
|
||||||
|
void testBig15ValueValidInteger_withValidation() {
|
||||||
|
enableValidation();
|
||||||
|
Message msg = MessageFactory.getFactory().getMessage("EAI_UXMLTYPE_REQ1");
|
||||||
|
assertDoesNotThrow(() -> msg.setData(VALID_XML),
|
||||||
|
"15자리 이내 정수 입력 시 validation=true에서도 예외가 발생하지 않아야 합니다");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─────────────────────────────────────────────────────────────────
|
||||||
|
// F. 빈 요소 / 요소 없음 — 경계 케이스
|
||||||
|
// F-1) 빈 요소(<BIG_VALUE/>) + validation=true → 예외 없음
|
||||||
|
// dom4j는 빈 요소의 getData()를 null로 반환
|
||||||
|
// → null instanceof String = false → 검증 건너뜀 → 요소 없음과 동일 동작
|
||||||
|
// F-2) 빈 요소(<BIG_VALUE/>) + validation=false → 예외 없음
|
||||||
|
// F-3) 요소 없음(BIG_VALUE 미포함 XML) + validation=true → 예외 없음
|
||||||
|
// XML에 요소가 없으면 doSetValue() 순회 대상이 없어 검증 자체가 실행되지 않음
|
||||||
|
// ─────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("[F-1] BIG_VALUE 빈 요소(<BIG_VALUE/>) + validation=true → 예외 없음 (dom4j null 반환)")
|
||||||
|
void testBigValueEmptyElement_withValidation() {
|
||||||
|
enableValidation();
|
||||||
|
// dom4j는 빈 요소의 getData()를 null로 반환 → null instanceof String = false → 검증 건너뜀
|
||||||
|
String xml =
|
||||||
|
"<EAI_UXMLTYPE_REQ1>" +
|
||||||
|
"<BIG_VALUE></BIG_VALUE>" +
|
||||||
|
"<BIG15_VALUE>123000</BIG15_VALUE>" +
|
||||||
|
"<STR_VALUE>HELLO</STR_VALUE>" +
|
||||||
|
"</EAI_UXMLTYPE_REQ1>";
|
||||||
|
Message msg = MessageFactory.getFactory().getMessage("EAI_UXMLTYPE_REQ1");
|
||||||
|
assertDoesNotThrow(() -> msg.setData(xml),
|
||||||
|
"dom4j 빈 요소는 null로 처리되어 검증 대상이 아니므로 예외가 발생하지 않아야 합니다");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("[F-2] BIG_VALUE 빈 문자열 + validation=false → 예외 없음")
|
||||||
|
void testBigValueEmptyString_withoutValidation() {
|
||||||
|
// validation=false (기본값)
|
||||||
|
String xml =
|
||||||
|
"<EAI_UXMLTYPE_REQ1>" +
|
||||||
|
"<BIG_VALUE></BIG_VALUE>" +
|
||||||
|
"<BIG15_VALUE>123000</BIG15_VALUE>" +
|
||||||
|
"<STR_VALUE>HELLO</STR_VALUE>" +
|
||||||
|
"</EAI_UXMLTYPE_REQ1>";
|
||||||
|
Message msg = MessageFactory.getFactory().getMessage("EAI_UXMLTYPE_REQ1");
|
||||||
|
assertDoesNotThrow(() -> msg.setData(xml),
|
||||||
|
"validation=false(기본값) 상태에서는 빈 문자열도 예외가 발생하지 않아야 합니다");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("[F-3] BIG_VALUE 요소 없음 + validation=true → 예외 없음")
|
||||||
|
void testBigValueMissingElement_withValidation() {
|
||||||
|
enableValidation();
|
||||||
|
// BIG_VALUE 요소 자체를 XML에서 제외
|
||||||
|
String xml =
|
||||||
|
"<EAI_UXMLTYPE_REQ1>" +
|
||||||
|
"<BIG15_VALUE>123000</BIG15_VALUE>" +
|
||||||
|
"<STR_VALUE>HELLO</STR_VALUE>" +
|
||||||
|
"</EAI_UXMLTYPE_REQ1>";
|
||||||
|
Message msg = MessageFactory.getFactory().getMessage("EAI_UXMLTYPE_REQ1");
|
||||||
|
assertDoesNotThrow(() -> msg.setData(xml),
|
||||||
|
"XML에 요소가 없으면 검증 대상이 아니므로 예외가 발생하지 않아야 합니다");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─────────────────────────────────────────────────────────────────
|
||||||
|
// 유틸 메서드
|
||||||
|
// ─────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
private void enableValidation() {
|
||||||
|
System.setProperty(SystemKeys.TRANSFROMER_VALIDATION, "true");
|
||||||
|
SystemKeys.reload();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
-- BytesMessage BIGDECIMAL validation 영향도 검증용 레이아웃
|
||||||
|
-- EAI_UBYTESTYPE_REQ1 : BYTES 타입, 전문길이=35 (5+10+20)
|
||||||
|
-- - INT_VALUE : TYPE_BYTEARRAY(2113), length=5, decimal=0 → loutitemrefptrnidname='Integer'
|
||||||
|
-- - BIG_VALUE : TYPE_BYTEARRAY(2113), length=10, decimal=5 → loutitemrefptrnidname='BigDecimal'
|
||||||
|
-- - STR_VALUE : TYPE_BYTEARRAY(2113), length=20, decimal=0 → loutitemrefptrnidname='String'
|
||||||
|
--
|
||||||
|
-- ※ BytesMessage 필드는 loutitemptrnidname=2113(TYPE_BYTEARRAY) 사용
|
||||||
|
-- Converter.convert()의 TYPE_BIGDECIMAL(2118) 분기와 완전히 분리됨을 확인하기 위한 레이아웃
|
||||||
|
|
||||||
|
INSERT INTO tseaitr07 (loutname,loutptrnname,loutdesc,lastamndhms,eaibzwkdstcd,uapplname,sysintfacname,eaisevrdstcd,modfimgtstusdstcd,useyn,verinfo,author) VALUES
|
||||||
|
('EAI_UBYTESTYPE_REQ1', 'BYTES', 'BYTES 타입 validation 영향도 검증', '2026052010000000', 'TST', ' ', ' ', 'E', ' ', '1', '00001', 'admin');
|
||||||
|
|
||||||
|
INSERT INTO TSEAITR08 (loutname,loutitemname,loutitemserno,loutitemidname,parntloutitemidname,loutitemdesc,loutitemnodeptrnidname,loutitemptrnidname,loutitempathname,loutitemlencnt,loutitemrefinfo,loutitemrefinfo2,loutitemoccurptrndstcd,loutitemmaxoccurnoitm,loutitemminoccurnoitm,loutitembascval,loutitemmskyn,loutdptcnt,decptlencnt,loutitemrefptrnidname,loutitemmasklength,multilang,loutitemmaskoffset) VALUES
|
||||||
|
('EAI_UBYTESTYPE_REQ1', 'EAI_UBYTESTYPE_REQ1', 0, 9010, 0, 'BYTES 타입 validation 검증', 2201, 2100, NULL, 0, NULL, NULL, NULL, 0, 0, NULL, NULL, 1, 0, NULL, NULL, NULL, NULL),
|
||||||
|
('EAI_UBYTESTYPE_REQ1', 'INT_VALUE', 1, 9011, 9010, 'INT 타입 필드 (BYTEARRAY)', 2203, 2113, NULL, 5, NULL, NULL, NULL, 1, 1, NULL, 'N', 2, 0, 'Integer', 0, NULL, NULL),
|
||||||
|
('EAI_UBYTESTYPE_REQ1', 'BIG_VALUE', 2, 9012, 9010, 'BIGDECIMAL 필드 (BYTEARRAY) l=10 d=5', 2203, 2113, NULL, 10, NULL, NULL, NULL, 1, 1, NULL, 'N', 2, 5, 'BigDecimal', 0, NULL, NULL),
|
||||||
|
('EAI_UBYTESTYPE_REQ1', 'STR_VALUE', 3, 9013, 9010, 'STRING 타입 필드 (BYTEARRAY)', 2203, 2113, NULL, 20, NULL, NULL, NULL, 1, 1, NULL, 'N', 2, 0, 'String', 0, NULL, NULL);
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
-- XMLMessage BIGDECIMAL validation 테스트용 레이아웃
|
||||||
|
-- EAI_UXMLTYPE_REQ1 : XML 타입
|
||||||
|
-- - BIG_VALUE : TYPE_BIGDECIMAL(2118), length=10, decimal=5 → 정수부 최대 4자리
|
||||||
|
-- - BIG15_VALUE : TYPE_BIGDECIMAL(2118), length=15, decimal=0 → 정수부 최대 15자리, 소수점 없음
|
||||||
|
-- - STR_VALUE : TYPE_STRING(2101), length=20, decimal=0
|
||||||
|
|
||||||
|
INSERT INTO tseaitr07 (loutname,loutptrnname,loutdesc,lastamndhms,eaibzwkdstcd,uapplname,sysintfacname,eaisevrdstcd,modfimgtstusdstcd,useyn,verinfo,author) VALUES
|
||||||
|
('EAI_UXMLTYPE_REQ1', 'XML', 'XML 타입 BIGDECIMAL validation 테스트', '2026052010000000', 'TST', ' ', ' ', 'E', ' ', '1', '00001', 'admin');
|
||||||
|
|
||||||
|
INSERT INTO TSEAITR08 (loutname,loutitemname,loutitemserno,loutitemidname,parntloutitemidname,loutitemdesc,loutitemnodeptrnidname,loutitemptrnidname,loutitempathname,loutitemlencnt,loutitemrefinfo,loutitemrefinfo2,loutitemoccurptrndstcd,loutitemmaxoccurnoitm,loutitemminoccurnoitm,loutitembascval,loutitemmskyn,loutdptcnt,decptlencnt,loutitemrefptrnidname,loutitemmasklength,multilang,loutitemmaskoffset) VALUES
|
||||||
|
('EAI_UXMLTYPE_REQ1', 'EAI_UXMLTYPE_REQ1', 0, 9020, 0, 'XML BIGDECIMAL validation 루트', 2201, 2100, NULL, 0, NULL, NULL, NULL, 0, 0, NULL, NULL, 1, 0, NULL, NULL, NULL, NULL),
|
||||||
|
('EAI_UXMLTYPE_REQ1', 'BIG_VALUE', 1, 9021, 9020, 'BIGDECIMAL length=10 decimal=5', 2203, 2118, NULL, 10, NULL, NULL, NULL, 1, 1, NULL, 'N', 2, 5, 'BigDecimal', 0, NULL, NULL),
|
||||||
|
('EAI_UXMLTYPE_REQ1', 'BIG15_VALUE', 2, 9022, 9020, 'BIGDECIMAL length=15 decimal=0', 2203, 2118, NULL, 15, NULL, NULL, NULL, 1, 1, NULL, 'N', 2, 0, 'BigDecimal', 0, NULL, NULL),
|
||||||
|
('EAI_UXMLTYPE_REQ1', 'STR_VALUE', 3, 9023, 9020, 'STRING 타입 필드', 2203, 2101, NULL, 20, NULL, NULL, NULL, 1, 1, NULL, 'N', 2, 0, 'String', 0, NULL, NULL);
|
||||||
Reference in New Issue
Block a user