package com.cloudhandson.ddsbackoffice.service; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import com.cloudhandson.ddsbackoffice.config.DdsProperties; import com.cloudhandson.ddsbackoffice.domain.DdsGrantInventoryEntry; import com.cloudhandson.ddsbackoffice.domain.DdsGrantInventorySnapshot; import com.cloudhandson.ddsbackoffice.domain.DdsGrantPlan; import com.cloudhandson.ddsbackoffice.domain.DdsProvisioningPlan; import java.time.Duration; import java.time.Instant; import java.util.List; import java.util.Map; import org.junit.jupiter.api.Test; class DdsProtectionStatusServiceTest { @Test void neverMarksAnUnavailableInventoryAsProtected() { DdsGrantInventory inventory = object -> new DdsGrantInventorySnapshot( false, List.of(), Instant.parse("2026-06-30T00:00:00Z"), "catalog 접근 실패" ); var service = new DdsProtectionStatusService(properties(), inventory, emptyPlanProvider()); var overview = service.overview(); assertEquals("확인 불가", overview.servicePath().primaryLabel()); assertEquals("확인 불가", overview.servicePath().observationLabel()); assertTrue(overview.servicePath().needsAction()); } @Test void separatesMissingTokenGrantFromDirectComparisonEvidence() { DdsGrantInventory inventory = object -> new DdsGrantInventorySnapshot( true, List.of(new DdsGrantInventoryEntry( "DDS_DEMO_BOTH_VECTOR_GRANT", "CB_DDS_VECTOR_SEARCH_DOCUMENTS", "DDS_DEMO_BOTH_ROLE")), Instant.parse("2026-06-30T00:00:00Z"), "" ); DdsProvisionPlanProvider provider = () -> new DdsProvisioningPlan(List.of(new DdsGrantPlan( "both", "통합 사용자", 103L, "dds_demo_both_role", "CB_VECTOR_SEARCH_DOCUMENTS", "ADMIN.CB_DDS_VECTOR_SEARCH_DOCUMENTS", "DDS_DEMO_BOTH_VECTOR_GRANT", "1 = 1", "", "CREATE DATA GRANT", true, "게시 가능" )), List.of(), 1); var service = new DdsProtectionStatusService(properties(), inventory, provider); var overview = service.overview(); assertEquals("조치 필요", overview.servicePath().primaryLabel()); assertEquals("반영 필요", overview.servicePath().synchronizationLabel()); var direct = service.directComparison(); assertEquals(1, direct.size()); assertEquals("재검증 필요", direct.getFirst().primaryLabel()); assertEquals("선언 관측", direct.getFirst().synchronizationLabel()); } @Test void reportsDirectGrantDriftWhenCurrentPlanHasNoGrantButInventoryDoes() { DdsGrantInventory inventory = object -> new DdsGrantInventorySnapshot( true, List.of(new DdsGrantInventoryEntry( "DDS_DEMO_BOTH_VECTOR_GRANT", "CB_DDS_VECTOR_SEARCH_DOCUMENTS", "DDS_DEMO_BOTH_ROLE")), Instant.parse("2026-06-30T00:00:00Z"), "" ); DdsProvisionPlanProvider provider = () -> new DdsProvisioningPlan(List.of(new DdsGrantPlan( "both", "통합 사용자", 103L, "dds_demo_both_role", "CB_VECTOR_SEARCH_DOCUMENTS", "ADMIN.CB_DDS_VECTOR_SEARCH_DOCUMENTS", "DDS_DEMO_BOTH_VECTOR_GRANT", "", "", "", false, "ALLOW 규칙 없음" )), List.of(), 1); var service = new DdsProtectionStatusService(properties(), inventory, provider); var direct = service.directComparison().getFirst(); assertEquals("조치 필요", direct.primaryLabel()); assertEquals("차이 발견", direct.synchronizationLabel()); } private static DdsProperties properties() { return new DdsProperties( "jdbc:test", Duration.ofSeconds(5), "ADMIN.V_DDS_CUSTOMERS_PG", "ADMIN.V_DDS_CUSTOMERS_MY", "ADMIN.CB_DDS_VECTOR_SEARCH_DOCUMENTS", Map.of("both", new DdsProperties.User( "통합 사용자", "직접 비교", "dds_demo_both", "secret", 103L, "dds_demo_both_role")), Map.of("CB_VECTOR_SEARCH_DOCUMENTS", "ADMIN.CB_DDS_VECTOR_SEARCH_DOCUMENTS"), new DdsProperties.Token("dds_demo_token", "secret", "cb_dds_token_role") ); } private static DdsProvisionPlanProvider emptyPlanProvider() { return () -> new DdsProvisioningPlan(List.of(), List.of(), 0); } }