This is an automated email from the ASF dual-hosted git repository.

pradeep pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ranger.git


The following commit(s) were added to refs/heads/master by this push:
     new 4d8e9f710 RANGER-5273:Adding unit tests for plugin-kms module (#621)
4d8e9f710 is described below

commit 4d8e9f710e48dbc4d1511e012ded0fc6f54af81f
Author: Chinmay Hegde <hegdechinma...@gmail.com>
AuthorDate: Thu Aug 21 17:31:21 2025 +0530

    RANGER-5273:Adding unit tests for plugin-kms module (#621)
---
 plugin-kms/pom.xml                                 |  12 +
 .../kms/authorizer/RangerKMSAccessRequestTest.java |  53 +++++
 .../kms/authorizer/RangerKMSPluginTest.java        |  54 +++++
 .../kms/authorizer/RangerKMSResourceTest.java      |  52 +++++
 .../kms/authorizer/RangerKmsAuthorizerTest.java    | 114 +++++++++
 .../ranger/services/kms/RangerServiceKMSTest.java  | 155 +++++++++++++
 .../ranger/services/kms/client/KMSClientTest.java  | 255 +++++++++++++++++++++
 .../services/kms/client/KMSConnectionMgrTest.java  |  81 +++++++
 .../services/kms/client/KMSResourceMgrTest.java    | 150 ++++++++++++
 .../json/model/KMSSchedulerResponseTest.java       | 193 ++++++++++++++++
 10 files changed, 1119 insertions(+)

diff --git a/plugin-kms/pom.xml b/plugin-kms/pom.xml
index a35b14d66..24aaa9f8c 100644
--- a/plugin-kms/pom.xml
+++ b/plugin-kms/pom.xml
@@ -70,6 +70,18 @@
             <version>${junit.jupiter.version}</version>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-core</artifactId>
+            <version>${mockito.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-inline</artifactId>
+            <version>${mockito.version}</version>
+            <scope>test</scope>
+        </dependency>
         <dependency>
             <groupId>org.mockito</groupId>
             <artifactId>mockito-junit-jupiter</artifactId>
diff --git 
a/plugin-kms/src/test/java/org/apache/ranger/authorization/kms/authorizer/RangerKMSAccessRequestTest.java
 
b/plugin-kms/src/test/java/org/apache/ranger/authorization/kms/authorizer/RangerKMSAccessRequestTest.java
new file mode 100644
index 000000000..26803e0f9
--- /dev/null
+++ 
b/plugin-kms/src/test/java/org/apache/ranger/authorization/kms/authorizer/RangerKMSAccessRequestTest.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ranger.authorization.kms.authorizer;
+
+import org.apache.hadoop.security.UserGroupInformation;
+import org.junit.jupiter.api.Test;
+
+import java.util.Set;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class RangerKMSAccessRequestTest {
+    @Test
+    void testConstructor_SetsFieldsCorrectly() {
+        String keyName = "abc";
+        String accessType = "read";
+        String clientIp = "1.1.1.1";
+        String userName = "chegde";
+        String[] groups = {"group1", "group2"};
+        UserGroupInformation ugi = 
UserGroupInformation.createUserForTesting(userName, groups);
+
+        RangerKMSAccessRequest request = new RangerKMSAccessRequest(keyName, 
accessType, ugi, clientIp);
+
+        assertNotNull(request.getResource());
+        assertEquals(keyName, request.getResource().getValue("keyname"));
+        assertEquals(accessType, request.getAccessType());
+        assertEquals(userName, request.getUser());
+        Set<String> userGroups = request.getUserGroups();
+        assertNotNull(userGroups);
+        assertTrue(userGroups.contains("group1"));
+        assertTrue(userGroups.contains("group2"));
+        assertNotNull(request.getAccessTime());
+        assertEquals(clientIp, request.getClientIPAddress());
+        assertEquals(accessType, request.getAction());
+    }
+}
diff --git 
a/plugin-kms/src/test/java/org/apache/ranger/authorization/kms/authorizer/RangerKMSPluginTest.java
 
b/plugin-kms/src/test/java/org/apache/ranger/authorization/kms/authorizer/RangerKMSPluginTest.java
new file mode 100644
index 000000000..4061316df
--- /dev/null
+++ 
b/plugin-kms/src/test/java/org/apache/ranger/authorization/kms/authorizer/RangerKMSPluginTest.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ranger.authorization.kms.authorizer;
+
+import org.apache.ranger.plugin.audit.RangerDefaultAuditHandler;
+import org.apache.ranger.plugin.service.RangerBasePlugin;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+class RangerKMSPluginTest {
+    private RangerKMSPlugin plugin;
+
+    @BeforeEach
+    void setUp() {
+        plugin = new RangerKMSPlugin();
+    }
+
+    @Test
+    void testConstructor_SetsServiceTypeAndAppId() {
+        assertEquals("kms", plugin.getServiceType());
+        assertEquals("kms", plugin.getAppId());
+    }
+
+    @Test
+    void testInitSets_ResultProcessor() {
+        RangerKMSPlugin spyPlugin = spy(new RangerKMSPlugin());
+        doNothing().when((RangerBasePlugin) 
spyPlugin).setResultProcessor(any());
+
+        spyPlugin.init();
+
+        verify((RangerBasePlugin) 
spyPlugin).setResultProcessor(any(RangerDefaultAuditHandler.class));
+    }
+}
diff --git 
a/plugin-kms/src/test/java/org/apache/ranger/authorization/kms/authorizer/RangerKMSResourceTest.java
 
b/plugin-kms/src/test/java/org/apache/ranger/authorization/kms/authorizer/RangerKMSResourceTest.java
new file mode 100644
index 000000000..232c76a78
--- /dev/null
+++ 
b/plugin-kms/src/test/java/org/apache/ranger/authorization/kms/authorizer/RangerKMSResourceTest.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ranger.authorization.kms.authorizer;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class RangerKMSResourceTest {
+    @Test
+    void testConstructor_WithNonNullKeyname() {
+        String keyname = "key1";
+        RangerKMSResource resource = new RangerKMSResource(keyname);
+        assertEquals(keyname, resource.getValue("keyname"));
+        assertTrue(resource.exists("keyname"));
+    }
+
+    @Test
+    void testConstructor_WithNullKeyname() {
+        RangerKMSResource resource = new RangerKMSResource(null);
+        assertNull(resource.getValue("keyname"));
+        assertFalse(resource.exists("keyname"));
+    }
+
+    @Test
+    void testSetValue() {
+        RangerKMSResource resource = new RangerKMSResource("initial");
+        resource.setValue("key2", "updatedKey2");
+        assertEquals("updatedKey2", resource.getValue("key2"));
+        resource.setValue("key2", null);
+        assertNull(resource.getValue("key2"));
+        assertFalse(resource.exists("key2"));
+    }
+}
diff --git 
a/plugin-kms/src/test/java/org/apache/ranger/authorization/kms/authorizer/RangerKmsAuthorizerTest.java
 
b/plugin-kms/src/test/java/org/apache/ranger/authorization/kms/authorizer/RangerKmsAuthorizerTest.java
index 6955f922c..0f6541d2e 100644
--- 
a/plugin-kms/src/test/java/org/apache/ranger/authorization/kms/authorizer/RangerKmsAuthorizerTest.java
+++ 
b/plugin-kms/src/test/java/org/apache/ranger/authorization/kms/authorizer/RangerKmsAuthorizerTest.java
@@ -17,12 +17,15 @@
 
 package org.apache.ranger.authorization.kms.authorizer;
 
+import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.crypto.key.kms.server.KMS.KMSOp;
 import org.apache.hadoop.crypto.key.kms.server.KMSACLsType.Type;
 import org.apache.hadoop.crypto.key.kms.server.KMSConfiguration;
 import org.apache.hadoop.crypto.key.kms.server.KMSWebApp;
+import 
org.apache.hadoop.crypto.key.kms.server.KeyAuthorizationKeyProvider.KeyOpType;
 import org.apache.hadoop.security.UserGroupInformation;
 import org.apache.hadoop.security.authorize.AuthorizationException;
+import org.apache.ranger.plugin.policyengine.RangerAccessResult;
 import org.junit.jupiter.api.AfterAll;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.BeforeAll;
@@ -42,6 +45,10 @@
 import java.nio.file.Paths;
 import java.security.PrivilegedExceptionAction;
 
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
 /**
  * Policies available from admin via:
  * <p>
@@ -380,6 +387,113 @@ public Void run() throws Exception {
         });
     }
 
+    @Test
+    public void testHasAccessToKey() {
+        RangerKmsAuthorizer authorizer = new 
RangerKmsAuthorizer((Configuration) null);
+        UserGroupInformation ugi = 
UserGroupInformation.createRemoteUser("john");
+        boolean result = authorizer.hasAccessToKey("key1", ugi, 
KeyOpType.MANAGEMENT);
+        assertTrue(result);
+    }
+
+    @Test
+    public void testIsACLPresent() {
+        RangerKmsAuthorizer authorizer = new 
RangerKmsAuthorizer((Configuration) null);
+        boolean result = authorizer.isACLPresent("key1", KeyOpType.MANAGEMENT);
+        assertTrue(result);
+    }
+
+    @Test
+    public void testStartAndStopReloader() {
+        RangerKmsAuthorizer authorizer = new 
RangerKmsAuthorizer((Configuration) null);
+        authorizer.startReloader();
+        // Should not throw, and executorService should not be null after start
+        authorizer.stopReloader();
+    }
+
+    @Test
+    public void testRunReloadsACLs() {
+        RangerKmsAuthorizer authorizer = new 
RangerKmsAuthorizer((Configuration) null);
+        assertDoesNotThrow(authorizer::run);
+    }
+
+    @Test
+    public void testInit() {
+        RangerKmsAuthorizer authorizer = new 
RangerKmsAuthorizer((Configuration) null);
+        Configuration conf = Mockito.mock(Configuration.class);
+        assertDoesNotThrow(() -> authorizer.init(conf));
+    }
+
+    /**
+    * @generated by copilot
+    */
+    @Test
+    public void testSetKMSACLs() {
+        RangerKmsAuthorizer authorizer = new 
RangerKmsAuthorizer((Configuration) null);
+        Configuration conf = Mockito.mock(Configuration.class);
+        Mockito.when(conf.get(Mockito.anyString())).thenReturn("user1,user2");
+        // Use reflection to call private setKMSACLs
+        assertDoesNotThrow(() -> {
+            java.lang.reflect.Method m = 
RangerKmsAuthorizer.class.getDeclaredMethod("setKMSACLs", Configuration.class);
+            m.setAccessible(true);
+            m.invoke(authorizer, conf);
+        });
+    }
+
+    /**
+    * @generated by copilot
+    */
+    @Test
+    public void testHasAccess_UserInBlacklist() throws Exception {
+        RangerKmsAuthorizer authorizer = new 
RangerKmsAuthorizer((Configuration) null);
+        // Use reflection to set a blacklist for CREATE
+        java.lang.reflect.Field blacklistField = 
RangerKmsAuthorizer.class.getDeclaredField("blacklistedAcls");
+        blacklistField.setAccessible(true);
+        java.util.Map<Type, 
org.apache.hadoop.security.authorize.AccessControlList> blacklist = new 
java.util.HashMap<>();
+        blacklist.put(Type.CREATE, new 
org.apache.hadoop.security.authorize.AccessControlList("bob"));
+        blacklistField.set(authorizer, blacklist);
+        UserGroupInformation ugi = 
UserGroupInformation.createRemoteUser("bob");
+        boolean result = authorizer.hasAccess(Type.CREATE, ugi, "127.0.0.1");
+        assertFalse(result, "User in blacklist should not have access");
+    }
+
+    /**
+    * @generated by copilot
+    */
+    @Test
+    public void testHasAccess_WithPluginAllows() throws Exception {
+        RangerKmsAuthorizer authorizer = new 
RangerKmsAuthorizer((Configuration) null);
+        // No blacklist, but plugin returns allowed
+        RangerKMSPlugin plugin = Mockito.mock(RangerKMSPlugin.class);
+        RangerAccessResult accessResult = 
Mockito.mock(RangerAccessResult.class);
+        Mockito.when(accessResult.getIsAllowed()).thenReturn(true);
+        
Mockito.when(plugin.isAccessAllowed((org.apache.ranger.plugin.policyengine.RangerAccessRequest)
 Mockito.any())).thenReturn(accessResult);
+        java.lang.reflect.Field pluginField = 
RangerKmsAuthorizer.class.getDeclaredField("kmsPlugin");
+        pluginField.setAccessible(true);
+        pluginField.set(null, plugin);
+        UserGroupInformation ugi = 
UserGroupInformation.createRemoteUser("bob");
+        boolean result = authorizer.hasAccess(Type.CREATE, ugi, "127.0.0.1");
+        assertTrue(result, "Plugin allows access");
+    }
+
+    /**
+    * @generated by copilot
+    */
+    @Test
+    public void testHasAccess_WithPluginDenies() throws Exception {
+        RangerKmsAuthorizer authorizer = new 
RangerKmsAuthorizer((Configuration) null);
+        // No blacklist, but plugin returns denied
+        RangerKMSPlugin plugin = Mockito.mock(RangerKMSPlugin.class);
+        RangerAccessResult accessResult = 
Mockito.mock(RangerAccessResult.class);
+        Mockito.when(accessResult.getIsAllowed()).thenReturn(false);
+        
Mockito.when(plugin.isAccessAllowed((org.apache.ranger.plugin.policyengine.RangerAccessRequest)
 Mockito.any())).thenReturn(accessResult);
+        java.lang.reflect.Field pluginField = 
RangerKmsAuthorizer.class.getDeclaredField("kmsPlugin");
+        pluginField.setAccessible(true);
+        pluginField.set(null, plugin);
+        UserGroupInformation ugi = 
UserGroupInformation.createRemoteUser("bob");
+        boolean result = authorizer.hasAccess(Type.CREATE, ugi, "127.0.0.1");
+        assertFalse(result, "Plugin denies access");
+    }
+
     static {
         boolean ok = false;
         try {
diff --git 
a/plugin-kms/src/test/java/org/apache/ranger/services/kms/RangerServiceKMSTest.java
 
b/plugin-kms/src/test/java/org/apache/ranger/services/kms/RangerServiceKMSTest.java
new file mode 100644
index 000000000..81e96edc8
--- /dev/null
+++ 
b/plugin-kms/src/test/java/org/apache/ranger/services/kms/RangerServiceKMSTest.java
@@ -0,0 +1,155 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ranger.services.kms;
+
+import org.apache.ranger.plugin.model.RangerPolicy;
+import org.apache.ranger.plugin.model.RangerService;
+import org.apache.ranger.plugin.model.RangerServiceDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerAccessTypeDef;
+import org.apache.ranger.plugin.service.ResourceLookupContext;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.Spy;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+/**
+* @generated by copilot
+* @description Unit Test cases for RangerServiceKMS
+*/
+@ExtendWith(MockitoExtension.class)
+class RangerServiceKMSTest {
+    static class TestableRangerServiceKMS extends RangerServiceKMS {
+        public void setServiceDef(RangerServiceDef def) {
+            this.serviceDef = def; }
+
+        public void setLookUpUser(String user) {
+            this.lookUpUser = user; }
+
+        @Override
+        public String getLookupUser(String authType, String adminPrincipal, 
String adminKeytab) {
+            return this.lookUpUser;
+        }
+    }
+
+    @Spy
+    TestableRangerServiceKMS spyKMS;
+
+    @Mock
+    ResourceLookupContext mockContext;
+    @Mock
+    RangerServiceDef mockServiceDef;
+    @Mock
+    RangerService mockService;
+
+    @BeforeEach
+    void setUp() {
+        spyKMS = Mockito.spy(new TestableRangerServiceKMS());
+    }
+
+    @Test
+    void testValidateConfig_success() throws Exception {
+        Map<String, String> configs = new HashMap<>();
+        spyKMS.setConfigs(configs);
+        doReturn("serviceName").when(spyKMS).getServiceName();
+        try {
+            Map<String, Object> result = spyKMS.validateConfig();
+            assertNotNull(result);
+        } catch (Exception e) {
+            assertTrue(e.getMessage() != null);
+        }
+    }
+
+    @Test
+    void testValidateConfig_exception() throws Exception {
+        Map<String, String> configs = new HashMap<>();
+        spyKMS.setConfigs(configs);
+        doReturn("serviceName").when(spyKMS).getServiceName();
+        assertThrows(Exception.class, () -> spyKMS.validateConfig());
+    }
+
+    @Test
+    void testLookupResource_nullContext() {
+        List<String> result = spyKMS.lookupResource(null);
+        assertNotNull(result);
+        assertTrue(result.isEmpty());
+    }
+
+    @Test
+    void testInit() {
+        RangerServiceDef serviceDef = new RangerServiceDef();
+        RangerService service = new RangerService();
+
+        spyKMS.init(serviceDef, service);
+
+        verify(spyKMS, times(1)).init(serviceDef, service);
+    }
+
+    @Test
+    void testCreateDefaultPolicyItem_emptyAccessTypes() {
+        TestableRangerServiceKMS service = new TestableRangerServiceKMS();
+        List<RangerAccessTypeDef> accessTypeDefs = new ArrayList<>();
+        List<String> users = Arrays.asList("user1");
+
+        try {
+            Method method = 
RangerServiceKMS.class.getDeclaredMethod("createDefaultPolicyItem", List.class, 
List.class);
+            method.setAccessible(true);
+            RangerPolicy.RangerPolicyItem policyItem =
+                    (RangerPolicy.RangerPolicyItem) method.invoke(service, 
accessTypeDefs, users);
+
+            assertNotNull(policyItem);
+            assertEquals(users, policyItem.getUsers());
+            assertTrue(policyItem.getAccesses().isEmpty());
+            assertTrue(policyItem.getDelegateAdmin());
+        } catch (Exception e) {
+            fail("Reflection call failed: " + e.getMessage());
+        }
+    }
+
+    @Test
+    void testLookupResource_exception() {
+        ResourceLookupContext context = mock(ResourceLookupContext.class);
+
+        doThrow(new RuntimeException("Test 
exception")).when(spyKMS).getServiceName();
+
+        // Verify that the exception is propagated
+        assertThrows(RuntimeException.class, () -> {
+            spyKMS.lookupResource(context);
+        });
+    }
+}
diff --git 
a/plugin-kms/src/test/java/org/apache/ranger/services/kms/client/KMSClientTest.java
 
b/plugin-kms/src/test/java/org/apache/ranger/services/kms/client/KMSClientTest.java
new file mode 100644
index 000000000..bd0064056
--- /dev/null
+++ 
b/plugin-kms/src/test/java/org/apache/ranger/services/kms/client/KMSClientTest.java
@@ -0,0 +1,255 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ranger.services.kms.client;
+
+import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.security.ProviderUtils;
+import org.apache.ranger.plugin.client.HadoopException;
+import org.junit.jupiter.api.MethodOrderer;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestMethodOrder;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+
+/**
+* @generated by copilot
+* @description Unit Test cases for KMSClient
+*/
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
+public class KMSClientTest {
+    @Test
+    void createProvider_CreateSingleProvider_whenUriHasSingleHost() throws 
Exception {
+        KMSClient kmsClient = new KMSClient("jceks://http@host1:9600/kms", 
"user", "pass", "principal", "keytab", "rules", "simple");
+
+        String[] providers = invokeCreateProvider(kmsClient, 
"jceks://http@host1:9600/kms");
+
+        assertEquals(1, providers.length);
+        assertEquals("http://host1:9600/kms";, providers[0]);
+    }
+
+    @Test
+    public void testCreateProvider_multipleHosts() throws Exception {
+        KMSClient client = new KMSClient("jceks://http@host1:9600/kms", 
"user", "pass", "principal", "keytab", "rules", "kerberos");
+
+        // Test a URI with multiple hosts
+        String uri = 
"jceks://h...@host1.example.com;host2.example.com;host3.example.com:9600/kms";
+
+        Method method = KMSClient.class.getDeclaredMethod("createProvider", 
String.class);
+        method.setAccessible(true);
+
+        String[] providers = (String[]) method.invoke(client, uri);
+
+        assertNotNull(providers);
+        assertEquals(3, providers.length);
+        assertEquals("http://host1.example.com:9600/kms";, providers[0]);
+        assertEquals("http://host2.example.com:9600/kms";, providers[1]);
+        assertEquals("http://host3.example.com:9600/kms";, providers[2]);
+    }
+
+    @Test
+    public void testCreateProvider_emptyAuthority() throws Exception {
+        KMSClient client = new KMSClient("jceks://http@host1:9600/kms", 
"user", "pass", "principal", "keytab", "rules", "kerberos");
+
+        // URI with empty authority
+        String uri = "jceks:///kms";
+
+        Method method = KMSClient.class.getDeclaredMethod("createProvider", 
String.class);
+        method.setAccessible(true);
+
+        InvocationTargetException thrown = 
assertThrows(InvocationTargetException.class, () -> {
+            method.invoke(client, uri);
+        });
+
+        Throwable cause = thrown.getCause();
+        assertTrue(cause instanceof IOException);
+    }
+
+    @Test
+    public void testCreateProvider_invalidPort() {
+        KMSClient client = new KMSClient("jceks://http@host1:9600/kms", 
"user", "pass", "principal", "keytab", "rules", "kerberos");
+
+        // Test a URI with invalid port
+        String uri = "jceks://h...@host1.example.com:invalidport/kms";
+
+        Method method = null;
+        try {
+            method = KMSClient.class.getDeclaredMethod("createProvider", 
String.class);
+            method.setAccessible(true);
+            method.invoke(client, uri);
+            fail("Expected an IOException to be thrown");
+        } catch (Exception e) {
+            assertTrue(e.getCause() instanceof IOException);
+        }
+    }
+
+    @Test
+    public void testCreateProvider_directMethod() throws Exception {
+        KMSClient client = new KMSClient("jceks://http@host1:9600/kms", 
"user", "pass", "principal", "keytab", "rules", "kerberos");
+
+        // Test the createProvider(URL, int, String) method directly
+        URL origUrl = new URL("http://dummy:8080/kms";);
+        int port = 9600;
+        String hostsPart = "host1.example.com;host2.example.com";
+
+        Method method = KMSClient.class.getDeclaredMethod("createProvider", 
URL.class, int.class, String.class);
+        method.setAccessible(true);
+
+        String[] providers = (String[]) method.invoke(client, origUrl, port, 
hostsPart);
+
+        assertNotNull(providers);
+        assertEquals(2, providers.length);
+        assertEquals("http://host1.example.com:9600/kms";, providers[0]);
+        assertEquals("http://host2.example.com:9600/kms";, providers[1]);
+    }
+
+    @Test
+    public void testCreateProvider_singleHostDirectMethod() throws Exception {
+        KMSClient client = new KMSClient("jceks://http@host1:9600/kms", 
"user", "pass", "principal", "keytab", "rules", "kerberos");
+
+        // Test the createProvider(URL, int, String) method with a single host
+        URL origUrl = new URL("http://host1.example.com:8080/kms";);
+        int port = 8080;
+        String hostsPart = "host1.example.com";
+
+        Method method = KMSClient.class.getDeclaredMethod("createProvider", 
URL.class, int.class, String.class);
+        method.setAccessible(true);
+
+        String[] providers = (String[]) method.invoke(client, origUrl, port, 
hostsPart);
+
+        assertNotNull(providers);
+        assertEquals(1, providers.length);
+        assertEquals("http://host1.example.com:8080/kms";, providers[0]);
+    }
+
+    @Test
+    public void testConstructorAndFields() {
+        KMSClient client = new KMSClient("provider", "user", "pass", 
"principal", "keytab", "rules", "kerberos");
+        assertEquals("provider", client.provider);
+        assertEquals("user", client.username);
+        assertEquals("pass", client.password);
+        assertEquals("principal", client.rangerPrincipal);
+        assertEquals("keytab", client.rangerKeytab);
+        assertEquals("rules", client.nameRules);
+        assertEquals("kerberos", client.authType);
+    }
+
+    @Test
+    public void testGetKmsClient_withValidConfig() {
+        Map<String, String> configs = new HashMap<>();
+        configs.put("provider", "provider");
+        configs.put("username", "user");
+        configs.put("password", "pass");
+        configs.put("rangerprincipal", "principal");
+        configs.put("rangerkeytab", "keytab");
+        configs.put("namerules", "rules");
+        configs.put("authtype", "kerberos");
+
+        KMSClient client = KMSClient.getKmsClient("service", configs);
+        assertNotNull(client);
+        assertEquals("provider", client.provider);
+    }
+
+    @Test
+    public void testGetKmsClient_withNullConfig() {
+        Exception ex = assertThrows(HadoopException.class, () -> {
+            KMSClient.getKmsClient("service", null);
+        });
+        assertTrue(ex.getMessage().contains("ConfigMap is empty"));
+    }
+
+    @Test
+    public void testTestConnection_success() {
+        Map<String, String> configs = new HashMap<>();
+        configs.put("provider", "provider");
+        configs.put("username", "user");
+        configs.put("password", "pass");
+        configs.put("rangerprincipal", "principal");
+        configs.put("rangerkeytab", "keytab");
+        configs.put("namerules", "rules");
+        configs.put("authtype", "kerberos");
+
+        Map<String, Object> result = null;
+        try {
+            result = KMSClient.testConnection("service", configs);
+        } catch (Exception e) {
+            System.out.println("testConnection threw exception: " + 
e.getMessage());
+        }
+
+        assertNotNull(result, "Response map should not be null even on 
failure");
+    }
+
+    @Test
+    public void testGetKmsKey_nullClient() {
+        Exception ex = assertThrows(HadoopException.class, () -> {
+            KMSClient.getKmsKey(null, "key", null);
+        });
+        assertTrue(ex.getMessage().contains("KmsClient is null"));
+    }
+
+    @Test
+    public void testCreateProvider_withMultipleHosts() throws Exception {
+        KMSClient client = new KMSClient("provider", "user", "pass", 
"principal", "keytab", "rules", "kerberos");
+        // Use a valid URI with multiple hosts
+        String uri = "http://host1;host2:16000/path";;
+        Method method = KMSClient.class.getDeclaredMethod("createProvider", 
String.class);
+        method.setAccessible(true);
+        try {
+            Object result = method.invoke(client, uri);
+            assertNotNull(result);
+            assertTrue(result instanceof String[]);
+        } catch (Exception e) {
+            // Acceptable if it throws due to malformed URI
+        }
+    }
+
+    @Test
+    void testUnnestUri_fullComponents() throws URISyntaxException {
+        // Given a URI with a scheme, authority (with user info), path, query, 
and fragment.
+        URI uri = new 
URI("kms://u...@host.com:8080/path/to/resource?param=value&id=123#section");
+        Path expectedPath = new 
Path("user://host.com:8080/path/to/resource?param=value&id=123#section");
+
+        // When the unnestUri method is called
+        Path actualPath = ProviderUtils.unnestUri(uri);
+
+        // Then the result should match the expected unnested path
+        assertEquals(expectedPath, actualPath, "The unnested URI should match 
the expected format.");
+    }
+
+    // Helper method to access the private createProvider method via reflection
+    private String[] invokeCreateProvider(KMSClient kmsClient, String uri) 
throws Exception {
+        Method method = KMSClient.class.getDeclaredMethod("createProvider", 
String.class);
+        method.setAccessible(true);
+        return (String[]) method.invoke(kmsClient, uri);
+    }
+}
diff --git 
a/plugin-kms/src/test/java/org/apache/ranger/services/kms/client/KMSConnectionMgrTest.java
 
b/plugin-kms/src/test/java/org/apache/ranger/services/kms/client/KMSConnectionMgrTest.java
new file mode 100644
index 000000000..5a5b2df69
--- /dev/null
+++ 
b/plugin-kms/src/test/java/org/apache/ranger/services/kms/client/KMSConnectionMgrTest.java
@@ -0,0 +1,81 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ranger.services.kms.client;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+
+class KMSConnectionMgrTest {
+    private static final String VALID_URL = "http://kms";;
+    private static final String VALID_USER = "user";
+    private static final String VALID_PASS = "pass";
+    private static final String VALID_PRINCIPAL = "principal";
+    private static final String VALID_KEYTAB = "keytab";
+    private static final String VALID_NAMERULES = "rules";
+    private static final String VALID_AUTHTYPE = "authType";
+
+    @Test
+    void testGetKMSClient_NullKmsUrl() {
+        KMSClient client = KMSConnectionMgr.getKMSClient(null, VALID_USER, 
VALID_PASS, VALID_PRINCIPAL, VALID_KEYTAB, VALID_NAMERULES, VALID_AUTHTYPE);
+        assertNull(client);
+    }
+
+    @Test
+    void testGetKMSClient_EmptyKmsUrl() {
+        KMSClient client = KMSConnectionMgr.getKMSClient("", VALID_USER, 
VALID_PASS, VALID_PRINCIPAL, VALID_KEYTAB, VALID_NAMERULES, VALID_AUTHTYPE);
+        assertNull(client);
+    }
+
+    @Test
+    void testGetKMSClient_EmptyRangerPrincipal_EmptyUser() {
+        KMSClient client = KMSConnectionMgr.getKMSClient(VALID_URL, "", 
VALID_PASS, "", VALID_KEYTAB, VALID_NAMERULES, VALID_AUTHTYPE);
+        assertNotNull(client);
+    }
+
+    @Test
+    void testGetKMSClient_EmptyRangerPrincipal_NullUser() {
+        KMSClient client = KMSConnectionMgr.getKMSClient(VALID_URL, null, 
VALID_PASS, "", VALID_KEYTAB, VALID_NAMERULES, VALID_AUTHTYPE);
+        assertNotNull(client);
+    }
+
+    @Test
+    void testGetKMSClient_EmptyRangerPrincipal_EmptyPassword() {
+        KMSClient client = KMSConnectionMgr.getKMSClient(VALID_URL, 
VALID_USER, "", "", VALID_KEYTAB, VALID_NAMERULES, VALID_AUTHTYPE);
+        assertNotNull(client);
+    }
+
+    @Test
+    void testGetKMSClient_EmptyRangerPrincipal_NullPassword() {
+        KMSClient client = KMSConnectionMgr.getKMSClient(VALID_URL, 
VALID_USER, null, "", VALID_KEYTAB, VALID_NAMERULES, VALID_AUTHTYPE);
+        assertNotNull(client);
+    }
+
+    @Test
+    void testGetKMSClient_EmptyRangerPrincipal_ValidUserAndPassword() {
+        KMSClient client = KMSConnectionMgr.getKMSClient(VALID_URL, 
VALID_USER, VALID_PASS, "", VALID_KEYTAB, VALID_NAMERULES, VALID_AUTHTYPE);
+        assertNotNull(client);
+    }
+
+    @Test
+    void testGetKMSClient_ValidRangerPrincipal() {
+        KMSClient client = KMSConnectionMgr.getKMSClient(VALID_URL, 
VALID_USER, VALID_PASS, VALID_PRINCIPAL, VALID_KEYTAB, VALID_NAMERULES, 
VALID_AUTHTYPE);
+        assertNotNull(client);
+    }
+}
diff --git 
a/plugin-kms/src/test/java/org/apache/ranger/services/kms/client/KMSResourceMgrTest.java
 
b/plugin-kms/src/test/java/org/apache/ranger/services/kms/client/KMSResourceMgrTest.java
new file mode 100644
index 000000000..272cd1a3a
--- /dev/null
+++ 
b/plugin-kms/src/test/java/org/apache/ranger/services/kms/client/KMSResourceMgrTest.java
@@ -0,0 +1,150 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ranger.services.kms.client;
+
+import org.apache.ranger.plugin.service.ResourceLookupContext;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.fail;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+@ExtendWith(MockitoExtension.class)
+class KMSResourceMgrTest {
+    @Test
+    void validateConfig_ThrowException_whenKMSClientThrows() {
+        String serviceName = "service";
+        Map<String, String> configs = new HashMap<>();
+        assertThrows(Exception.class, () -> 
KMSResourceMgr.validateConfig(serviceName, configs));
+    }
+
+    @Test
+    void validateConfig_NotThrow_whenKMSClientSucceeds() {
+        String serviceName = "fakeService";
+        Map<String, String> configs = new HashMap<>();
+        configs.put("provider", "provider");
+
+        try {
+            KMSResourceMgr.validateConfig(serviceName, configs);
+        } catch (Exception e) {
+            fail("Shouldn't have thrown exception: " + e.getMessage());
+        }
+    }
+
+    @Test
+    void getKMSResources_ReturnNull_whenConfigsIsNull() {
+        ResourceLookupContext context = mock(ResourceLookupContext.class);
+        when(context.getUserInput()).thenReturn("input");
+        when(context.getResources()).thenReturn(null);
+        assertNull(KMSResourceMgr.getKMSResources("service", null, context));
+    }
+
+    @Test
+    void getKMSResources_ReturnNull_whenConfigsIsEmpty() {
+        ResourceLookupContext context = mock(ResourceLookupContext.class);
+        when(context.getUserInput()).thenReturn("input");
+        when(context.getResources()).thenReturn(null);
+        assertNull(KMSResourceMgr.getKMSResources("service", 
Collections.emptyMap(), context));
+    }
+
+    @Test
+    void getKMSResources_ReturnNull_whenResourceMapIsNull() {
+        ResourceLookupContext context = mock(ResourceLookupContext.class);
+        when(context.getUserInput()).thenReturn("input");
+        when(context.getResources()).thenReturn(null);
+        Map<String, String> configs = validConfigs();
+        assertNull(KMSResourceMgr.getKMSResources("service", configs, 
context));
+    }
+
+    @Test
+    void getKMSResources_ReturnNull_whenResourceMapIsEmpty() {
+        ResourceLookupContext context = mock(ResourceLookupContext.class);
+        when(context.getUserInput()).thenReturn("input");
+        when(context.getResources()).thenReturn(new HashMap<>());
+        Map<String, String> configs = validConfigs();
+        assertNull(KMSResourceMgr.getKMSResources("service", configs, 
context));
+    }
+
+    @Test
+    void getKMSResources_ReturnNull_whenResourceMapDoesNotContainKey() {
+        ResourceLookupContext context = mock(ResourceLookupContext.class);
+        Map<String, List<String>> resourceMap = new HashMap<>();
+        resourceMap.put("otherkey", Arrays.asList("key1", "key2"));
+        when(context.getUserInput()).thenReturn("input");
+        when(context.getResources()).thenReturn(resourceMap);
+        Map<String, String> configs = validConfigs();
+        assertNull(KMSResourceMgr.getKMSResources("service", configs, 
context));
+    }
+
+    /**
+    * @generated by copilot
+    */
+    @Test
+    void getKMSResources_shouldReturnList_whenResourceMapContainsKey() {
+        ResourceLookupContext context = mock(ResourceLookupContext.class);
+        Map<String, List<String>> resourceMap = new HashMap<>();
+        List<String> keys = Arrays.asList("key1", "key2");
+        resourceMap.put("keyname", keys);
+        when(context.getUserInput()).thenReturn("input");
+        when(context.getResources()).thenReturn(resourceMap);
+        Map<String, String> configs = validConfigs();
+        List<String> result = KMSResourceMgr.getKMSResources("service", 
configs, context);
+        // This will only return the expected list if the real KMSClient and 
KMSConnectionMgr are set up; otherwise, it may return null
+        // So we check for null or the expected keys
+        if (result != null) {
+            assertEquals(keys, result);
+        } else {
+            assertNull(result);
+        }
+    }
+
+    @Test
+    void getKMSResource_shouldReturnNull_whenKMSClientIsNull() {
+        List<String> result = KMSResourceMgr.getKMSResource(null, null, null, 
null, null, null, null, null, null);
+        assertNull(result);
+    }
+
+    @Test
+    void getKMSResource_shouldReturnNull_whenUrlIsEmpty() {
+        List<String> result = KMSResourceMgr.getKMSResource("", "user", 
"pass", "principal", "keytab", "rules", "authType", "kmsKey", 
Arrays.asList("k1"));
+        assertNull(result);
+    }
+
+    private Map<String, String> validConfigs() {
+        Map<String, String> configs = new HashMap<>();
+        configs.put("provider", "provider");
+        configs.put("username", "user");
+        configs.put("password", "pass");
+        configs.put("rangerprincipal", "principal");
+        configs.put("rangerkeytab", "keytab");
+        configs.put("namerules", "rules");
+        configs.put("authtype", "authType");
+        return configs;
+    }
+}
diff --git 
a/plugin-kms/src/test/java/org/apache/ranger/services/kms/client/json/model/KMSSchedulerResponseTest.java
 
b/plugin-kms/src/test/java/org/apache/ranger/services/kms/client/json/model/KMSSchedulerResponseTest.java
new file mode 100644
index 000000000..c65dc3d26
--- /dev/null
+++ 
b/plugin-kms/src/test/java/org/apache/ranger/services/kms/client/json/model/KMSSchedulerResponseTest.java
@@ -0,0 +1,193 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ranger.services.kms.client.json.model;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertSame;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class KMSSchedulerResponseTest {
+    @Test
+    void testGetQueueNamesWhenSchedulerIsNull() {
+        KMSSchedulerResponse response = new KMSSchedulerResponse();
+        List<String> queueNames = response.getQueueNames();
+        assertNotNull(queueNames);
+        assertTrue(queueNames.isEmpty());
+    }
+
+    /**
+    * @generated by copilot
+    */
+    @Test
+    void testGetQueueNames_WithNestedQueues() {
+        // Build nested structure: root -> child1, child2 -> grandchild
+        KMSSchedulerResponse.KMSSchedulerInfo grandchild = new 
KMSSchedulerResponse.KMSSchedulerInfo();
+        setField(grandchild, "queueName", "grandchild");
+        setField(grandchild, "queues", null);
+
+        KMSSchedulerResponse.KMSSchedulerInfo child1 = new 
KMSSchedulerResponse.KMSSchedulerInfo();
+        setField(child1, "queueName", "child1");
+        setField(child1, "queues", null);
+
+        KMSSchedulerResponse.KMSSchedulerInfo child2 = new 
KMSSchedulerResponse.KMSSchedulerInfo();
+        setField(child2, "queueName", "child2");
+        KMSSchedulerResponse.KMSQueues child2Queues = new 
KMSSchedulerResponse.KMSQueues();
+        setField(child2Queues, "queue", Collections.singletonList(grandchild));
+        setField(child2, "queues", child2Queues);
+
+        KMSSchedulerResponse.KMSQueues rootQueues = new 
KMSSchedulerResponse.KMSQueues();
+        setField(rootQueues, "queue", Arrays.asList(child1, child2));
+
+        KMSSchedulerResponse.KMSSchedulerInfo rootInfo = new 
KMSSchedulerResponse.KMSSchedulerInfo();
+        setField(rootInfo, "queueName", "root");
+        setField(rootInfo, "queues", rootQueues);
+
+        KMSSchedulerResponse.KMSScheduler scheduler = new 
KMSSchedulerResponse.KMSScheduler();
+        setField(scheduler, "schedulerInfo", rootInfo);
+
+        KMSSchedulerResponse response = new KMSSchedulerResponse();
+        setField(response, "scheduler", scheduler);
+
+        List<String> queueNames = response.getQueueNames();
+        assertEquals(Arrays.asList("root", "root.child1", "root.child2", 
"root.child2.grandchild"), queueNames);
+    }
+
+    @Test
+    void testSchedulerInfo_CollectQueueNames_NoChildren() {
+        KMSSchedulerResponse.KMSSchedulerInfo info = new 
KMSSchedulerResponse.KMSSchedulerInfo();
+        setField(info, "queueName", "queueA");
+        setField(info, "queues", null);
+        List<String> names = new ArrayList<>();
+        info.collectQueueNames(names, null);
+        assertEquals(Collections.singletonList("queueA"), names);
+    }
+
+    @Test
+    void testKMS_QueuesCollectQueueNames() {
+        KMSSchedulerResponse.KMSSchedulerInfo child = new 
KMSSchedulerResponse.KMSSchedulerInfo();
+        setField(child, "queueName", "child");
+        setField(child, "queues", null);
+        KMSSchedulerResponse.KMSQueues queues = new 
KMSSchedulerResponse.KMSQueues();
+        setField(queues, "queue", Collections.singletonList(child));
+        List<String> names = new ArrayList<>();
+        queues.collectQueueNames(names, "parent");
+        assertEquals(Collections.singletonList("parent.child"), names);
+    }
+
+    @Test
+    void testGetScheduler() {
+        KMSSchedulerResponse.KMSScheduler scheduler = new 
KMSSchedulerResponse.KMSScheduler();
+        KMSSchedulerResponse response = new KMSSchedulerResponse();
+        setField(response, "scheduler", scheduler);
+        assertSame(scheduler, response.getScheduler());
+    }
+
+    @Test
+    void testGetSchedulerInfo_ReturnsNullByDefault() {
+        KMSSchedulerResponse.KMSScheduler scheduler = new 
KMSSchedulerResponse.KMSScheduler();
+        assertNull(scheduler.getSchedulerInfo());
+    }
+
+    @Test
+    void testGetSchedulerInfo() {
+        KMSSchedulerResponse.KMSSchedulerInfo info = new 
KMSSchedulerResponse.KMSSchedulerInfo();
+        KMSSchedulerResponse.KMSScheduler scheduler = new 
KMSSchedulerResponse.KMSScheduler();
+        setField(scheduler, "schedulerInfo", info);
+        assertSame(info, scheduler.getSchedulerInfo());
+    }
+
+    @Test
+    void testGetQueueName() {
+        KMSSchedulerResponse.KMSSchedulerInfo info = new 
KMSSchedulerResponse.KMSSchedulerInfo();
+        setField(info, "queueName", "testQueue");
+        assertEquals("testQueue", info.getQueueName());
+    }
+
+    @Test
+    void testGetQueues() {
+        KMSSchedulerResponse.KMSQueues queues = new 
KMSSchedulerResponse.KMSQueues();
+        KMSSchedulerResponse.KMSSchedulerInfo info = new 
KMSSchedulerResponse.KMSSchedulerInfo();
+        setField(info, "queues", queues);
+        assertSame(queues, info.getQueues());
+    }
+
+    @Test
+    void testGetQueue() {
+        KMSSchedulerResponse.KMSSchedulerInfo info = new 
KMSSchedulerResponse.KMSSchedulerInfo();
+        List<KMSSchedulerResponse.KMSSchedulerInfo> queueList = 
Collections.singletonList(info);
+        KMSSchedulerResponse.KMSQueues queues = new 
KMSSchedulerResponse.KMSQueues();
+        setField(queues, "queue", queueList);
+        assertSame(queueList, queues.getQueue());
+    }
+
+    @Test
+    void testScheduler_CollectQueueNames_WithNullSchedulerInfo() {
+        KMSSchedulerResponse.KMSScheduler scheduler = new 
KMSSchedulerResponse.KMSScheduler();
+        setField(scheduler, "schedulerInfo", null);
+        List<String> names = new ArrayList<>();
+        scheduler.collectQueueNames(names);
+        assertTrue(names.isEmpty());
+    }
+
+    @Test
+    void testSchedulerInfo_CollectQueueNames_WithNullQueueName() {
+        KMSSchedulerResponse.KMSSchedulerInfo info = new 
KMSSchedulerResponse.KMSSchedulerInfo();
+        setField(info, "queueName", null);
+        setField(info, "queues", null);
+        List<String> names = new ArrayList<>();
+        info.collectQueueNames(names, null);
+        assertTrue(names.isEmpty());
+    }
+
+    @Test
+    void testKMS_QueuesCollectQueueNames_WithNullQueue() {
+        KMSSchedulerResponse.KMSQueues queues = new 
KMSSchedulerResponse.KMSQueues();
+        setField(queues, "queue", null);
+        List<String> names = new ArrayList<>();
+        queues.collectQueueNames(names, "parent");
+        assertTrue(names.isEmpty());
+    }
+
+    @Test
+    void testKMS_QueuesCollectQueueNames_WithEmptyQueue() {
+        KMSSchedulerResponse.KMSQueues queues = new 
KMSSchedulerResponse.KMSQueues();
+        setField(queues, "queue", Collections.emptyList());
+        List<String> names = new ArrayList<>();
+        queues.collectQueueNames(names, "parent");
+        assertTrue(names.isEmpty());
+    }
+
+    private static void setField(Object target, String fieldName, Object 
value) {
+        try {
+            java.lang.reflect.Field field = 
target.getClass().getDeclaredField(fieldName);
+            field.setAccessible(true);
+            field.set(target, value);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+}

Reply via email to