diff --git a/src/main/java/com/eactive/eai/transformer/message/BytesMessage.java b/src/main/java/com/eactive/eai/transformer/message/BytesMessage.java index 790b022..b5c04bd 100644 --- a/src/main/java/com/eactive/eai/transformer/message/BytesMessage.java +++ b/src/main/java/com/eactive/eai/transformer/message/BytesMessage.java @@ -4,6 +4,7 @@ package com.eactive.eai.transformer.message; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.UnsupportedEncodingException; +import java.math.BigDecimal; import java.util.ArrayList; import java.util.Iterator; import java.util.Stack; @@ -250,6 +251,18 @@ public class BytesMessage extends Message { item.setValue(ByteUtil.cut(data, startPosition, item.getLength())); startPosition += item.getLength(); remainSize -= item.getLength(); + if (SystemKeys.isValidationEnabled() && item.getDecimalPointLength() > 0) { + String strVal = new String((byte[]) item.getValue(), defaultCharset).trim(); + try { + new BigDecimal(strVal); + } catch (NumberFormatException nfe) { + throw new MessageException( + String.format("decimal 필드 숫자형 오류: %s = [%s]", + item.getItemPath(), strVal)); + } + } + } catch(MessageException me) { + throw me; } catch(Exception e) { StringBuilder sb = new StringBuilder(); sb.append("전문레이아웃 매핑 중 데이터 사이즈 오류 ("+e.getMessage()+")"); diff --git a/src/test/java/com/eactive/eai/transformer/BytesMessageValidationTest.java b/src/test/java/com/eactive/eai/transformer/BytesMessageValidationTest.java index 2185366..8b57ea0 100644 --- a/src/test/java/com/eactive/eai/transformer/BytesMessageValidationTest.java +++ b/src/test/java/com/eactive/eai/transformer/BytesMessageValidationTest.java @@ -3,6 +3,7 @@ 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.Assertions.assertThrows; import static org.junit.jupiter.api.Assumptions.assumeTrue; import org.junit.jupiter.api.AfterEach; @@ -18,6 +19,7 @@ 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; /** * BytesMessage 필드 validation 영향도 단위테스트 @@ -71,8 +73,8 @@ class BytesMessageValidationTest { @AfterEach void tearDown() { - System.setProperty(SystemKeys.TRANSFROMER_VALIDATION, "false"); - System.setProperty(SystemKeys.TRANSFROMER_SCIENTIFIC_NORMALIZE, "false"); + System.clearProperty(SystemKeys.TRANSFROMER_VALIDATION); + System.clearProperty(SystemKeys.TRANSFROMER_SCIENTIFIC_NORMALIZE); SystemKeys.reload(); } @@ -165,21 +167,73 @@ class BytesMessageValidationTest { } // ───────────────────────────────────────────────────────────────── - // B-4. setString() — 자릿수 초과 문자열 + validation=false - // validation 설정과 무관하게 예외 없음 (B-3과 결과 동일) + // B-4. setString() — 자릿수 초과 문자열 + // setString 경로는 setDataBytes()를 통하지 않으므로 + // validation 설정과 완전히 무관하게 예외 발생 안 함 (B-3과 결과 동일) // ───────────────────────────────────────────────────────────────── @Test - @DisplayName("[B-4] BIG_VALUE 자릿수 초과 + validation=false → 예외 없음") - void testSetStringOverflowWithValidationDisabled() { - // validation=false (기본값) + @DisplayName("[B-4] BIG_VALUE 자릿수 초과 setString → setString 경로는 decimal 검증 대상 아님") + void testSetStringOverflowIsNotSubjectToDecimalValidation() { + // setString → setDataBytes() 미경유 → decimal 숫자형 검증 실행 안 됨 + // validation 설정과 무관하게 예외 없음 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 필드는 자릿수 초과에 예외가 발생하지 않아야 합니다"); + "TYPE_BYTEARRAY setString은 setDataBytes()를 통하지 않으므로 자릿수 초과에도 예외가 발생하지 않아야 합니다"); + } + + // ───────────────────────────────────────────────────────────────── + // C. decimal > 0 필드 숫자 검증 — 파싱(setData) 시점 + // BytesMessage는 raw bytes를 위치 기반으로 잘라 저장하므로, + // decimal > 0 인 숫자형 필드에 비숫자 bytes가 들어오는 경우를 검증 + // + // INVALID_RAW: BIG_VALUE 위치(5~14)에 비숫자 "HELLO_WOLD" 삽입 + // 전문 구조 동일: INT_VALUE(5) + BIG_VALUE(10) + STR_VALUE(20) = 35 bytes + // + // C-1) 비숫자 bytes + validation=true → MessageSetDataException + // C-2) 비숫자 bytes + validation=false → 예외 없음 (기존 동작 유지) + // C-3) 정상 숫자 bytes + validation=true → 예외 없음 ([A] 테스트와 동일 경로) + // ───────────────────────────────────────────────────────────────── + + private static final String INVALID_RAW = + "00042" // INT_VALUE : 5자리 정수 (decimal=0, 검증 대상 아님) + + "HELLO_WOLD" // BIG_VALUE : 비숫자 10자리 (decimal=5 → 숫자여야 함) + + "HELLO WORLD "; // STR_VALUE : 20자리 문자열 (decimal=0, 검증 대상 아님) + + @Test + @DisplayName("[C-1] decimal>0 필드에 비숫자 bytes + validation=true → MessageSetDataException") + void testDecimalFieldNonNumeric_withValidation() { + // validation 기본값이 true이므로 enableValidation() 호출 불필요 + Message msg = MessageFactory.getFactory().getMessage("EAI_UBYTESTYPE_REQ1"); + assertThrows(MessageSetDataException.class, + () -> msg.setData(INVALID_RAW.getBytes()), + "decimal>0 필드에 비숫자 bytes 입력 시 validation=true이면 MessageSetDataException이 발생해야 합니다"); + } + + @Test + @DisplayName("[C-2] decimal>0 필드에 비숫자 bytes + validation=false → 예외 없음") + void testDecimalFieldNonNumeric_withoutValidation() { + // 기본값이 true이므로 명시적으로 비활성화 + System.setProperty(SystemKeys.TRANSFROMER_VALIDATION, "false"); + SystemKeys.reload(); + Message msg = MessageFactory.getFactory().getMessage("EAI_UBYTESTYPE_REQ1"); + assertDoesNotThrow( + () -> msg.setData(INVALID_RAW.getBytes()), + "validation=false 상태에서는 비숫자 bytes도 예외가 발생하지 않아야 합니다"); + } + + @Test + @DisplayName("[C-3] decimal>0 필드에 정상 숫자 bytes + validation=true → 예외 없음") + void testDecimalFieldNumeric_withValidation() { + // validation 기본값이 true이므로 enableValidation() 호출 불필요 + Message msg = MessageFactory.getFactory().getMessage("EAI_UBYTESTYPE_REQ1"); + assertDoesNotThrow( + () -> msg.setData(VALID_RAW.getBytes()), + "decimal>0 필드에 정상 숫자 bytes 입력 시 validation=true에서도 예외가 발생하지 않아야 합니다"); } // ─────────────────────────────────────────────────────────────────