Merge branch 'feature/inflow-control-improvement' into master
This commit is contained in:
+1
-1
Submodule elink-online-common updated: d81aeeef67...d08c7efcdc
@@ -0,0 +1,40 @@
|
||||
package com.eactive.eai.manage.inflow;
|
||||
|
||||
public class GroupMetricDTO {
|
||||
private String groupId;
|
||||
private String groupName;
|
||||
private boolean activate;
|
||||
private long allowed;
|
||||
private long rejectedPerSecond;
|
||||
private long rejectedThreshold;
|
||||
private long totalRequests;
|
||||
private double rejectRatio;
|
||||
private long lastResetTime;
|
||||
|
||||
public String getGroupId() { return groupId; }
|
||||
public void setGroupId(String groupId) { this.groupId = groupId; }
|
||||
|
||||
public String getGroupName() { return groupName; }
|
||||
public void setGroupName(String groupName) { this.groupName = groupName; }
|
||||
|
||||
public boolean isActivate() { return activate; }
|
||||
public void setActivate(boolean activate) { this.activate = activate; }
|
||||
|
||||
public long getAllowed() { return allowed; }
|
||||
public void setAllowed(long allowed) { this.allowed = allowed; }
|
||||
|
||||
public long getRejectedPerSecond() { return rejectedPerSecond; }
|
||||
public void setRejectedPerSecond(long rejectedPerSecond) { this.rejectedPerSecond = rejectedPerSecond; }
|
||||
|
||||
public long getRejectedThreshold() { return rejectedThreshold; }
|
||||
public void setRejectedThreshold(long rejectedThreshold) { this.rejectedThreshold = rejectedThreshold; }
|
||||
|
||||
public long getTotalRequests() { return totalRequests; }
|
||||
public void setTotalRequests(long totalRequests) { this.totalRequests = totalRequests; }
|
||||
|
||||
public double getRejectRatio() { return rejectRatio; }
|
||||
public void setRejectRatio(double rejectRatio) { this.rejectRatio = rejectRatio; }
|
||||
|
||||
public long getLastResetTime() { return lastResetTime; }
|
||||
public void setLastResetTime(long lastResetTime) { this.lastResetTime = lastResetTime; }
|
||||
}
|
||||
@@ -1,9 +1,7 @@
|
||||
package com.eactive.eai.manage.inflow;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@@ -72,21 +70,8 @@ public class InflowGroupBucketService {
|
||||
return dto;
|
||||
}
|
||||
|
||||
/**
|
||||
* 그룹 버킷 조회 (리플렉션 사용)
|
||||
*/
|
||||
public CustomGroupBucket getCustomGroupBucket(String groupId) {
|
||||
try {
|
||||
InflowControlManager manager = InflowControlManager.getInstance();
|
||||
Field field = InflowControlManager.class.getDeclaredField("groupBucketList");
|
||||
field.setAccessible(true);
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, CustomGroupBucket> groupBucketList =
|
||||
(Map<String, CustomGroupBucket>) field.get(manager);
|
||||
return groupBucketList.get(groupId);
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
return InflowControlManager.getInstance().getGroupBucket(groupId);
|
||||
}
|
||||
|
||||
public List<GroupBucketStatusDTO> getAllGroupBucketStatus() {
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
package com.eactive.eai.manage.inflow;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/manage/inflow/group")
|
||||
public class InflowGroupMetricController {
|
||||
|
||||
@Autowired
|
||||
private InflowGroupMetricService metricService;
|
||||
|
||||
/**
|
||||
* 특정 그룹의 메트릭 조회
|
||||
* GET /manage/inflow/group/{groupId}/metric
|
||||
*/
|
||||
@GetMapping("/{groupId}/metric")
|
||||
public ResponseEntity<?> getGroupMetric(@PathVariable String groupId) {
|
||||
GroupMetricDTO metric = metricService.getGroupMetric(groupId);
|
||||
|
||||
if (metric == null) {
|
||||
Map<String, Object> error = new HashMap<>();
|
||||
error.put("success", false);
|
||||
error.put("message", "그룹을 찾을 수 없습니다: " + groupId);
|
||||
return ResponseEntity.ok(error);
|
||||
}
|
||||
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("success", true);
|
||||
result.put("data", metric);
|
||||
return ResponseEntity.ok(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 모든 그룹의 메트릭 조회
|
||||
* GET /manage/inflow/group/metric
|
||||
*/
|
||||
@GetMapping("/metric")
|
||||
public ResponseEntity<?> getAllGroupMetrics() {
|
||||
List<GroupMetricDTO> list = metricService.getAllGroupMetrics();
|
||||
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("success", true);
|
||||
result.put("data", list);
|
||||
result.put("count", list.size());
|
||||
return ResponseEntity.ok(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 특정 그룹의 메트릭 초기화
|
||||
* POST /manage/inflow/group/{groupId}/metric/reset
|
||||
*/
|
||||
@PostMapping("/{groupId}/metric/reset")
|
||||
public ResponseEntity<?> resetGroupMetric(@PathVariable String groupId) {
|
||||
boolean ok = metricService.resetGroupMetric(groupId);
|
||||
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("success", ok);
|
||||
result.put("message", ok ? "초기화 완료: " + groupId : "그룹을 찾을 수 없습니다: " + groupId);
|
||||
return ResponseEntity.ok(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 전체 그룹 메트릭 초기화
|
||||
* POST /manage/inflow/group/metric/reset
|
||||
*/
|
||||
@PostMapping("/metric/reset")
|
||||
public ResponseEntity<?> resetAllGroupMetrics() {
|
||||
metricService.resetAllGroupMetrics();
|
||||
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("success", true);
|
||||
result.put("message", "전체 그룹 메트릭 초기화 완료");
|
||||
return ResponseEntity.ok(result);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package com.eactive.eai.manage.inflow;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.eactive.eai.common.inflow.Bucket;
|
||||
import com.eactive.eai.common.inflow.InflowControlUtil;
|
||||
import com.eactive.eai.common.inflow.InflowGroupVO;
|
||||
import com.eactive.eai.common.inflow.dual.DualInflowControlManager;
|
||||
|
||||
@Service
|
||||
public class InflowGroupMetricService {
|
||||
|
||||
public GroupMetricDTO getGroupMetric(String groupId) {
|
||||
DualInflowControlManager manager = getManager();
|
||||
if (manager == null) return null;
|
||||
|
||||
InflowGroupVO groupVo = manager.getGroupInflowThreshold(groupId);
|
||||
if (groupVo == null) return null;
|
||||
|
||||
return buildDTO(groupId, groupVo, manager.getGroupMetrics(groupId));
|
||||
}
|
||||
|
||||
public List<GroupMetricDTO> getAllGroupMetrics() {
|
||||
DualInflowControlManager manager = getManager();
|
||||
if (manager == null) return new ArrayList<>();
|
||||
|
||||
List<GroupMetricDTO> result = new ArrayList<>();
|
||||
for (String groupId : manager.getGroupAllKeys()) {
|
||||
GroupMetricDTO dto = getGroupMetric(groupId);
|
||||
if (dto != null) result.add(dto);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean resetGroupMetric(String groupId) {
|
||||
DualInflowControlManager manager = getManager();
|
||||
if (manager == null) return false;
|
||||
if (manager.getGroupInflowThreshold(groupId) == null) return false;
|
||||
manager.resetGroupMetrics(groupId);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void resetAllGroupMetrics() {
|
||||
DualInflowControlManager manager = getManager();
|
||||
if (manager != null) manager.resetAllGroupMetrics();
|
||||
}
|
||||
|
||||
protected DualInflowControlManager getManager() {
|
||||
Bucket bucket = InflowControlUtil.getBucket();
|
||||
return (bucket instanceof DualInflowControlManager)
|
||||
? (DualInflowControlManager) bucket
|
||||
: null;
|
||||
}
|
||||
|
||||
private GroupMetricDTO buildDTO(String groupId, InflowGroupVO groupVo,
|
||||
DualInflowControlManager.TargetMetrics m) {
|
||||
GroupMetricDTO dto = new GroupMetricDTO();
|
||||
dto.setGroupId(groupId);
|
||||
dto.setGroupName(groupVo.getGroupName());
|
||||
dto.setActivate(groupVo.isActivate());
|
||||
|
||||
if (m != null) {
|
||||
long allowed = m.allowed.get();
|
||||
long rejPs = m.rejectedPerSecond.get();
|
||||
long rejTh = m.rejectedThreshold.get();
|
||||
long total = allowed + rejPs + rejTh;
|
||||
dto.setAllowed(allowed);
|
||||
dto.setRejectedPerSecond(rejPs);
|
||||
dto.setRejectedThreshold(rejTh);
|
||||
dto.setTotalRequests(total);
|
||||
dto.setRejectRatio(total > 0
|
||||
? Math.round((double)(rejPs + rejTh) / total * 10000) / 100.0
|
||||
: 0.0);
|
||||
dto.setLastResetTime(m.lastResetTime);
|
||||
}
|
||||
return dto;
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,7 @@ mapper.definition=standard-message-mapping-config-djb.properties
|
||||
# StandardMessage Coordinator implementation
|
||||
message.coordinator.class=com.eactive.eai.custom.message.StandardMessageCoordinatorDJB
|
||||
# RequestProcessor implementation
|
||||
#requestProcessor.class=com.eactive.eai.inbound.processor.RequestProcessor
|
||||
requestProcessor.class=com.eactive.eai.inbound.processor.DualRequestProcessor
|
||||
# reader : parsing input data to StandardMessage
|
||||
reader.JSON=com.eactive.eai.message.parser.JsonReader
|
||||
reader.JSN=com.eactive.eai.message.parser.JsonReader
|
||||
|
||||
@@ -0,0 +1,173 @@
|
||||
package com.eactive.eai.manage.inflow;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
|
||||
/**
|
||||
* InflowGroupMetricController 단위 테스트.
|
||||
*
|
||||
* <p>Spring MVC를 기동하지 않고 컨트롤러를 직접 인스턴스화하여
|
||||
* 응답 구조(success, data, count, message)를 검증한다.
|
||||
*/
|
||||
class InflowGroupMetricControllerTest {
|
||||
|
||||
private InflowGroupMetricController controller;
|
||||
private InflowGroupMetricService mockService;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
controller = new InflowGroupMetricController();
|
||||
mockService = mock(InflowGroupMetricService.class);
|
||||
ReflectionTestUtils.setField(controller, "metricService", mockService);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Helper
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
private GroupMetricDTO makeDTO(String groupId, String groupName,
|
||||
long allowed, long rejPs, long rejTh) {
|
||||
GroupMetricDTO dto = new GroupMetricDTO();
|
||||
dto.setGroupId(groupId);
|
||||
dto.setGroupName(groupName);
|
||||
dto.setActivate(true);
|
||||
dto.setAllowed(allowed);
|
||||
dto.setRejectedPerSecond(rejPs);
|
||||
dto.setRejectedThreshold(rejTh);
|
||||
long total = allowed + rejPs + rejTh;
|
||||
dto.setTotalRequests(total);
|
||||
dto.setRejectRatio(total > 0 ? (double)(rejPs + rejTh) / total * 100 : 0.0);
|
||||
dto.setLastResetTime(System.currentTimeMillis());
|
||||
return dto;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Map<String, Object> body(ResponseEntity<?> response) {
|
||||
return (Map<String, Object>) response.getBody();
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// GET /{groupId}/metric
|
||||
// =========================================================================
|
||||
|
||||
@Test
|
||||
void getGroupMetric_found_successTrueAndDataPresent() {
|
||||
GroupMetricDTO dto = makeDTO("G1", "결제그룹", 900, 60, 40);
|
||||
when(mockService.getGroupMetric("G1")).thenReturn(dto);
|
||||
|
||||
ResponseEntity<?> response = controller.getGroupMetric("G1");
|
||||
Map<String, Object> body = body(response);
|
||||
|
||||
assertEquals(200, response.getStatusCodeValue());
|
||||
assertEquals(Boolean.TRUE, body.get("success"));
|
||||
assertSame(dto, body.get("data"));
|
||||
assertFalse(body.containsKey("message"), "성공 응답에 message 필드는 없어야 합니다");
|
||||
}
|
||||
|
||||
@Test
|
||||
void getGroupMetric_notFound_successFalseWithMessage() {
|
||||
when(mockService.getGroupMetric("GHOST")).thenReturn(null);
|
||||
|
||||
ResponseEntity<?> response = controller.getGroupMetric("GHOST");
|
||||
Map<String, Object> body = body(response);
|
||||
|
||||
assertEquals(200, response.getStatusCodeValue());
|
||||
assertEquals(Boolean.FALSE, body.get("success"));
|
||||
assertTrue(body.get("message").toString().contains("GHOST"),
|
||||
"오류 메시지에 groupId가 포함되어야 합니다");
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// GET /metric
|
||||
// =========================================================================
|
||||
|
||||
@Test
|
||||
void getAllGroupMetrics_returnsListAndCount() {
|
||||
List<GroupMetricDTO> list = Arrays.asList(
|
||||
makeDTO("G1", "그룹1", 100, 5, 0),
|
||||
makeDTO("G2", "그룹2", 200, 0, 10)
|
||||
);
|
||||
when(mockService.getAllGroupMetrics()).thenReturn(list);
|
||||
|
||||
ResponseEntity<?> response = controller.getAllGroupMetrics();
|
||||
Map<String, Object> body = body(response);
|
||||
|
||||
assertEquals(Boolean.TRUE, body.get("success"));
|
||||
assertSame(list, body.get("data"));
|
||||
assertEquals(2, body.get("count"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void getAllGroupMetrics_emptyList_countZero() {
|
||||
when(mockService.getAllGroupMetrics()).thenReturn(Collections.emptyList());
|
||||
|
||||
ResponseEntity<?> response = controller.getAllGroupMetrics();
|
||||
Map<String, Object> body = body(response);
|
||||
|
||||
assertEquals(Boolean.TRUE, body.get("success"));
|
||||
assertEquals(0, body.get("count"));
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// POST /{groupId}/metric/reset
|
||||
// =========================================================================
|
||||
|
||||
@Test
|
||||
void resetGroupMetric_success_successTrueWithGroupId() {
|
||||
when(mockService.resetGroupMetric("G1")).thenReturn(true);
|
||||
|
||||
ResponseEntity<?> response = controller.resetGroupMetric("G1");
|
||||
Map<String, Object> body = body(response);
|
||||
|
||||
assertEquals(Boolean.TRUE, body.get("success"));
|
||||
assertTrue(body.get("message").toString().contains("G1"),
|
||||
"성공 메시지에 groupId가 포함되어야 합니다");
|
||||
}
|
||||
|
||||
@Test
|
||||
void resetGroupMetric_notFound_successFalseWithGroupId() {
|
||||
when(mockService.resetGroupMetric("GHOST")).thenReturn(false);
|
||||
|
||||
ResponseEntity<?> response = controller.resetGroupMetric("GHOST");
|
||||
Map<String, Object> body = body(response);
|
||||
|
||||
assertEquals(Boolean.FALSE, body.get("success"));
|
||||
assertTrue(body.get("message").toString().contains("GHOST"),
|
||||
"오류 메시지에 groupId가 포함되어야 합니다");
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// POST /metric/reset
|
||||
// =========================================================================
|
||||
|
||||
@Test
|
||||
void resetAllGroupMetrics_alwaysSuccessTrue() {
|
||||
doNothing().when(mockService).resetAllGroupMetrics();
|
||||
|
||||
ResponseEntity<?> response = controller.resetAllGroupMetrics();
|
||||
Map<String, Object> body = body(response);
|
||||
|
||||
assertEquals(Boolean.TRUE, body.get("success"));
|
||||
assertNotNull(body.get("message"));
|
||||
verify(mockService).resetAllGroupMetrics();
|
||||
}
|
||||
|
||||
@Test
|
||||
void resetAllGroupMetrics_callsDelegateOnce() {
|
||||
doNothing().when(mockService).resetAllGroupMetrics();
|
||||
|
||||
controller.resetAllGroupMetrics();
|
||||
|
||||
verify(mockService, times(1)).resetAllGroupMetrics();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,236 @@
|
||||
package com.eactive.eai.manage.inflow;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import com.eactive.eai.common.inflow.InflowGroupVO;
|
||||
import com.eactive.eai.common.inflow.dual.DualInflowControlManager;
|
||||
|
||||
/**
|
||||
* InflowGroupMetricService 단위 테스트.
|
||||
*
|
||||
* <p>getManager()를 protected로 오버라이드하는 내부 테스트 서브클래스를 사용하여
|
||||
* mockito-inline(static mock) 없이 DualInflowControlManager 의존성을 주입한다.
|
||||
*/
|
||||
class InflowGroupMetricServiceTest {
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// 테스트용 서브클래스 — getManager()를 오버라이드하여 mock 주입
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
private static InflowGroupMetricService serviceWith(DualInflowControlManager manager) {
|
||||
return new InflowGroupMetricService() {
|
||||
@Override
|
||||
protected DualInflowControlManager getManager() {
|
||||
return manager;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Helpers
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
private InflowGroupVO makeGroupVO(String groupId, String groupName) {
|
||||
InflowGroupVO vo = new InflowGroupVO();
|
||||
vo.setGroupId(groupId);
|
||||
vo.setGroupName(groupName);
|
||||
vo.setActivate(true);
|
||||
return vo;
|
||||
}
|
||||
|
||||
private DualInflowControlManager.TargetMetrics makeMetrics(long allowed, long rejPs, long rejTh) {
|
||||
DualInflowControlManager.TargetMetrics m = new DualInflowControlManager.TargetMetrics();
|
||||
m.allowed.set(allowed);
|
||||
m.rejectedPerSecond.set(rejPs);
|
||||
m.rejectedThreshold.set(rejTh);
|
||||
return m;
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// getGroupMetric
|
||||
// =========================================================================
|
||||
|
||||
@Test
|
||||
void getGroupMetric_managerIsNull_returnsNull() {
|
||||
assertNull(serviceWith(null).getGroupMetric("G1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void getGroupMetric_groupNotFound_returnsNull() {
|
||||
DualInflowControlManager manager = mock(DualInflowControlManager.class);
|
||||
when(manager.getGroupInflowThreshold("G1")).thenReturn(null);
|
||||
|
||||
assertNull(serviceWith(manager).getGroupMetric("G1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void getGroupMetric_noMetricsYet_returnsZeroCounters() {
|
||||
DualInflowControlManager manager = mock(DualInflowControlManager.class);
|
||||
when(manager.getGroupInflowThreshold("G1")).thenReturn(makeGroupVO("G1", "결제그룹"));
|
||||
when(manager.getGroupMetrics("G1")).thenReturn(null);
|
||||
|
||||
GroupMetricDTO dto = serviceWith(manager).getGroupMetric("G1");
|
||||
|
||||
assertNotNull(dto);
|
||||
assertEquals("G1", dto.getGroupId());
|
||||
assertEquals("결제그룹", dto.getGroupName());
|
||||
assertTrue(dto.isActivate());
|
||||
assertEquals(0, dto.getAllowed());
|
||||
assertEquals(0, dto.getRejectedPerSecond());
|
||||
assertEquals(0, dto.getRejectedThreshold());
|
||||
assertEquals(0, dto.getTotalRequests());
|
||||
assertEquals(0.0, dto.getRejectRatio());
|
||||
assertEquals(0, dto.getLastResetTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
void getGroupMetric_withMetrics_returnsCorrectValues() {
|
||||
DualInflowControlManager manager = mock(DualInflowControlManager.class);
|
||||
when(manager.getGroupInflowThreshold("G1")).thenReturn(makeGroupVO("G1", "결제그룹"));
|
||||
when(manager.getGroupMetrics("G1")).thenReturn(makeMetrics(900, 60, 40));
|
||||
|
||||
GroupMetricDTO dto = serviceWith(manager).getGroupMetric("G1");
|
||||
|
||||
assertEquals(900, dto.getAllowed());
|
||||
assertEquals(60, dto.getRejectedPerSecond());
|
||||
assertEquals(40, dto.getRejectedThreshold());
|
||||
assertEquals(1000, dto.getTotalRequests());
|
||||
}
|
||||
|
||||
@Test
|
||||
void getGroupMetric_rejectRatioCalculation() {
|
||||
DualInflowControlManager manager = mock(DualInflowControlManager.class);
|
||||
when(manager.getGroupInflowThreshold("G1")).thenReturn(makeGroupVO("G1", "G1"));
|
||||
// allowed=90, rejPs=5, rejTh=5 → reject=10/100 = 10.00%
|
||||
when(manager.getGroupMetrics("G1")).thenReturn(makeMetrics(90, 5, 5));
|
||||
|
||||
GroupMetricDTO dto = serviceWith(manager).getGroupMetric("G1");
|
||||
|
||||
assertEquals(10.0, dto.getRejectRatio(), 0.01);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getGroupMetric_zeroTotal_rejectRatioIsZero() {
|
||||
DualInflowControlManager manager = mock(DualInflowControlManager.class);
|
||||
when(manager.getGroupInflowThreshold("G1")).thenReturn(makeGroupVO("G1", "G1"));
|
||||
when(manager.getGroupMetrics("G1")).thenReturn(makeMetrics(0, 0, 0));
|
||||
|
||||
GroupMetricDTO dto = serviceWith(manager).getGroupMetric("G1");
|
||||
|
||||
assertEquals(0.0, dto.getRejectRatio(), 0.0001);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getGroupMetric_lastResetTimeIsPropagated() {
|
||||
DualInflowControlManager.TargetMetrics m = makeMetrics(10, 0, 0);
|
||||
m.lastResetTime = 1234567890L;
|
||||
|
||||
DualInflowControlManager manager = mock(DualInflowControlManager.class);
|
||||
when(manager.getGroupInflowThreshold("G1")).thenReturn(makeGroupVO("G1", "G1"));
|
||||
when(manager.getGroupMetrics("G1")).thenReturn(m);
|
||||
|
||||
GroupMetricDTO dto = serviceWith(manager).getGroupMetric("G1");
|
||||
|
||||
assertEquals(1234567890L, dto.getLastResetTime());
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// getAllGroupMetrics
|
||||
// =========================================================================
|
||||
|
||||
@Test
|
||||
void getAllGroupMetrics_managerIsNull_returnsEmptyList() {
|
||||
List<GroupMetricDTO> result = serviceWith(null).getAllGroupMetrics();
|
||||
|
||||
assertNotNull(result);
|
||||
assertTrue(result.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
void getAllGroupMetrics_noGroups_returnsEmptyList() {
|
||||
DualInflowControlManager manager = mock(DualInflowControlManager.class);
|
||||
when(manager.getGroupAllKeys()).thenReturn(new String[]{});
|
||||
|
||||
assertTrue(serviceWith(manager).getAllGroupMetrics().isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
void getAllGroupMetrics_twoGroups_returnsBoth() {
|
||||
DualInflowControlManager manager = mock(DualInflowControlManager.class);
|
||||
when(manager.getGroupAllKeys()).thenReturn(new String[]{"G1", "G2"});
|
||||
when(manager.getGroupInflowThreshold("G1")).thenReturn(makeGroupVO("G1", "그룹1"));
|
||||
when(manager.getGroupInflowThreshold("G2")).thenReturn(makeGroupVO("G2", "그룹2"));
|
||||
when(manager.getGroupMetrics("G1")).thenReturn(makeMetrics(10, 0, 0));
|
||||
when(manager.getGroupMetrics("G2")).thenReturn(makeMetrics(20, 5, 0));
|
||||
|
||||
List<GroupMetricDTO> result = serviceWith(manager).getAllGroupMetrics();
|
||||
|
||||
assertEquals(2, result.size());
|
||||
assertEquals("G1", result.get(0).getGroupId());
|
||||
assertEquals("G2", result.get(1).getGroupId());
|
||||
}
|
||||
|
||||
@Test
|
||||
void getAllGroupMetrics_groupNotFoundIsSkipped() {
|
||||
DualInflowControlManager manager = mock(DualInflowControlManager.class);
|
||||
when(manager.getGroupAllKeys()).thenReturn(new String[]{"G1", "GHOST"});
|
||||
when(manager.getGroupInflowThreshold("G1")).thenReturn(makeGroupVO("G1", "그룹1"));
|
||||
when(manager.getGroupInflowThreshold("GHOST")).thenReturn(null);
|
||||
when(manager.getGroupMetrics("G1")).thenReturn(makeMetrics(5, 0, 0));
|
||||
|
||||
List<GroupMetricDTO> result = serviceWith(manager).getAllGroupMetrics();
|
||||
|
||||
assertEquals(1, result.size());
|
||||
assertEquals("G1", result.get(0).getGroupId());
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// resetGroupMetric
|
||||
// =========================================================================
|
||||
|
||||
@Test
|
||||
void resetGroupMetric_managerIsNull_returnsFalse() {
|
||||
assertFalse(serviceWith(null).resetGroupMetric("G1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void resetGroupMetric_groupNotFound_returnsFalse() {
|
||||
DualInflowControlManager manager = mock(DualInflowControlManager.class);
|
||||
when(manager.getGroupInflowThreshold("G1")).thenReturn(null);
|
||||
|
||||
assertFalse(serviceWith(manager).resetGroupMetric("G1"));
|
||||
verify(manager, never()).resetGroupMetrics(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
void resetGroupMetric_success_returnsTrueAndCallsManager() {
|
||||
DualInflowControlManager manager = mock(DualInflowControlManager.class);
|
||||
when(manager.getGroupInflowThreshold("G1")).thenReturn(makeGroupVO("G1", "그룹1"));
|
||||
|
||||
assertTrue(serviceWith(manager).resetGroupMetric("G1"));
|
||||
verify(manager).resetGroupMetrics("G1");
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// resetAllGroupMetrics
|
||||
// =========================================================================
|
||||
|
||||
@Test
|
||||
void resetAllGroupMetrics_managerIsNull_noException() {
|
||||
assertDoesNotThrow(() -> serviceWith(null).resetAllGroupMetrics());
|
||||
}
|
||||
|
||||
@Test
|
||||
void resetAllGroupMetrics_callsManagerReset() {
|
||||
DualInflowControlManager manager = mock(DualInflowControlManager.class);
|
||||
|
||||
serviceWith(manager).resetAllGroupMetrics();
|
||||
|
||||
verify(manager).resetAllGroupMetrics();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user