암복호화 function 개발
- 암호화모듈서비스(CryptoModuleService)를 호출하여 암복호화 수행하는 function
This commit is contained in:
+220
@@ -0,0 +1,220 @@
|
||||
package com.eactive.eai.custom.transformer.function;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyMap;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.ArgumentMatchers.isNull;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.reset;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Base64;
|
||||
import java.util.Stack;
|
||||
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.MethodOrderer;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.TestMethodOrder;
|
||||
import org.nfunk.jep.ParseException;
|
||||
import org.nfunk.jep.function.PostfixMathCommand;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.context.support.GenericApplicationContext;
|
||||
|
||||
import com.eactive.eai.common.security.CryptoModuleService;
|
||||
import com.eactive.eai.common.util.ApplicationContextProvider;
|
||||
|
||||
@TestMethodOrder(MethodOrderer.DisplayName.class)
|
||||
class DJBErpCryptoFunctionTest {
|
||||
|
||||
private static final String MODULE_NAME = "TEST_MODULE";
|
||||
private static final String PLAIN_TEXT = "plaintext-value";
|
||||
private static final byte[] PLAIN_BYTES = PLAIN_TEXT.getBytes(StandardCharsets.UTF_8);
|
||||
private static final byte[] CIPHER_BYTES = new byte[]{0x10, 0x20, 0x30, 0x40};
|
||||
private static final String ENC_BASE64 = Base64.getEncoder().encodeToString(CIPHER_BYTES);
|
||||
|
||||
private static GenericApplicationContext ctx;
|
||||
private static CryptoModuleService mockService;
|
||||
|
||||
private DJBErpDecryt decryt;
|
||||
private DJBErpEncryt encryt;
|
||||
|
||||
// =========================================================================
|
||||
// 클래스 초기화
|
||||
// =========================================================================
|
||||
|
||||
@BeforeAll
|
||||
static void setUpClass() throws Exception {
|
||||
mockService = mock(CryptoModuleService.class);
|
||||
|
||||
ctx = new GenericApplicationContext();
|
||||
ctx.getBeanFactory().registerSingleton("cryptoModuleService", mockService);
|
||||
ctx.registerBeanDefinition("applicationContextProvider",
|
||||
BeanDefinitionBuilder.genericBeanDefinition(ApplicationContextProvider.class)
|
||||
.getBeanDefinition());
|
||||
ctx.refresh();
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
static void tearDownClass() {
|
||||
if (ctx != null) ctx.close();
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
void setUp() throws Exception {
|
||||
reset(mockService);
|
||||
when(mockService.decrypt(any(), anyMap(), isNull(), any(byte[].class))).thenReturn(PLAIN_BYTES);
|
||||
when(mockService.encrypt(any(), anyMap(), isNull(), any(byte[].class))).thenReturn(CIPHER_BYTES);
|
||||
decryt = new DJBErpDecryt();
|
||||
encryt = new DJBErpEncryt();
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// 1. DJBErpDecryt
|
||||
// =========================================================================
|
||||
|
||||
@Test
|
||||
@DisplayName("1-1. 정상 복호화: (encBase64, moduleName) → 평문이 스택에 push된다")
|
||||
void decryt_normalCase_pushesPlainText() throws Exception {
|
||||
Stack<Object> stack = buildStack(ENC_BASE64, MODULE_NAME);
|
||||
setParamCount(decryt, 2);
|
||||
|
||||
decryt.run(stack);
|
||||
|
||||
assertEquals(PLAIN_TEXT, stack.pop());
|
||||
assertTrue(stack.isEmpty(), "결과 push 후 스택에 잔여 항목이 없어야 한다");
|
||||
verify(mockService).decrypt(eq(MODULE_NAME), anyMap(), isNull(), any(byte[].class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("1-2. 파라미터 수가 2가 아니면 ParseException")
|
||||
void decryt_wrongParamCount_throwsParseException() throws Exception {
|
||||
Stack<Object> stack = buildStack(ENC_BASE64, MODULE_NAME);
|
||||
setParamCount(decryt, 3);
|
||||
|
||||
assertThrows(ParseException.class, () -> decryt.run(stack));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("1-3. 유효하지 않은 Base64 입력 → ParseException")
|
||||
void decryt_invalidBase64_throwsParseException() throws Exception {
|
||||
Stack<Object> stack = buildStack("not-valid-base64!!!", MODULE_NAME);
|
||||
setParamCount(decryt, 2);
|
||||
|
||||
assertThrows(ParseException.class, () -> decryt.run(stack));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("1-4. 암호화 서비스 예외 → 'DJBErpDecryt 복호화 실패' ParseException으로 래핑")
|
||||
void decryt_serviceThrows_wrapsInParseException() throws Exception {
|
||||
when(mockService.decrypt(any(), anyMap(), isNull(), any(byte[].class)))
|
||||
.thenThrow(new RuntimeException("모듈 오류"));
|
||||
Stack<Object> stack = buildStack(ENC_BASE64, MODULE_NAME);
|
||||
setParamCount(decryt, 2);
|
||||
|
||||
ParseException ex = assertThrows(ParseException.class, () -> decryt.run(stack));
|
||||
assertTrue(ex.getMessage().contains("DJBErpDecryt 복호화 실패"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("1-5. moduleName이 CryptoModuleService에 그대로 전달된다")
|
||||
void decryt_moduleNamePassedToService() throws Exception {
|
||||
String customModule = "CUSTOM_AES_MODULE";
|
||||
Stack<Object> stack = buildStack(ENC_BASE64, customModule);
|
||||
setParamCount(decryt, 2);
|
||||
|
||||
decryt.run(stack);
|
||||
|
||||
verify(mockService).decrypt(eq(customModule), anyMap(), isNull(), any(byte[].class));
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// 2. DJBErpEncryt
|
||||
// =========================================================================
|
||||
|
||||
@Test
|
||||
@DisplayName("2-1. 정상 암호화: (plainText, moduleName) → Base64가 스택에 push된다")
|
||||
void encryt_normalCase_pushesBase64() throws Exception {
|
||||
Stack<Object> stack = buildStack(PLAIN_TEXT, MODULE_NAME);
|
||||
setParamCount(encryt, 2);
|
||||
|
||||
encryt.run(stack);
|
||||
|
||||
assertEquals(ENC_BASE64, stack.pop());
|
||||
assertTrue(stack.isEmpty(), "결과 push 후 스택에 잔여 항목이 없어야 한다");
|
||||
verify(mockService).encrypt(eq(MODULE_NAME), anyMap(), isNull(), any(byte[].class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("2-2. 파라미터 수가 2가 아니면 ParseException")
|
||||
void encryt_wrongParamCount_throwsParseException() throws Exception {
|
||||
Stack<Object> stack = buildStack(PLAIN_TEXT, MODULE_NAME);
|
||||
setParamCount(encryt, 3);
|
||||
|
||||
assertThrows(ParseException.class, () -> encryt.run(stack));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("2-3. 암호화 서비스 예외 → 'DJBErpEncryt 암호화 실패' ParseException으로 래핑")
|
||||
void encryt_serviceThrows_wrapsInParseException() throws Exception {
|
||||
when(mockService.encrypt(any(), anyMap(), isNull(), any(byte[].class)))
|
||||
.thenThrow(new RuntimeException("모듈 오류"));
|
||||
Stack<Object> stack = buildStack(PLAIN_TEXT, MODULE_NAME);
|
||||
setParamCount(encryt, 2);
|
||||
|
||||
ParseException ex = assertThrows(ParseException.class, () -> encryt.run(stack));
|
||||
assertTrue(ex.getMessage().contains("DJBErpEncryt 암호화 실패"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("2-4. moduleName이 CryptoModuleService에 그대로 전달된다")
|
||||
void encryt_moduleNamePassedToService() throws Exception {
|
||||
String customModule = "CUSTOM_AES_MODULE";
|
||||
Stack<Object> stack = buildStack(PLAIN_TEXT, customModule);
|
||||
setParamCount(encryt, 2);
|
||||
|
||||
encryt.run(stack);
|
||||
|
||||
verify(mockService).encrypt(eq(customModule), anyMap(), isNull(), any(byte[].class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("2-5. plainText가 UTF-8 바이트로 변환되어 서비스에 전달된다")
|
||||
void encryt_plainTextEncodedAsUtf8() throws Exception {
|
||||
String korean = "한글평문";
|
||||
Stack<Object> stack = buildStack(korean, MODULE_NAME);
|
||||
setParamCount(encryt, 2);
|
||||
|
||||
encryt.run(stack);
|
||||
|
||||
verify(mockService).encrypt(eq(MODULE_NAME), anyMap(), isNull(),
|
||||
eq(korean.getBytes(StandardCharsets.UTF_8)));
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// 헬퍼
|
||||
// =========================================================================
|
||||
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
private Stack<Object> buildStack(Object... params) {
|
||||
Stack stack = new Stack();
|
||||
for (Object p : params) {
|
||||
stack.push(p);
|
||||
}
|
||||
return stack;
|
||||
}
|
||||
|
||||
private void setParamCount(PostfixMathCommand cmd, int count) throws Exception {
|
||||
Field field = PostfixMathCommand.class.getDeclaredField("curNumberOfParameters");
|
||||
field.setAccessible(true);
|
||||
field.set(cmd, count);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user