You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ranger.apache.org by dh...@apache.org on 2025/07/23 11:47:09 UTC

(ranger) branch ds_RANGER-5238_ut created (now 718a766c1)

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

dhavalshah9131 pushed a change to branch ds_RANGER-5238_ut
in repository https://gitbox.apache.org/repos/asf/ranger.git


      at 718a766c1 RANGER-5238 : Adding test cases for the KMS module

This branch includes the following new commits:

     new 718a766c1 RANGER-5238 : Adding test cases for the KMS module

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



(ranger) 01/01: RANGER-5238 : Adding test cases for the KMS module

Posted by dh...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

dhavalshah9131 pushed a commit to branch ds_RANGER-5238_ut
in repository https://gitbox.apache.org/repos/asf/ranger.git

commit 718a766c1d68f18919e6b6bd75c5363e8e398e4a
Author: dhavalshah9131 <dh...@gmail.com>
AuthorDate: Wed Jul 23 17:15:24 2025 +0530

    RANGER-5238 : Adding test cases for the KMS module
---
 .../apache/hadoop/crypto/key/RangerKMSDBTest.java  | 487 ++++++++++
 .../hadoop/crypto/key/TestDBToKeySecure.java       | 131 +++
 .../apache/hadoop/crypto/key/TestHSM2DBMKUtil.java | 128 +++
 .../crypto/key/TestRangerAWSKMSProvider.java       | 235 +++++
 .../crypto/key/kms/RangerKeyStoreProviderTest.java | 990 +++++++++++++++++++++
 .../hadoop/crypto/key/kms/RangerMasterKeyTest.java | 305 +++++++
 .../kms/TestAzureKeyVaultClientAuthenticator.java  |  78 ++
 .../crypto/key/kms/TestDBToAzureKeyVault.java      | 218 +++++
 .../hadoop/crypto/key/kms/TestJKS2RangerUtil.java  | 197 ++++
 .../key/kms/TestKeySecureToRangerDBMKUtil.java     | 198 +++++
 .../crypto/key/kms/TestMigrateDBMKeyToGCP.java     | 113 +++
 .../hadoop/crypto/key/kms/TestRanger2JKSUtil.java  |  74 ++
 .../kms/TestRangerAzureKeyVaultKeyGenerator.java   | 392 ++++++++
 .../key/kms/TestRangerGoogleCloudHSMProvider.java  | 380 ++++++++
 .../hadoop/crypto/key/kms/TestRangerKeyStore.java  | 423 ++++++++-
 .../crypto/key/kms/TestRangerSafenetKeySecure.java | 139 +++
 .../crypto/key/kms/server/DerbyTestUtils.java      |   2 +-
 .../hadoop/crypto/key/kms/server/TestKMS.java      | 525 +++++++++++
 .../hadoop/crypto/key/kms/server/TestKMSACLs.java  |   2 +-
 .../hadoop/crypto/key/kms/server/TestKMSAudit.java |  15 +-
 .../key/kms/server/TestKMSExceptionsProvider.java  | 117 +++
 .../crypto/key/kms/server/TestKMSMDCFilter.java    |  87 ++
 .../key/kms/server/TestKMSServerJSONUtils.java     |  79 ++
 .../crypto/key/kms/server/TestKMSWebApp.java       | 446 ++++++++++
 .../server/TestKeyAuthorizationKeyProvider.java    |   8 +-
 .../key/kms/server/TestRangerJsonProvider.java     |  38 +
 .../org/apache/ranger/entity/TestXXDBBase.java     | 226 +++++
 .../apache/ranger/entity/TestXXRangerKeyStore.java |  40 +
 .../ranger/kms/biz/TestRangerKMSStartUp.java       |  33 +
 .../org/apache/ranger/kms/dao/TestBaseDao.java     |  94 ++
 .../kms/metrics/source/TestKMSMetricUtil.java      | 143 +++
 31 files changed, 6322 insertions(+), 21 deletions(-)

diff --git a/kms/src/test/java/org/apache/hadoop/crypto/key/RangerKMSDBTest.java b/kms/src/test/java/org/apache/hadoop/crypto/key/RangerKMSDBTest.java
new file mode 100644
index 000000000..b4bad9929
--- /dev/null
+++ b/kms/src/test/java/org/apache/hadoop/crypto/key/RangerKMSDBTest.java
@@ -0,0 +1,487 @@
+/*
+ * 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.hadoop.crypto.key;
+
+import org.apache.hadoop.conf.Configuration;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.nio.file.Files;
+import java.util.Map;
+import java.util.Properties;
+
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+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;
+
+@ExtendWith(MockitoExtension.class)
+public class RangerKMSDBTest {
+    private static final String PROPERTY_PREFIX                = "ranger.ks.";
+    private static final String DB_DIALECT                     = "jpa.jdbc.dialect";
+    private static final String DB_DRIVER                      = "jpa.jdbc.driver";
+    private static final String DB_URL                         = "jpa.jdbc.url";
+    private static final String DB_USER                        = "jpa.jdbc.user";
+    private static final String DB_PASSWORD                    = "jpa.jdbc.password";
+    private static final String DB_SSL_ENABLED                 = "db.ssl.enabled";
+    private static final String DB_SSL_REQUIRED                = "db.ssl.required";
+    private static final String DB_SSL_VerifyServerCertificate = "db.ssl.verifyServerCertificate";
+    private static final String DB_SSL_AUTH_TYPE               = "db.ssl.auth.type";
+    private static final String DB_SSL_KEYSTORE                = "keystore.file";
+    private static final String DB_SSL_KEYSTORE_PASSWORD       = "keystore.password";
+    private static final String DB_SSL_TRUSTSTORE              = "truststore.file";
+    private static final String DB_SSL_TRUSTSTORE_PASSWORD     = "truststore.password";
+    private static final String DB_SSL_CERTIFICATE_FILE        = "db.ssl.certificateFile";
+    private static final String JPA_DB_URL                     = "javax.persistence.jdbc.url";
+
+    private RangerKMSDB   rangerKMSDB;
+    private Configuration conf;
+    private Method        updateDBSSLURLMethod;
+    private Field         jpaPropertiesField;
+    private File          tempKeystore;
+    private File          tempTruststore;
+    private File          tempCertificate;
+    private Properties    originalSystemProperties;
+
+    @BeforeEach
+    public void setUp() throws Exception {
+        conf = new Configuration();
+
+        // Set basic database properties required for RangerKMSDB constructor
+        conf.set(PROPERTY_PREFIX + DB_DIALECT, "org.eclipse.persistence.platform.database.H2Platform");
+        conf.set(PROPERTY_PREFIX + DB_DRIVER, "org.h2.Driver");
+        conf.set(PROPERTY_PREFIX + DB_URL, "jdbc:h2:mem:testdb");
+        conf.set(PROPERTY_PREFIX + DB_USER, "test");
+        conf.set(PROPERTY_PREFIX + DB_PASSWORD, "test");
+
+        // Save original system properties
+        originalSystemProperties = new Properties();
+        originalSystemProperties.putAll(System.getProperties());
+
+        // Create temporary files for testing
+        createTempFiles();
+
+        // Get private method and field using reflection
+        updateDBSSLURLMethod = RangerKMSDB.class.getDeclaredMethod("updateDBSSLURL");
+        updateDBSSLURLMethod.setAccessible(true);
+
+        jpaPropertiesField = RangerKMSDB.class.getDeclaredField("jpaProperties");
+        jpaPropertiesField.setAccessible(true);
+    }
+
+    @AfterEach
+    public void tearDown() {
+        // Restore original system properties
+        System.setProperties(originalSystemProperties);
+
+        // Clean up temporary files
+        cleanupTempFiles();
+
+        if (rangerKMSDB != null) {
+            // Clean up any database connections if needed
+        }
+    }
+
+    @Test
+    public void testUpdateDBSSLURL_NullConfiguration() throws Exception {
+        Configuration nullConf = null;
+        rangerKMSDB = new RangerKMSDB(nullConf) {
+            @Override
+            public org.apache.ranger.kms.dao.DaoManager getDaoManager() {
+                return null;
+            }
+        };
+
+        // Should not throw exception
+        assertDoesNotThrow(() -> updateDBSSLURLMethod.invoke(rangerKMSDB));
+    }
+
+    @Test
+    public void testUpdateDBSSLURL_NoSSLEnabledProperty() throws Exception {
+        // Don't set DB_SSL_ENABLED property
+        createRangerKMSDBWithoutSSL();
+
+        String originalUrl = conf.get(PROPERTY_PREFIX + DB_URL);
+        updateDBSSLURLMethod.invoke(rangerKMSDB);
+
+        // URL should remain unchanged
+        assertEquals(originalUrl, conf.get(PROPERTY_PREFIX + DB_URL));
+    }
+
+    @Test
+    public void testUpdateDBSSLURL_MySQLSSLEnabled_NoQueryParams() throws Exception {
+        // Setup MySQL configuration
+        conf.set(PROPERTY_PREFIX + DB_DIALECT, "mysql");
+        conf.set(PROPERTY_PREFIX + DB_URL, "jdbc:mysql://localhost:3306/ranger");
+        conf.set(PROPERTY_PREFIX + DB_SSL_ENABLED, "true");
+        conf.set(PROPERTY_PREFIX + DB_SSL_REQUIRED, "true");
+        conf.set(PROPERTY_PREFIX + DB_SSL_VerifyServerCertificate, "true");
+
+        createRangerKMSDBWithoutSSL();
+        updateDBSSLURLMethod.invoke(rangerKMSDB);
+
+        String updatedUrl = conf.get(PROPERTY_PREFIX + DB_URL);
+        assertTrue(updatedUrl.contains("useSSL=true"));
+        assertTrue(updatedUrl.contains("requireSSL=true"));
+        assertTrue(updatedUrl.contains("verifyServerCertificate=true"));
+
+        @SuppressWarnings("unchecked")
+        Map<String, String> jpaProperties = (Map<String, String>) jpaPropertiesField.get(rangerKMSDB);
+        assertEquals(updatedUrl, jpaProperties.get(JPA_DB_URL));
+    }
+
+    @Test
+    public void testUpdateDBSSLURL_MySQLSSLEnabled_WithQueryParams() throws Exception {
+        // Setup MySQL configuration with existing query parameters
+        conf.set(PROPERTY_PREFIX + DB_DIALECT, "mysql");
+        conf.set(PROPERTY_PREFIX + DB_URL, "jdbc:mysql://localhost:3306/ranger?charset=utf8");
+        conf.set(PROPERTY_PREFIX + DB_SSL_ENABLED, "true");
+
+        createRangerKMSDBWithoutSSL();
+        updateDBSSLURLMethod.invoke(rangerKMSDB);
+
+        String updatedUrl = conf.get(PROPERTY_PREFIX + DB_URL);
+        // Should not modify URL if it already has query parameters
+        assertEquals("jdbc:mysql://localhost:3306/ranger?charset=utf8", updatedUrl);
+    }
+
+    @Test
+    public void testUpdateDBSSLURL_MySQLSSLDisabled() throws Exception {
+        // Setup MySQL configuration with SSL disabled
+        conf.set(PROPERTY_PREFIX + DB_DIALECT, "mysql");
+        conf.set(PROPERTY_PREFIX + DB_URL, "jdbc:mysql://localhost:3306/ranger");
+        conf.set(PROPERTY_PREFIX + DB_SSL_ENABLED, "false");
+
+        createRangerKMSDBWithoutSSL();
+        updateDBSSLURLMethod.invoke(rangerKMSDB);
+
+        String updatedUrl = conf.get(PROPERTY_PREFIX + DB_URL);
+        assertTrue(updatedUrl.contains("useSSL=false"));
+    }
+
+    @Test
+    public void testUpdateDBSSLURL_PostgreSQLSSLEnabled_WithCertificateFile() throws Exception {
+        // Setup PostgreSQL configuration
+        conf.set(PROPERTY_PREFIX + DB_DIALECT, "postgresql");
+        conf.set(PROPERTY_PREFIX + DB_URL, "jdbc:postgresql://localhost:5432/ranger");
+        conf.set(PROPERTY_PREFIX + DB_SSL_ENABLED, "true");
+        conf.set(PROPERTY_PREFIX + DB_SSL_CERTIFICATE_FILE, tempCertificate.getAbsolutePath());
+
+        createRangerKMSDBWithoutSSL();
+        updateDBSSLURLMethod.invoke(rangerKMSDB);
+
+        String updatedUrl = conf.get(PROPERTY_PREFIX + DB_URL);
+        assertTrue(updatedUrl.contains("ssl=true"));
+        assertTrue(updatedUrl.contains("sslmode=verify-full"));
+        assertTrue(updatedUrl.contains("sslrootcert=" + tempCertificate.getAbsolutePath()));
+    }
+
+    @Test
+    public void testUpdateDBSSLURL_PostgreSQLSSLEnabled_WithVerification_NoCertFile() throws Exception {
+        // Setup PostgreSQL configuration
+        conf.set(PROPERTY_PREFIX + DB_DIALECT, "postgresql");
+        conf.set(PROPERTY_PREFIX + DB_URL, "jdbc:postgresql://localhost:5432/ranger");
+        conf.set(PROPERTY_PREFIX + DB_SSL_ENABLED, "true");
+        conf.set(PROPERTY_PREFIX + DB_SSL_VerifyServerCertificate, "true");
+
+        createRangerKMSDBWithoutSSL();
+        updateDBSSLURLMethod.invoke(rangerKMSDB);
+
+        String updatedUrl = conf.get(PROPERTY_PREFIX + DB_URL);
+        assertTrue(updatedUrl.contains("ssl=true"));
+        assertTrue(updatedUrl.contains("sslmode=verify-full"));
+        assertTrue(updatedUrl.contains("sslfactory=org.postgresql.ssl.DefaultJavaSSLFactory"));
+    }
+
+    @Test
+    public void testUpdateDBSSLURL_PostgreSQLSSLEnabled_NoVerification() throws Exception {
+        // Setup PostgreSQL configuration
+        conf.set(PROPERTY_PREFIX + DB_DIALECT, "postgresql");
+        conf.set(PROPERTY_PREFIX + DB_URL, "jdbc:postgresql://localhost:5432/ranger");
+        conf.set(PROPERTY_PREFIX + DB_SSL_ENABLED, "true");
+        conf.set(PROPERTY_PREFIX + DB_SSL_VerifyServerCertificate, "false");
+        conf.set(PROPERTY_PREFIX + DB_SSL_REQUIRED, "false");
+
+        createRangerKMSDBWithoutSSL();
+        updateDBSSLURLMethod.invoke(rangerKMSDB);
+
+        String updatedUrl = conf.get(PROPERTY_PREFIX + DB_URL);
+        assertTrue(updatedUrl.contains("ssl=true"));
+        assertFalse(updatedUrl.contains("sslmode=verify-full"));
+    }
+
+    @Test
+    public void testUpdateDBSSLURL_PostgreSQLSSLDisabled() throws Exception {
+        // Setup PostgreSQL configuration with SSL disabled
+        conf.set(PROPERTY_PREFIX + DB_DIALECT, "postgresql");
+        conf.set(PROPERTY_PREFIX + DB_URL, "jdbc:postgresql://localhost:5432/ranger");
+        conf.set(PROPERTY_PREFIX + DB_SSL_ENABLED, "false");
+
+        createRangerKMSDBWithoutSSL();
+        String originalUrl = conf.get(PROPERTY_PREFIX + DB_URL);
+        updateDBSSLURLMethod.invoke(rangerKMSDB);
+
+        String updatedUrl = conf.get(PROPERTY_PREFIX + DB_URL);
+        // PostgreSQL URL should not be modified when SSL is disabled
+        assertEquals(originalUrl, updatedUrl);
+    }
+
+    @Test
+    public void testUpdateDBSSLURL_OracleDatabase() throws Exception {
+        // Setup Oracle configuration (should not modify URL)
+        conf.set(PROPERTY_PREFIX + DB_DIALECT, "oracle");
+        conf.set(PROPERTY_PREFIX + DB_URL, "jdbc:oracle:thin:@localhost:1521:ranger");
+        conf.set(PROPERTY_PREFIX + DB_SSL_ENABLED, "true");
+
+        createRangerKMSDBWithoutSSL();
+        String originalUrl = conf.get(PROPERTY_PREFIX + DB_URL);
+        updateDBSSLURLMethod.invoke(rangerKMSDB);
+
+        String updatedUrl = conf.get(PROPERTY_PREFIX + DB_URL);
+        // Oracle URL should not be modified
+        assertEquals(originalUrl, updatedUrl);
+    }
+
+    @Test
+    public void testUpdateDBSSLURL_KeystoreAndTruststoreSetup() throws Exception {
+        // Setup MySQL configuration with SSL verification and keystore/truststore
+        conf.set(PROPERTY_PREFIX + DB_DIALECT, "mysql");
+        conf.set(PROPERTY_PREFIX + DB_URL, "jdbc:mysql://localhost:3306/ranger");
+        conf.set(PROPERTY_PREFIX + DB_SSL_ENABLED, "true");
+        conf.set(PROPERTY_PREFIX + DB_SSL_REQUIRED, "true");
+        conf.set(PROPERTY_PREFIX + DB_SSL_VerifyServerCertificate, "true");
+        conf.set(PROPERTY_PREFIX + DB_SSL_AUTH_TYPE, "2-way");
+        conf.set(PROPERTY_PREFIX + DB_SSL_KEYSTORE, tempKeystore.getAbsolutePath());
+        conf.set(PROPERTY_PREFIX + DB_SSL_KEYSTORE_PASSWORD, "keystore-password");
+        conf.set(PROPERTY_PREFIX + DB_SSL_TRUSTSTORE, tempTruststore.getAbsolutePath());
+        conf.set(PROPERTY_PREFIX + DB_SSL_TRUSTSTORE_PASSWORD, "truststore-password");
+
+        createRangerKMSDBWithoutSSL();
+        updateDBSSLURLMethod.invoke(rangerKMSDB);
+
+        // Verify system properties are set
+        assertEquals(tempKeystore.getAbsolutePath(), System.getProperty("javax.net.ssl.keyStore"));
+        assertEquals("keystore-password", System.getProperty("javax.net.ssl.keyStorePassword"));
+        assertEquals(tempTruststore.getAbsolutePath(), System.getProperty("javax.net.ssl.trustStore"));
+        assertEquals("truststore-password", System.getProperty("javax.net.ssl.trustStorePassword"));
+    }
+
+    @Test
+    public void testUpdateDBSSLURL_OneWaySSL() throws Exception {
+        // Setup MySQL configuration with 1-way SSL (should not set keystore)
+        conf.set(PROPERTY_PREFIX + DB_DIALECT, "mysql");
+        conf.set(PROPERTY_PREFIX + DB_URL, "jdbc:mysql://localhost:3306/ranger");
+        conf.set(PROPERTY_PREFIX + DB_SSL_ENABLED, "true");
+        conf.set(PROPERTY_PREFIX + DB_SSL_REQUIRED, "true");
+        conf.set(PROPERTY_PREFIX + DB_SSL_VerifyServerCertificate, "true");
+        conf.set(PROPERTY_PREFIX + DB_SSL_AUTH_TYPE, "1-way");
+        conf.set(PROPERTY_PREFIX + DB_SSL_KEYSTORE, tempKeystore.getAbsolutePath());
+        conf.set(PROPERTY_PREFIX + DB_SSL_TRUSTSTORE, tempTruststore.getAbsolutePath());
+        conf.set(PROPERTY_PREFIX + DB_SSL_TRUSTSTORE_PASSWORD, "truststore-password");
+
+        createRangerKMSDBWithoutSSL();
+        updateDBSSLURLMethod.invoke(rangerKMSDB);
+
+        // Verify keystore is not set for 1-way SSL
+        assertNull(System.getProperty("javax.net.ssl.keyStore"));
+        // But truststore should still be set
+        assertEquals(tempTruststore.getAbsolutePath(), System.getProperty("javax.net.ssl.trustStore"));
+    }
+
+    @Test
+    public void testUpdateDBSSLURL_NonExistentKeystoreFile() throws Exception {
+        // Setup configuration with non-existent keystore file
+        conf.set(PROPERTY_PREFIX + DB_DIALECT, "mysql");
+        conf.set(PROPERTY_PREFIX + DB_URL, "jdbc:mysql://localhost:3306/ranger");
+        conf.set(PROPERTY_PREFIX + DB_SSL_ENABLED, "true");
+        conf.set(PROPERTY_PREFIX + DB_SSL_REQUIRED, "true");
+        conf.set(PROPERTY_PREFIX + DB_SSL_VerifyServerCertificate, "true");
+        conf.set(PROPERTY_PREFIX + DB_SSL_KEYSTORE, "/non/existent/keystore.jks");
+        conf.set(PROPERTY_PREFIX + DB_SSL_KEYSTORE_PASSWORD, "password");
+
+        createRangerKMSDBWithoutSSL();
+        updateDBSSLURLMethod.invoke(rangerKMSDB);
+
+        // Should not set system property for non-existent file
+        assertNull(System.getProperty("javax.net.ssl.keyStore"));
+    }
+
+    @Test
+    public void testUpdateDBSSLURL_EmptyKeystoreProperty() throws Exception {
+        // Setup configuration with empty keystore property
+        conf.set(PROPERTY_PREFIX + DB_DIALECT, "mysql");
+        conf.set(PROPERTY_PREFIX + DB_URL, "jdbc:mysql://localhost:3306/ranger");
+        conf.set(PROPERTY_PREFIX + DB_SSL_ENABLED, "true");
+        conf.set(PROPERTY_PREFIX + DB_SSL_REQUIRED, "true");
+        conf.set(PROPERTY_PREFIX + DB_SSL_VerifyServerCertificate, "true");
+        conf.set(PROPERTY_PREFIX + DB_SSL_KEYSTORE, "");
+
+        createRangerKMSDBWithoutSSL();
+        updateDBSSLURLMethod.invoke(rangerKMSDB);
+
+        // Should not set system property for empty keystore
+        assertNull(System.getProperty("javax.net.ssl.keyStore"));
+    }
+
+    @Test
+    public void testUpdateDBSSLURL_VariousBooleanValues() throws Exception {
+        // Test various boolean value formats
+        String[] trueValues  = {"true", "TRUE", "True"};
+        String[] falseValues = {"false", "FALSE", "False", "", null, "invalid"};
+
+        for (String trueValue : trueValues) {
+            conf = new Configuration();
+            conf.set(PROPERTY_PREFIX + DB_DIALECT, "mysql");
+            conf.set(PROPERTY_PREFIX + DB_URL, "jdbc:mysql://localhost:3306/ranger");
+            conf.set(PROPERTY_PREFIX + DB_SSL_ENABLED, trueValue);
+
+            createRangerKMSDBWithoutSSL();
+            updateDBSSLURLMethod.invoke(rangerKMSDB);
+
+            String updatedUrl = conf.get(PROPERTY_PREFIX + DB_URL);
+            assertTrue(updatedUrl.contains("useSSL=true"),
+                    "Failed for SSL enabled value: " + trueValue);
+        }
+
+        for (String falseValue : falseValues) {
+            conf = new Configuration();
+            conf.set(PROPERTY_PREFIX + DB_DIALECT, "mysql");
+            conf.set(PROPERTY_PREFIX + DB_URL, "jdbc:mysql://localhost:3306/ranger");
+            if (falseValue != null) {
+                conf.set(PROPERTY_PREFIX + DB_SSL_ENABLED, falseValue);
+            }
+
+            createRangerKMSDBWithoutSSL();
+            updateDBSSLURLMethod.invoke(rangerKMSDB);
+
+            String updatedUrl = conf.get(PROPERTY_PREFIX + DB_URL);
+            if (falseValue == null) {
+                assertFalse(updatedUrl.contains("useSSL"),
+                        "URL should not be modified when SSL property is null");
+            } else {
+                assertTrue(updatedUrl.contains("useSSL=false"),
+                        "Failed for SSL enabled value: " + falseValue);
+            }
+        }
+    }
+
+    @Test
+    public void testUpdateDBSSLURL_SQLServerDatabase() throws Exception {
+        // Test SQL Server (should not modify URL for SSL)
+        conf.set(PROPERTY_PREFIX + DB_DIALECT, "sqlserver");
+        conf.set(PROPERTY_PREFIX + DB_URL, "jdbc:sqlserver://localhost:1433;database=ranger");
+        conf.set(PROPERTY_PREFIX + DB_SSL_ENABLED, "true");
+
+        createRangerKMSDBWithoutSSL();
+        String originalUrl = conf.get(PROPERTY_PREFIX + DB_URL);
+        updateDBSSLURLMethod.invoke(rangerKMSDB);
+
+        String updatedUrl = conf.get(PROPERTY_PREFIX + DB_URL);
+        // SQL Server URL should not be modified
+        assertEquals(originalUrl, updatedUrl);
+    }
+
+    @Test
+    public void testUpdateDBSSLURL_PostgreSQLSSLRequired() throws Exception {
+        // Setup PostgreSQL configuration with SSL required
+        conf.set(PROPERTY_PREFIX + DB_DIALECT, "postgresql");
+        conf.set(PROPERTY_PREFIX + DB_URL, "jdbc:postgresql://localhost:5432/ranger");
+        conf.set(PROPERTY_PREFIX + DB_SSL_ENABLED, "true");
+        conf.set(PROPERTY_PREFIX + DB_SSL_REQUIRED, "true");
+
+        createRangerKMSDBWithoutSSL();
+        updateDBSSLURLMethod.invoke(rangerKMSDB);
+
+        String updatedUrl = conf.get(PROPERTY_PREFIX + DB_URL);
+        assertTrue(updatedUrl.contains("ssl=true"));
+        assertTrue(updatedUrl.contains("sslmode=verify-full"));
+        assertTrue(updatedUrl.contains("sslfactory=org.postgresql.ssl.DefaultJavaSSLFactory"));
+    }
+
+    @Test
+    public void testUpdateDBSSLURL_ComplexScenario() throws Exception {
+        // Test complex scenario with multiple properties set
+        conf.set(PROPERTY_PREFIX + DB_DIALECT, "mysql");
+        conf.set(PROPERTY_PREFIX + DB_URL, "jdbc:mysql://localhost:3306/ranger");
+        conf.set(PROPERTY_PREFIX + DB_SSL_ENABLED, "true");
+        conf.set(PROPERTY_PREFIX + DB_SSL_REQUIRED, "false");
+        conf.set(PROPERTY_PREFIX + DB_SSL_VerifyServerCertificate, "false");
+        conf.set(PROPERTY_PREFIX + DB_SSL_AUTH_TYPE, "2-way");
+        conf.set(PROPERTY_PREFIX + DB_SSL_KEYSTORE, tempKeystore.getAbsolutePath());
+        conf.set(PROPERTY_PREFIX + DB_SSL_KEYSTORE_PASSWORD, "keystore-pass");
+        conf.set(PROPERTY_PREFIX + DB_SSL_TRUSTSTORE, tempTruststore.getAbsolutePath());
+        conf.set(PROPERTY_PREFIX + DB_SSL_TRUSTSTORE_PASSWORD, "truststore-pass");
+
+        createRangerKMSDBWithoutSSL();
+        updateDBSSLURLMethod.invoke(rangerKMSDB);
+
+        String updatedUrl = conf.get(PROPERTY_PREFIX + DB_URL);
+        assertTrue(updatedUrl.contains("useSSL=true"));
+        assertTrue(updatedUrl.contains("requireSSL=false"));
+        assertTrue(updatedUrl.contains("verifyServerCertificate=false"));
+
+        // System properties should not be set when verification is false
+        assertNull(System.getProperty("javax.net.ssl.keyStore"));
+        assertNull(System.getProperty("javax.net.ssl.trustStore"));
+    }
+
+    private void createTempFiles() throws IOException {
+        tempKeystore    = File.createTempFile("test-keystore", ".jks");
+        tempTruststore  = File.createTempFile("test-truststore", ".jks");
+        tempCertificate = File.createTempFile("test-cert", ".pem");
+
+        // Write some dummy content to make files readable
+        Files.write(tempKeystore.toPath(), "dummy content".getBytes());
+        Files.write(tempTruststore.toPath(), "dummy content".getBytes());
+        Files.write(tempCertificate.toPath(), "dummy content".getBytes());
+    }
+
+    private void cleanupTempFiles() {
+        if (tempKeystore != null && tempKeystore.exists()) {
+            tempKeystore.delete();
+        }
+        if (tempTruststore != null && tempTruststore.exists()) {
+            tempTruststore.delete();
+        }
+        if (tempCertificate != null && tempCertificate.exists()) {
+            tempCertificate.delete();
+        }
+    }
+
+    private void createRangerKMSDBWithoutSSL() {
+        try {
+            rangerKMSDB = new RangerKMSDB(conf) {
+                // Override to prevent actual DB connection
+                @Override
+                public org.apache.ranger.kms.dao.DaoManager getDaoManager() {
+                    return null;
+                }
+            };
+        } catch (Exception e) {
+            // Expected for some tests where DB connection fails
+        }
+    }
+}
diff --git a/kms/src/test/java/org/apache/hadoop/crypto/key/TestDBToKeySecure.java b/kms/src/test/java/org/apache/hadoop/crypto/key/TestDBToKeySecure.java
new file mode 100644
index 000000000..a2a747c01
--- /dev/null
+++ b/kms/src/test/java/org/apache/hadoop/crypto/key/TestDBToKeySecure.java
@@ -0,0 +1,131 @@
+/*
+ * 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.hadoop.crypto.key;
+
+import org.apache.hadoop.conf.Configuration;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+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.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.security.Permission;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.fail;
+
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
+public class TestDBToKeySecure {
+    private static SecurityManager originalSecurityManager;
+
+    @BeforeAll
+    static void installExitInterceptor() {
+        originalSecurityManager = System.getSecurityManager();
+        System.setSecurityManager(new ExitInterceptingSecurityManager());
+    }
+
+    @AfterAll
+    static void restoreSecurityManager() {
+        System.setSecurityManager(originalSecurityManager);
+    }
+
+    @Test
+    public void testDoExportMKToKeySecure() throws NoSuchMethodException {
+        String        keyName       = "testKeyName";
+        String        username      = "testUser";
+        String        password      = "testPassword";
+        String        cfgFilePath   = "testConfigFilePath";
+        Configuration conf          = new Configuration();
+        DBToKeySecure dbToKeySecure = new DBToKeySecure();
+
+        Method method = DBToKeySecure.class.getDeclaredMethod("doExportMKToKeySecure",
+                String.class, String.class, String.class, String.class, Configuration.class);
+        method.setAccessible(true);
+        try {
+            method.invoke(dbToKeySecure, keyName, username, password, cfgFilePath, conf);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    @Test
+    void testMain_invalidArgs_shouldExit1() {
+        String[] args = new String[] {"only-one"};
+        SecurityException ex = assertThrows(SecurityException.class, () -> {
+            DBToKeySecure.main(args);
+        });
+
+        assertEquals(1, ExitInterceptingSecurityManager.getStatus());
+    }
+
+    @Test
+    void testMain_emptyKeyName_shouldExit1() {
+        String[] args = new String[] {"", "user", "pass", "path"};
+        SecurityException ex = assertThrows(SecurityException.class, () -> {
+            DBToKeySecure.main(args);
+        });
+
+        assertEquals(1, ExitInterceptingSecurityManager.getStatus());
+    }
+
+    @Test
+    void testMain_emptyKeyName_shouldExit3() {
+        String[] args = new String[] {"", "user", "pass", "path", "extraArg", "anotherArg"};
+        SecurityException ex = assertThrows(SecurityException.class, () -> {
+            DBToKeySecure.main(args);
+        });
+
+        assertEquals(1, ExitInterceptingSecurityManager.getStatus());
+    }
+
+    @Test
+    void testMain_exportSuccess_shouldExit0() {
+        String[] args = new String[] {"validKey", "user", "pass", "path"};
+        try {
+            Method mainMethod = DBToKeySecure.class.getDeclaredMethod("main", String[].class);
+            mainMethod.setAccessible(true);
+            InvocationTargetException ex = assertThrows(InvocationTargetException.class, () -> {
+                mainMethod.invoke(null, (Object) args);
+            });
+        } catch (Exception e) {
+            fail("Unexpected exception: " + e.getMessage());
+        }
+    }
+
+    static class ExitInterceptingSecurityManager extends SecurityManager {
+        private static int status;
+
+        public static int getStatus() {
+            return status;
+        }
+
+        @Override
+        public void checkPermission(Permission perm) {}
+
+        @Override
+        public void checkExit(int status) {
+            ExitInterceptingSecurityManager.status = status;
+            throw new SecurityException("Intercepted System.exit(" + status + ")");
+        }
+    }
+}
diff --git a/kms/src/test/java/org/apache/hadoop/crypto/key/TestHSM2DBMKUtil.java b/kms/src/test/java/org/apache/hadoop/crypto/key/TestHSM2DBMKUtil.java
new file mode 100644
index 000000000..926e2aad1
--- /dev/null
+++ b/kms/src/test/java/org/apache/hadoop/crypto/key/TestHSM2DBMKUtil.java
@@ -0,0 +1,128 @@
+/*
+ * 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.hadoop.crypto.key;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+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.ByteArrayOutputStream;
+import java.io.PrintStream;
+import java.lang.reflect.Method;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
+public class TestHSM2DBMKUtil {
+    private final PrintStream     originalOut             = System.out;
+    private final PrintStream     originalErr             = System.err;
+    private final SecurityManager originalSecurityManager = System.getSecurityManager();
+
+    private ByteArrayOutputStream outContent;
+    private ByteArrayOutputStream errContent;
+
+    @BeforeEach
+    public void setUp() {
+        outContent = new ByteArrayOutputStream();
+        errContent = new ByteArrayOutputStream();
+        System.setOut(new PrintStream(outContent));
+        System.setErr(new PrintStream(errContent));
+        System.setSecurityManager(new NoExitSecurityManager());
+    }
+
+    @AfterEach
+    public void tearDown() {
+        System.setOut(originalOut);
+        System.setErr(originalErr);
+        System.setSecurityManager(originalSecurityManager);
+    }
+
+    @Test
+    public void testMain_WithLessThan2Args_ShouldExit1() {
+        String[]             args = {"onlyOneArg"};
+        ExitTrappedException ex   = assertThrows(ExitTrappedException.class, () -> HSM2DBMKUtil.main(args));
+        assertEquals(1, ex.status);
+        assertTrue(errContent.toString().contains("Invalid number of parameters"));
+    }
+
+    @Test
+    public void testMain_WithEmptyHSMType_ShouldExit1() {
+        String[]             args = {"", "partition1"};
+        ExitTrappedException ex   = assertThrows(ExitTrappedException.class, () -> HSM2DBMKUtil.main(args));
+        assertEquals(1, ex.status);
+        assertTrue(errContent.toString().contains("HSM Type does not exists"));
+    }
+
+    @Test
+    public void testMain_WithEmptyPartition_ShouldExit1() {
+        String[]             args = {"HSMType", ""};
+        ExitTrappedException ex   = assertThrows(ExitTrappedException.class, () -> HSM2DBMKUtil.main(args));
+        assertEquals(1, ex.status);
+        assertTrue(errContent.toString().contains("Partition name does not exists"));
+    }
+
+    @Test
+    public void testShowUsage() {
+        HSM2DBMKUtil ranger2DBMKUtil = new HSM2DBMKUtil();
+        ranger2DBMKUtil.getClass();
+        HSM2DBMKUtil.showUsage();
+    }
+
+    @Test
+    public void testDoExportMKToDB() throws NoSuchMethodException {
+        HSM2DBMKUtil ranger2DBMKUtil = new HSM2DBMKUtil();
+        String[]     args            = {"-jks", "test.jks", "-out", "output.txt"};
+
+        Method method = HSM2DBMKUtil.class.getDeclaredMethod(
+                "doImportMKFromHSM", String.class, String.class);
+        method.setAccessible(true);
+
+        try {
+            method.invoke(ranger2DBMKUtil, args[1], args[3]);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    static class ExitTrappedException extends SecurityException {
+        final int status;
+
+        ExitTrappedException(int status) {
+            super("System.exit(" + status + ") called");
+            this.status = status;
+        }
+    }
+
+    private static class NoExitSecurityManager extends SecurityManager {
+        @Override
+        public void checkPermission(java.security.Permission perm) {
+            // Allow all
+        }
+
+        @Override
+        public void checkExit(int status) {
+            throw new ExitTrappedException(status);
+        }
+    }
+}
diff --git a/kms/src/test/java/org/apache/hadoop/crypto/key/TestRangerAWSKMSProvider.java b/kms/src/test/java/org/apache/hadoop/crypto/key/TestRangerAWSKMSProvider.java
new file mode 100644
index 000000000..3c31e3be4
--- /dev/null
+++ b/kms/src/test/java/org/apache/hadoop/crypto/key/TestRangerAWSKMSProvider.java
@@ -0,0 +1,235 @@
+/*
+ * 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.hadoop.crypto.key;
+
+import com.amazonaws.services.kms.AWSKMS;
+import com.amazonaws.services.kms.model.AliasListEntry;
+import com.amazonaws.services.kms.model.DecryptRequest;
+import com.amazonaws.services.kms.model.DecryptResult;
+import com.amazonaws.services.kms.model.DescribeKeyRequest;
+import com.amazonaws.services.kms.model.DescribeKeyResult;
+import com.amazonaws.services.kms.model.EncryptRequest;
+import com.amazonaws.services.kms.model.EncryptResult;
+import com.amazonaws.services.kms.model.KeyMetadata;
+import com.amazonaws.services.kms.model.ListAliasesRequest;
+import com.amazonaws.services.kms.model.ListAliasesResult;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.crypto.key.kms.server.KMSConfiguration;
+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.Mockito;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import javax.crypto.spec.SecretKeySpec;
+
+import java.lang.reflect.Field;
+import java.nio.ByteBuffer;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.security.Key;
+
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
+public class TestRangerAWSKMSProvider {
+    @Test
+    public void testCreateKMSClient() throws Exception {
+        Path configDir = Paths.get("src/test/resources/kms");
+        System.setProperty(KMSConfiguration.KMS_CONFIG_DIR, configDir.toFile().getAbsolutePath());
+        Configuration conf = new Configuration();
+        conf.set("ranger.kms.awskms.masterkey.id", "your-master-key-id");
+        conf.set("ranger.kms.aws.client.accesskey", "your-access-key");
+        conf.set("ranger.kms.aws.client.secretkey", "your-secret-key");
+        conf.set("ranger.kms.aws.client.region", "us-west-2");
+
+        AWSKMS               client      = RangerAWSKMSProvider.createKMSClient(conf);
+        RangerAWSKMSProvider kmsProvider = new RangerAWSKMSProvider(conf, client);
+
+        RangerAWSKMSProvider.createKMSClient(conf);
+    }
+
+    @Test
+    public void testGetMasterKey() throws Exception {
+        Path configDir = Paths.get("src/test/resources/kms");
+        System.setProperty(KMSConfiguration.KMS_CONFIG_DIR, configDir.toFile().getAbsolutePath());
+        Configuration conf = new Configuration();
+        conf.set("ranger.kms.awskms.masterkey.id", "your-master-key-id");
+        conf.set("ranger.kms.aws.client.accesskey", "your-access-key");
+        conf.set("ranger.kms.aws.client.secretkey", "your-secret-key");
+        conf.set("ranger.kms.aws.client.region", "us-west-2");
+
+        RangerAWSKMSProvider kmsProvider         = new RangerAWSKMSProvider(conf);
+        String               masterKeySecretName = conf.get("ranger.kms.awskms.masterkey.id");
+        kmsProvider.getMasterKey(masterKeySecretName);
+    }
+
+    @Test
+    void testDecryptZoneKey_happyPath() throws Exception {
+        /* ---------- 1.  Test data --------------------------------------------------- */
+        byte[] ciphertext    = {0, 1, 2, 3, 4};
+        byte[] expectedPlain = {10, 11, 12};
+
+        /* ---------- 2.  Stub AWSKMS.decrypt(...) ------------------------------------ */
+        AWSKMS kmsMock = mock(AWSKMS.class);
+        DecryptResult decryptResult = new DecryptResult()
+                .withPlaintext(ByteBuffer.wrap(expectedPlain));
+        when(kmsMock.decrypt(Mockito.any(DecryptRequest.class)))
+                .thenReturn(decryptResult);
+
+        Path configDir = Paths.get("src/test/resources/kms");
+        System.setProperty(KMSConfiguration.KMS_CONFIG_DIR, configDir.toFile().getAbsolutePath());
+
+        /* ---------- 3.  Build provider with regular ctor --------------------------- */
+        Configuration conf = new Configuration();
+        conf.set("ranger.kms.awskms.masterkey.id", "your-master-key-id");
+        conf.set("ranger.kms.aws.client.accesskey", "your-access-key");
+        conf.set("ranger.kms.aws.client.secretkey", "your-secret-key");
+        conf.set("ranger.kms.aws.client.region", "us-west-2");
+        RangerAWSKMSProvider provider = new RangerAWSKMSProvider(conf);
+
+        /* ---------- 4.  Inject mock client via reflection -------------------------- */
+        Field clientField = null;
+        for (Field f : RangerAWSKMSProvider.class.getDeclaredFields()) {
+            if (AWSKMS.class.isAssignableFrom(f.getType())) {
+                clientField = f;
+                break;
+            }
+        }
+        assertNotNull(clientField, "AWSKMS client field not found!");
+        clientField.setAccessible(true);
+        clientField.set(provider, kmsMock);
+
+        /* ---------- 5.  Call and assert -------------------------------------------- */
+        byte[] actualPlain = provider.decryptZoneKey(ciphertext);
+        assertArrayEquals(expectedPlain, actualPlain,
+                "Returned plaintext must match stubbed value");
+
+        /* ---------- 6.  Verify interaction ----------------------------------------- */
+        verify(kmsMock, times(1))
+                .decrypt(Mockito.any(DecryptRequest.class));
+    }
+
+    @Test
+    void testEncryptZoneKey_happyPath() throws Exception {
+        /* ---------- 1. Test data -------------------------------------------------- */
+        byte[] plainBytes     = {10, 11, 12, 13, 14, 15};
+        Key    zoneKey        = new SecretKeySpec(plainBytes, "AES");
+        byte[] expectedCipher = {1, 2, 3, 4};
+
+        /* ---------- 2. Stub AWSKMS.encrypt(...) ---------------------------------- */
+        AWSKMS kmsMock = mock(AWSKMS.class);
+        EncryptResult encrypted = new EncryptResult()
+                .withCiphertextBlob(ByteBuffer.wrap(expectedCipher));
+        when(kmsMock.encrypt(any(EncryptRequest.class))).thenReturn(encrypted);
+
+        Path configDir = Paths.get("src/test/resources/kms");
+        System.setProperty(KMSConfiguration.KMS_CONFIG_DIR, configDir.toFile().getAbsolutePath());
+
+        /* ---------- 3. Build provider & inject mock client ----------------------- */
+        Configuration conf = new Configuration();
+        conf.set("ranger.kms.awskms.masterkey.id", "your-master-key-id");
+        conf.set("ranger.kms.aws.client.accesskey", "your-access-key");
+        conf.set("ranger.kms.aws.client.secretkey", "your-secret-key");
+        conf.set("ranger.kms.aws.client.region", "us-west-2");
+        RangerAWSKMSProvider provider = new RangerAWSKMSProvider(conf);
+
+        Field clientField = null;
+        for (Field f : RangerAWSKMSProvider.class.getDeclaredFields()) {
+            if (AWSKMS.class.isAssignableFrom(f.getType())) {
+                clientField = f;
+                break;
+            }
+        }
+        assertNotNull(clientField, "AWSKMS client field not found");
+        clientField.setAccessible(true);
+        clientField.set(provider, kmsMock);
+
+        /* ---------- 4. Call encryptZoneKey(...) ---------------------------------- */
+        byte[] actualCipher = provider.encryptZoneKey(zoneKey);
+
+        /* ---------- 5. Assertions & verifications -------------------------------- */
+        assertArrayEquals(expectedCipher, actualCipher,
+                "Returned ciphertext must match stubbed value");
+        verify(kmsMock, times(1)).encrypt(any(EncryptRequest.class));
+    }
+
+    @Test
+    void testGenerateMasterKey_success() throws Exception {
+        // Dummy inputs and expected values
+        String password    = "testPassword";
+        String masterKeyId = "your-master-key-id";
+
+        // 1. Stub DescribeKey → returns DescribeKeyResult with KeyMetadata
+        KeyMetadata keyMetadata = new KeyMetadata()
+                .withKeyId(masterKeyId)
+                .withArn("dummy-arn")
+                .withDescription("test key");
+        DescribeKeyResult describeKeyResult = new DescribeKeyResult()
+                .withKeyMetadata(keyMetadata);
+
+        // 2. Stub ListAliases → returns alias that matches masterKeyId
+        AliasListEntry aliasEntry = new AliasListEntry()
+                .withAliasName(masterKeyId)
+                .withTargetKeyId(masterKeyId);
+        ListAliasesResult aliasesResult = new ListAliasesResult()
+                .withAliases(aliasEntry);
+
+        // 3. Mock AWSKMS client
+        AWSKMS kmsMock = mock(AWSKMS.class);
+        when(kmsMock.describeKey(any(DescribeKeyRequest.class))).thenReturn(describeKeyResult);
+        when(kmsMock.listAliases(any(ListAliasesRequest.class))).thenReturn(aliasesResult);
+
+        // 4. Prepare configuration and inject mocked client
+        Configuration conf = new Configuration(false);
+        conf.set("ranger.kms.awskms.masterkey.id", masterKeyId);
+        conf.set("ranger.kms.aws.client.accesskey", "dummy-access-key");
+        conf.set("ranger.kms.aws.client.secretkey", "dummy-secret-key");
+        conf.set("ranger.kms.aws.client.region", "us-west-2");
+
+        RangerAWSKMSProvider provider = new RangerAWSKMSProvider(conf);
+
+        // Inject the mocked AWSKMS client into provider
+        Field clientField = null;
+        for (Field f : RangerAWSKMSProvider.class.getDeclaredFields()) {
+            if (AWSKMS.class.isAssignableFrom(f.getType())) {
+                clientField = f;
+                break;
+            }
+        }
+        assertNotNull(clientField, "AWSKMS client field not found");
+        clientField.setAccessible(true);
+        clientField.set(provider, kmsMock);
+
+        // 5. Call generateMasterKey and assert result
+        boolean result = provider.generateMasterKey(password);
+        assertTrue(result, "Expected generateMasterKey to return true");
+
+        // 6. Verify calls
+        verify(kmsMock, times(1)).describeKey(any(DescribeKeyRequest.class));
+        verify(kmsMock, times(1)).listAliases(any(ListAliasesRequest.class));
+    }
+}
diff --git a/kms/src/test/java/org/apache/hadoop/crypto/key/kms/RangerKeyStoreProviderTest.java b/kms/src/test/java/org/apache/hadoop/crypto/key/kms/RangerKeyStoreProviderTest.java
new file mode 100644
index 000000000..e5aefd2de
--- /dev/null
+++ b/kms/src/test/java/org/apache/hadoop/crypto/key/kms/RangerKeyStoreProviderTest.java
@@ -0,0 +1,990 @@
+/*
+ * 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.hadoop.crypto.key.kms;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.crypto.key.KeyProvider;
+import org.apache.hadoop.crypto.key.KeyProvider.KeyVersion;
+import org.apache.hadoop.crypto.key.KeyProvider.Options;
+import org.apache.hadoop.crypto.key.RangerKMSMKI;
+import org.apache.hadoop.crypto.key.RangerKeyStore;
+import org.apache.hadoop.crypto.key.RangerKeyStoreProvider;
+import org.apache.hadoop.crypto.key.kms.server.DerbyTestUtils;
+import org.apache.hadoop.crypto.key.kms.server.KMSConfiguration;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import javax.crypto.Cipher;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.SecretKeySpec;
+
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.CertificateException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
+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.any;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.isNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+/**
+ * A test for the RangerKeyStoreProvider, which is an implementation of the Hadoop KeyProvider interface, which stores keys in a database.
+ * Apache Derby is used to create the relevant tables to store the keys in for this test.
+ */
+public class RangerKeyStoreProviderTest {
+    private static final boolean UNRESTRICTED_POLICIES_INSTALLED;
+
+    @BeforeAll
+    public static void startServers() throws Exception {
+        if (!UNRESTRICTED_POLICIES_INSTALLED) {
+            return;
+        }
+        DerbyTestUtils.startDerby();
+    }
+
+    @AfterAll
+    public static void stopServers() throws Exception {
+        if (UNRESTRICTED_POLICIES_INSTALLED) {
+            DerbyTestUtils.stopDerby();
+        }
+    }
+
+    @BeforeEach
+    public void cleanUpKeyBeforeEachTest() throws Throwable {
+        if (!UNRESTRICTED_POLICIES_INSTALLED) {
+            return;
+        }
+        Path configDir = Paths.get("src/test/resources/kms");
+        System.setProperty(KMSConfiguration.KMS_CONFIG_DIR, configDir.toFile().getAbsolutePath());
+
+        Configuration          conf        = new Configuration();
+        RangerKeyStoreProvider keyProvider = new RangerKeyStoreProvider(conf);
+
+        try {
+            keyProvider.deleteKey("newkey1");
+            keyProvider.flush();
+        } catch (IOException e) {
+            // Ignore if the key doesn't exist yet
+        }
+    }
+
+    @Test
+    public void testCreateDeleteKey() throws Throwable {
+        if (!UNRESTRICTED_POLICIES_INSTALLED) {
+            return;
+        }
+
+        Path configDir = Paths.get("src/test/resources/kms");
+        System.setProperty(KMSConfiguration.KMS_CONFIG_DIR, configDir.toFile().getAbsolutePath());
+
+        Configuration          conf        = new Configuration();
+        RangerKeyStoreProvider keyProvider = new RangerKeyStoreProvider(conf);
+
+        // Create a key
+        Options options = new Options(conf);
+        options.setBitLength(128);
+        options.setCipher("AES");
+        KeyVersion keyVersion = keyProvider.createKey("newkey1", options);
+        Assertions.assertEquals("newkey1", keyVersion.getName());
+        Assertions.assertEquals(128 / 8, keyVersion.getMaterial().length);
+        Assertions.assertEquals("newkey1@0", keyVersion.getVersionName());
+
+        keyProvider.flush();
+        Assertions.assertEquals(1, keyProvider.getKeys().size());
+        keyProvider.deleteKey("newkey1");
+
+        keyProvider.flush();
+        Assertions.assertEquals(0, keyProvider.getKeys().size());
+    }
+
+    @Test
+    public void testDeleteKey_EngineDeleteEntryThrowsForBaseKey() throws Throwable {
+        Configuration          conf     = new Configuration();
+        RangerKeyStoreProvider provider = spy(new RangerKeyStoreProvider(conf));
+        RangerKeyStore         dbStore  = mock(RangerKeyStore.class);
+
+        // Inject mocked dbStore
+        Field dbStoreField = RangerKeyStoreProvider.class.getDeclaredField("dbStore");
+        dbStoreField.setAccessible(true);
+        dbStoreField.set(provider, dbStore);
+
+        // Mock Metadata
+        KeyProvider.Metadata metadata = mock(KeyProvider.Metadata.class);
+        when(metadata.getAlgorithm()).thenReturn("AES");
+        when(metadata.getBitLength()).thenReturn(128);
+        when(metadata.getDescription()).thenReturn("test description");
+        when(metadata.getVersions()).thenReturn(0); // No versions (only base key)
+        when(metadata.getAttributes()).thenReturn(new HashMap<>());
+
+        // Return mocked metadata
+        doReturn(metadata).when(provider).getMetadata("testKey");
+
+        // Simulate that base key alias exists
+        doReturn(true).when(dbStore).engineContainsAlias("testKey");
+
+        // Throw exception when trying to delete base key alias
+        doThrow(new KeyStoreException("Delete failed")).when(dbStore).engineDeleteEntry("testKey");
+
+        // Act & Assert
+        IOException ex = assertThrows(IOException.class, () -> provider.deleteKey("testKey"));
+        assertTrue(ex.getMessage().contains("Problem removing testKey from"));
+    }
+
+    @Test
+    public void testCreateKey() throws Throwable {
+        if (!UNRESTRICTED_POLICIES_INSTALLED) {
+            return;
+        }
+
+        Path configDir = Paths.get("src/test/resources/kms");
+        System.setProperty(KMSConfiguration.KMS_CONFIG_DIR, configDir.toFile().getAbsolutePath());
+
+        Configuration          conf        = new Configuration();
+        RangerKeyStoreProvider keyProvider = new RangerKeyStoreProvider(conf);
+
+        // Create a key
+        Options options = new Options(conf);
+        options.setBitLength(256);
+        options.setCipher("AES");
+        KeyVersion keyVersion = keyProvider.createKey("newkey1", options);
+        Assertions.assertEquals("newkey1", keyVersion.getName());
+        Assertions.assertEquals(256 / 8, keyVersion.getMaterial().length);
+        Assertions.assertEquals("newkey1@0", keyVersion.getVersionName());
+
+        keyProvider.flush();
+
+        // Validate the key exists
+        List<String> keys = keyProvider.getKeys();
+        Assertions.assertEquals(1, keys.size());
+        Assertions.assertEquals("newkey1", keys.get(0));
+    }
+
+    @Test
+    public void testRolloverKey() throws Throwable {
+        if (!UNRESTRICTED_POLICIES_INSTALLED) {
+            return;
+        }
+
+        Path configDir = Paths.get("src/test/resources/kms");
+        System.setProperty(KMSConfiguration.KMS_CONFIG_DIR, configDir.toFile().getAbsolutePath());
+
+        Configuration          conf        = new Configuration();
+        RangerKeyStoreProvider keyProvider = new RangerKeyStoreProvider(conf);
+
+        // Create a key
+        Options options = new Options(conf);
+        options.setBitLength(192);
+        options.setCipher("AES");
+        KeyVersion keyVersion = keyProvider.createKey("newkey1", options);
+        Assertions.assertEquals("newkey1", keyVersion.getName());
+        Assertions.assertEquals(192 / 8, keyVersion.getMaterial().length);
+        Assertions.assertEquals("newkey1@0", keyVersion.getVersionName());
+
+        keyProvider.flush();
+
+        // Rollover a new key
+        byte[] oldKey = keyVersion.getMaterial();
+        keyVersion = keyProvider.rollNewVersion("newkey1");
+        Assertions.assertEquals("newkey1", keyVersion.getName());
+        Assertions.assertEquals(192 / 8, keyVersion.getMaterial().length);
+        Assertions.assertEquals("newkey1@1", keyVersion.getVersionName());
+        Assertions.assertFalse(Arrays.equals(oldKey, keyVersion.getMaterial()));
+
+        keyProvider.deleteKey("newkey1");
+
+        keyProvider.flush();
+        Assertions.assertEquals(0, keyProvider.getKeys().size());
+        try {
+            keyProvider.deleteKey("newkey1");
+            keyProvider.flush();
+        } catch (IOException e) {
+            // Ignore if key doesn't exist
+        }
+    }
+
+    @Test
+    public void testGetKeyVersion() throws Throwable {
+        if (!UNRESTRICTED_POLICIES_INSTALLED) {
+            return;
+        }
+
+        Path configDir = Paths.get("src/test/resources/kms");
+        System.setProperty(KMSConfiguration.KMS_CONFIG_DIR, configDir.toFile().getAbsolutePath());
+
+        Configuration          conf        = new Configuration();
+        RangerKeyStoreProvider keyProvider = new RangerKeyStoreProvider(conf);
+
+        // Create a key version
+        Options options = new Options(conf);
+        options.setBitLength(192);
+        options.setCipher("AES");
+        KeyVersion keyVersion = keyProvider.createKey("newkey1", options);
+
+        Assertions.assertEquals("newkey1", keyVersion.getName());
+        Assertions.assertEquals(192 / 8, keyVersion.getMaterial().length);
+        Assertions.assertEquals("newkey1@0", keyVersion.getVersionName());
+
+        keyProvider.flush();
+
+        // Validate the key exists
+        Assertions.assertEquals(1, keyProvider.getKeys().size());
+
+        // Get key versions
+        List<KeyVersion> keyVersions = keyProvider.getKeyVersions("newkey1");
+        Assertions.assertEquals(1, keyVersions.size());
+
+        KeyVersion kv = keyVersions.get(0);
+        Assertions.assertEquals("newkey1", kv.getName());
+        Assertions.assertEquals(192 / 8, kv.getMaterial().length);
+        assertTrue(kv.getVersionName().startsWith("newkey1@"));
+
+        keyProvider.flush();
+        Assertions.assertNotEquals(0, keyProvider.getKeys().size());
+
+        // Try to get key versions of a non-existent key
+        try {
+            List<KeyVersion> invalidVersions = keyProvider.getKeyVersions("newkey2");
+            if (!invalidVersions.isEmpty()) {
+                Assertions.fail("Unexpected key version found: " + invalidVersions.get(0).getName());
+            }
+        } catch (IOException ex) {
+            // expected
+        }
+    }
+
+    @Test
+    public void testGetKeys() throws Throwable {
+        if (!UNRESTRICTED_POLICIES_INSTALLED) {
+            return;
+        }
+
+        Path configDir = Paths.get("src/test/resources/kms");
+        System.setProperty(KMSConfiguration.KMS_CONFIG_DIR, configDir.toFile().getAbsolutePath());
+
+        Configuration          conf        = new Configuration();
+        RangerKeyStoreProvider keyProvider = new RangerKeyStoreProvider(conf);
+
+        // Create a key version
+        Options options = new Options(conf);
+        options.setBitLength(192);
+        options.setCipher("AES");
+        KeyVersion keyVersion = keyProvider.createKey("newkey1", options);
+
+        Assertions.assertEquals("newkey1", keyVersion.getName());
+        Assertions.assertEquals(192 / 8, keyVersion.getMaterial().length);
+        Assertions.assertEquals("newkey1@0", keyVersion.getVersionName());
+
+        keyProvider.flush();
+
+        List<String> getkeys = keyProvider.getKeys();
+        Assertions.assertEquals(1, getkeys.size());
+        Assertions.assertEquals("newkey1", getkeys.get(0));
+
+        keyProvider.flush();
+        Assertions.assertNotEquals(0, keyProvider.getKeys().size());
+    }
+
+    @Test
+    public void testGetKeyVersionWithInvalidKey() throws Throwable {
+        if (!UNRESTRICTED_POLICIES_INSTALLED) {
+            return;
+        }
+
+        Path configDir = Paths.get("src/test/resources/kms");
+        System.setProperty(KMSConfiguration.KMS_CONFIG_DIR, configDir.toFile().getAbsolutePath());
+
+        Configuration          conf        = new Configuration();
+        RangerKeyStoreProvider keyProvider = new RangerKeyStoreProvider(conf);
+
+        // Try to get key versions of a non-existent key
+        try {
+            List<KeyVersion> invalidVersions = keyProvider.getKeyVersions("nonExistentKey");
+            assertTrue(invalidVersions.isEmpty(), "Expected no key versions for non-existent key");
+        } catch (IOException ex) {
+            // expected
+        }
+    }
+
+    @Test
+    public void testGetKeyVersionWithInvalidVersion() throws Throwable {
+        if (!UNRESTRICTED_POLICIES_INSTALLED) {
+            return;
+        }
+
+        Path configDir = Paths.get("src/test/resources/kms");
+        System.setProperty(KMSConfiguration.KMS_CONFIG_DIR, configDir.toFile().getAbsolutePath());
+
+        Configuration          conf        = new Configuration();
+        RangerKeyStoreProvider keyProvider = new RangerKeyStoreProvider(conf);
+
+        // Create a key version
+        Options options = new Options(conf);
+        options.setBitLength(192);
+        options.setCipher("AES");
+        KeyVersion keyVersion = keyProvider.createKey("newkey1", options);
+
+        Assertions.assertEquals("newkey1", keyVersion.getName());
+        Assertions.assertEquals(192 / 8, keyVersion.getMaterial().length);
+        Assertions.assertEquals("newkey1@0", keyVersion.getVersionName());
+
+        keyProvider.flush();
+
+        // Try to get an invalid version
+        try {
+            KeyVersion invalidVersion = keyProvider.getKeyVersion("newkey1@invalid");
+            Assertions.assertNull(invalidVersion, "Expected null for invalid version");
+        } catch (IOException ex) {
+            // expected
+        }
+    }
+
+    @Test
+    public void testGetKeyVersions() throws Throwable {
+        if (!UNRESTRICTED_POLICIES_INSTALLED) {
+            return;
+        }
+
+        Path configDir = Paths.get("src/test/resources/kms");
+        System.setProperty(KMSConfiguration.KMS_CONFIG_DIR, configDir.toFile().getAbsolutePath());
+
+        Configuration          conf        = new Configuration();
+        RangerKeyStoreProvider keyProvider = new RangerKeyStoreProvider(conf);
+
+        // Create a key version
+        Options options = new Options(conf);
+        options.setBitLength(192);
+        options.setCipher("AES");
+        KeyVersion keyVersion = keyProvider.createKey("newkey1", options);
+
+        Assertions.assertEquals("newkey1", keyVersion.getName());
+        Assertions.assertEquals(192 / 8, keyVersion.getMaterial().length);
+        Assertions.assertEquals("newkey1@0", keyVersion.getVersionName());
+
+        keyProvider.flush();
+
+        // Get key versions
+        List<KeyVersion> keyVersions = keyProvider.getKeyVersions("newkey1");
+        Assertions.assertEquals(1, keyVersions.size());
+
+        KeyVersion kv = keyVersions.get(0);
+        Assertions.assertEquals("newkey1", kv.getName());
+        Assertions.assertEquals(192 / 8, kv.getMaterial().length);
+        assertTrue(kv.getVersionName().startsWith("newkey1@"));
+    }
+
+    @Test
+    public void testGetMetadata() throws Throwable {
+        if (!UNRESTRICTED_POLICIES_INSTALLED) {
+            return;
+        }
+
+        Path configDir = Paths.get("src/test/resources/kms");
+        System.setProperty(KMSConfiguration.KMS_CONFIG_DIR, configDir.toFile().getAbsolutePath());
+
+        Configuration          conf        = new Configuration();
+        RangerKeyStoreProvider keyProvider = new RangerKeyStoreProvider(conf);
+
+        // Create a key version
+        Options options = new Options(conf);
+        options.setBitLength(192);
+        options.setCipher("AES");
+        KeyVersion keyVersion = keyProvider.createKey("newkey1", options);
+        Assertions.assertEquals("newkey1", keyVersion.getName());
+        Assertions.assertEquals(192 / 8, keyVersion.getMaterial().length);
+        Assertions.assertEquals("newkey1@0", keyVersion.getVersionName());
+
+        keyProvider.flush();
+
+        // Get metadata
+        String metadata = String.valueOf(keyProvider.getMetadata("newkey1"));
+        assertNotNull(metadata, "Metadata should not be null");
+        assertTrue(metadata.contains("192"), "Metadata should contain key bit length");
+        assertTrue(metadata.contains("AES"), "Metadata should contain key cipher");
+    }
+
+    @Test
+    public void testGetKeyVersionWithInvalidKeyName() throws Throwable {
+        if (!UNRESTRICTED_POLICIES_INSTALLED) {
+            return;
+        }
+
+        Path configDir = Paths.get("src/test/resources/kms");
+        System.setProperty(KMSConfiguration.KMS_CONFIG_DIR, configDir.toFile().getAbsolutePath());
+
+        Configuration          conf        = new Configuration();
+        RangerKeyStoreProvider keyProvider = new RangerKeyStoreProvider(conf);
+
+        // Try to get key versions of a non-existent key
+        try {
+            KeyVersion invalidVersion = keyProvider.getKeyVersion("nonExistentKey@0");
+            Assertions.assertNull(invalidVersion, "Expected null for non-existent key version");
+        } catch (IOException ex) {
+            // expected
+        }
+    }
+
+    @Test
+    public void testFlush() throws Throwable {
+        if (!UNRESTRICTED_POLICIES_INSTALLED) {
+            return;
+        }
+
+        Path configDir = Paths.get("src/test/resources/kms");
+        System.setProperty(KMSConfiguration.KMS_CONFIG_DIR, configDir.toFile().getAbsolutePath());
+
+        Configuration          conf        = new Configuration();
+        RangerKeyStoreProvider keyProvider = new RangerKeyStoreProvider(conf);
+
+        // Create a key version
+        Options options = new Options(conf);
+        options.setBitLength(192);
+        options.setCipher("AES");
+        KeyVersion keyVersion = keyProvider.createKey("newkey1", options);
+
+        Assertions.assertEquals("newkey1", keyVersion.getName());
+        Assertions.assertEquals(192 / 8, keyVersion.getMaterial().length);
+        Assertions.assertEquals("newkey1@0", keyVersion.getVersionName());
+
+        // Flush the provider
+        keyProvider.flush();
+
+        // Validate that the key is still present after flush
+        List<KeyVersion> keyVersions = keyProvider.getKeyVersions("newkey1");
+        Assertions.assertEquals(1, keyVersions.size());
+    }
+
+    @Test
+    public void testGetConfiguration() {
+        if (!UNRESTRICTED_POLICIES_INSTALLED) {
+            return;
+        }
+
+        String originalConfDir = System.getProperty(KMSConfiguration.KMS_CONFIG_DIR);
+
+        try {
+            System.setProperty(KMSConfiguration.KMS_CONFIG_DIR, "relative/path");
+
+            Configuration conf = new Configuration();
+
+            RuntimeException ex = assertThrows(RuntimeException.class, () -> {
+                new RangerKeyStoreProvider(conf); // Should internally call getConfiguration()
+            });
+
+            assertTrue(ex.getMessage().contains("must be an absolute path"));
+        } finally {
+            if (originalConfDir != null) {
+                System.setProperty(KMSConfiguration.KMS_CONFIG_DIR, originalConfDir);
+            } else {
+                System.clearProperty(KMSConfiguration.KMS_CONFIG_DIR);
+            }
+        }
+    }
+
+    @Test
+    public void testGetKeyVersionWithInvalidVersionName() throws Throwable {
+        if (!UNRESTRICTED_POLICIES_INSTALLED) {
+            return;
+        }
+
+        Path configDir = Paths.get("src/test/resources/kms");
+        System.setProperty(KMSConfiguration.KMS_CONFIG_DIR, configDir.toFile().getAbsolutePath());
+
+        Configuration          conf        = new Configuration();
+        RangerKeyStoreProvider keyProvider = new RangerKeyStoreProvider(conf);
+
+        // Try to get key version with an invalid version name
+        try {
+            KeyVersion invalidVersion = keyProvider.getKeyVersion("newkey1@invalid");
+            Assertions.assertNull(invalidVersion, "Expected null for invalid version name");
+        } catch (IOException ex) {
+            // expected
+        }
+    }
+
+    @Test
+    public void testGetDBKSConf() throws Throwable {
+        if (!UNRESTRICTED_POLICIES_INSTALLED) {
+            return;
+        }
+
+        Path configDir = Paths.get("src/test/resources/kms");
+        System.setProperty(KMSConfiguration.KMS_CONFIG_DIR, configDir.toFile().getAbsolutePath());
+
+        Configuration          conf        = new Configuration();
+        RangerKeyStoreProvider keyProvider = new RangerKeyStoreProvider(conf);
+
+        // Get the DB configuration
+        Configuration dbConf = RangerKeyStoreProvider.getDBKSConf();
+        assertNotNull(dbConf, "DB configuration should not be null");
+    }
+
+    @Test
+    public void testRollNewVersion_ThrowsWhenKeyNotFound() throws Throwable {
+        Path configDir = Paths.get("src/test/resources/kms");
+        System.setProperty(KMSConfiguration.KMS_CONFIG_DIR, configDir.toFile().getAbsolutePath());
+        Configuration          conf     = new Configuration();
+        RangerKeyStoreProvider provider = new RangerKeyStoreProvider(conf);
+
+        byte[] dummyMaterial = new byte[16]; // 128-bit material
+
+        IOException exception = assertThrows(IOException.class, () ->
+                provider.rollNewVersion("nonExistingKey", dummyMaterial));
+
+        assertTrue(exception.getMessage().contains("Key nonExistingKey not found"));
+    }
+
+    @Test
+    public void testRollNewVersion_ThrowsWhenKeyLengthMismatch() throws Throwable {
+        Path configDir = Paths.get("src/test/resources/kms");
+        System.setProperty(KMSConfiguration.KMS_CONFIG_DIR, configDir.toFile().getAbsolutePath());
+
+        Configuration          conf     = new Configuration();
+        RangerKeyStoreProvider provider = new RangerKeyStoreProvider(conf);
+
+        Options options = new Options(conf);
+        options.setBitLength(128);
+        options.setCipher("AES");
+        provider.createKey("testKeyMismatch", options);
+        provider.flush();
+
+        // Use 192-bit material
+        byte[] wrongMaterial = new byte[24];
+
+        IOException exception = assertThrows(IOException.class, () ->
+                provider.rollNewVersion("testKeyMismatch", wrongMaterial));
+
+        assertTrue(exception.getMessage().contains("Wrong key length"));
+    }
+
+    @Test
+    public void testDeleteKey_MetadataIsNull() throws Throwable {
+        Path configDir = Paths.get("src/test/resources/kms");
+        System.setProperty(KMSConfiguration.KMS_CONFIG_DIR, configDir.toFile().getAbsolutePath());
+
+        Configuration          conf         = new Configuration();
+        RangerKeyStoreProvider realProvider = new RangerKeyStoreProvider(conf);
+
+        // Spy on the real provider to override getMetadata
+        RangerKeyStoreProvider provider = spy(realProvider);
+
+        // Simulate missing metadata
+        doReturn(null).when(provider).getMetadata("testKey");
+
+        // Act & Assert
+        IOException ex = assertThrows(IOException.class, () -> provider.deleteKey("testKey"));
+
+        // This now matches the real message thrown by deleteKey()
+        assertTrue(ex.getMessage().contains("Key testKey does not exist"));
+    }
+
+    @Test
+    public void testGetKeyVersion_DecryptKeyThrowsRuntimeException() throws Throwable {
+        Configuration          conf     = new Configuration();
+        RangerKeyStore         dbStore  = mock(RangerKeyStore.class);
+        RangerKeyStoreProvider provider = spy(new RangerKeyStoreProvider(conf));
+
+        // Inject dbStore
+        Field dbStoreField = RangerKeyStoreProvider.class.getDeclaredField("dbStore");
+        dbStoreField.setAccessible(true);
+        dbStoreField.set(provider, dbStore);
+
+        // Enable keyVault mode
+        Field keyVaultField = RangerKeyStoreProvider.class.getDeclaredField("keyVaultEnabled");
+        keyVaultField.setAccessible(true);
+        keyVaultField.set(provider, true);
+
+        // Setup mocks: alias exists, but decryption fails
+        doReturn(true).when(dbStore).engineContainsAlias("testKey");
+        doThrow(new RuntimeException("decryption failure")).when(dbStore).engineGetDecryptedZoneKeyByte("testKey");
+
+        RuntimeException ex = assertThrows(RuntimeException.class, () -> provider.getKeyVersion("testKey"));
+        assertTrue(ex.getMessage().contains("Error while getting decrypted key."));
+        assertTrue(ex.getMessage().contains("decryption failure"));
+    }
+
+    @Test
+    public void testGetKeyVersion_NoSuchAlgorithmException() throws Throwable {
+        Configuration          conf     = new Configuration();
+        RangerKeyStore         dbStore  = mock(RangerKeyStore.class);
+        RangerKeyStoreProvider provider = spy(new RangerKeyStoreProvider(conf));
+
+        // Inject dbStore
+        Field dbStoreField = RangerKeyStoreProvider.class.getDeclaredField("dbStore");
+        dbStoreField.setAccessible(true);
+        dbStoreField.set(provider, dbStore);
+
+        // Setup: alias exists, key fetch throws NoSuchAlgorithmException
+        doReturn(true).when(dbStore).engineContainsAlias("testKey");
+        doThrow(new NoSuchAlgorithmException()).when(dbStore).engineGetKey(eq("testKey"), any());
+
+        IOException ex = assertThrows(IOException.class, () -> provider.getKeyVersion("testKey"));
+
+        assertTrue(ex.getMessage().contains("Can't get algorithm for key"));
+
+        // Setup: alias exists, key fetch throws UnrecoverableKeyException
+        doReturn(true).when(dbStore).engineContainsAlias("testKey");
+        doThrow(new UnrecoverableKeyException()).when(dbStore).engineGetKey(eq("testKey"), any());
+
+        IOException ex1 = assertThrows(IOException.class, () -> provider.getKeyVersion("testKey"));
+
+        assertTrue(ex1.getMessage().contains("Can't recover key "));
+    }
+
+    @Test
+    public void testGetMetadata_GenericException() throws Throwable {
+        Configuration          conf     = new Configuration();
+        RangerKeyStoreProvider provider = spy(new RangerKeyStoreProvider(conf));
+        RangerKeyStore         dbStore  = mock(RangerKeyStore.class);
+
+        // Inject mocked dbStore
+        Field dbStoreField = RangerKeyStoreProvider.class.getDeclaredField("dbStore");
+        dbStoreField.setAccessible(true);
+        dbStoreField.set(provider, dbStore);
+
+        // Simulate exception during dbStore.engineContainsAlias for RuntimeException
+        when(dbStore.engineContainsAlias("testKey")).thenThrow(new RuntimeException("DB failure"));
+
+        IOException ex = assertThrows(IOException.class, () -> provider.getMetadata("testKey"));
+
+        assertTrue(ex.getMessage().contains("Please try again"));
+        assertTrue(ex.getCause().getMessage().contains("DB failure"));
+    }
+
+    @Test
+    public void testGetConfiguration1() throws Throwable {
+        if (!UNRESTRICTED_POLICIES_INSTALLED) {
+            return;
+        }
+
+        Path configDir = Paths.get("src/test/resources/kms");
+        System.setProperty(KMSConfiguration.KMS_CONFIG_DIR, configDir.toFile().getAbsolutePath());
+
+        Configuration          conf        = new Configuration();
+        RangerKeyStoreProvider keyProvider = new RangerKeyStoreProvider(conf);
+
+        // Get the configuration
+        Configuration keyProviderConf = keyProvider.getConf();
+        assertNotNull(keyProviderConf, "Configuration should not be null");
+    }
+
+    @Test
+    public void testSaveKey_ThrowsIOException() throws Throwable {
+        Configuration          conf     = new Configuration();
+        RangerKeyStoreProvider provider = spy(new RangerKeyStoreProvider(conf));
+        RangerKeyStore         dbStore  = mock(RangerKeyStore.class);
+
+        // Inject mocked dbStore
+        Field dbStoreField = RangerKeyStoreProvider.class.getDeclaredField("dbStore");
+        dbStoreField.setAccessible(true);
+        dbStoreField.set(provider, dbStore);
+
+        // Set keyVaultEnabled = false
+        Field keyVaultField = RangerKeyStoreProvider.class.getDeclaredField("keyVaultEnabled");
+        keyVaultField.setAccessible(true);
+        keyVaultField.set(provider, false);
+
+        // Mock Metadata with required getters
+        KeyProvider.Metadata metadata = mock(KeyProvider.Metadata.class);
+        when(metadata.getAlgorithm()).thenReturn("AES");
+        when(metadata.getBitLength()).thenReturn(128);
+        when(metadata.getDescription()).thenReturn("test description");
+        when(metadata.getVersions()).thenReturn(1);
+        when(metadata.getAttributes()).thenReturn(new HashMap<>());
+
+        // Mock exception on addKeyEntry
+        doThrow(new RuntimeException("decryption failure")).when(dbStore).addKeyEntry(
+                eq("testKey"),
+                any(),
+                any(),
+                eq("AES"),
+                eq(128),
+                eq("test description"),
+                eq(1),
+                any());
+
+        Method saveKeyMethod = RangerKeyStoreProvider.class.getDeclaredMethod("saveKey", String.class, KeyProvider.Metadata.class);
+        saveKeyMethod.setAccessible(true);
+
+        try {
+            saveKeyMethod.invoke(provider, "testKey", metadata);
+            fail("Expected IOException to be thrown");
+        } catch (InvocationTargetException e) {
+            Throwable cause = e.getCause();
+            assertInstanceOf(IOException.class, cause, "Cause should be IOException");
+            assertInstanceOf(RuntimeException.class, cause.getCause(), "IOException cause should be RuntimeException");
+            assertTrue(cause.getCause().getMessage().contains("decryption failure"));
+        }
+    }
+
+    @Test
+    public void testGetKeyVersion_KeyVaultTrue_SuccessPath() throws Throwable {
+        Configuration          conf     = new Configuration();
+        RangerKeyStoreProvider provider = spy(new RangerKeyStoreProvider(conf));
+        RangerKeyStore         dbStore  = mock(RangerKeyStore.class);
+
+        // Inject dbStore
+        Field dbStoreField = RangerKeyStoreProvider.class.getDeclaredField("dbStore");
+        dbStoreField.setAccessible(true);
+        dbStoreField.set(provider, dbStore);
+
+        // Set keyVaultEnabled = true
+        Field keyVaultField = RangerKeyStoreProvider.class.getDeclaredField("keyVaultEnabled");
+        keyVaultField.setAccessible(true);
+        keyVaultField.set(provider, true);
+
+        String versionedKey = "testKey@0";
+
+        // Simulate engineContainsAlias returns false first, then true
+        when(dbStore.engineContainsAlias(versionedKey)).thenReturn(false).thenReturn(true);
+
+        // Simulate engineLoad
+        doNothing().when(dbStore).engineLoad(isNull(), any());
+
+        // Simulate decrypted key return
+        byte[] decryptedKey = new byte[] {0x01, 0x02, 0x03};
+        when(dbStore.engineGetDecryptedZoneKeyByte(versionedKey)).thenReturn(decryptedKey);
+
+        // Act
+        KeyVersion result = provider.getKeyVersion(versionedKey);
+
+        // Assert
+        assertNotNull(result);
+        assertEquals(versionedKey, result.getVersionName());
+        assertEquals("testKey", result.getName());
+        assertArrayEquals(decryptedKey, result.getMaterial());
+    }
+
+    @Test
+    public void testGenerateAndGetMasterKey_generateMasterKeyThrows() throws Throwable {
+        Configuration          conf              = new Configuration();
+        RangerKeyStoreProvider provider          = spy(new RangerKeyStoreProvider(conf));
+        RangerKMSMKI           masterKeyProvider = mock(RangerKMSMKI.class);
+
+        // simulate generateMasterKey throwing an exception
+        doThrow(new RuntimeException("Simulated failure in generateMasterKey")).when(masterKeyProvider).generateMasterKey("abc123");
+
+        Method method = RangerKeyStoreProvider.class.getDeclaredMethod("generateAndGetMasterKey", RangerKMSMKI.class, String.class);
+        method.setAccessible(true);
+
+        RuntimeException ex = assertThrows(RuntimeException.class, () -> {
+            try {
+                method.invoke(provider, masterKeyProvider, "abc123");
+            } catch (InvocationTargetException e) {
+                throw e.getCause();
+            }
+        });
+
+        assertTrue(ex.getMessage().contains("Error while generating Ranger Master key"));
+    }
+
+    @Test
+    void testFlush_EngineStoreThrowsIOException() throws Throwable {
+        Configuration  conf    = new Configuration();
+        RangerKeyStore dbStore = mock(RangerKeyStore.class);
+        doThrow(new IOException("Flush failed")).when(dbStore).engineStore(any(), any());
+
+        RangerKeyStoreProvider provider = spy(new RangerKeyStoreProvider(conf));
+
+        // Inject mocks and changed = true
+        Field dbStoreField = RangerKeyStoreProvider.class.getDeclaredField("dbStore");
+        dbStoreField.setAccessible(true);
+        dbStoreField.set(provider, dbStore);
+
+        Field changedField = RangerKeyStoreProvider.class.getDeclaredField("changed");
+        changedField.setAccessible(true);
+        changedField.set(provider, true);
+
+        IOException ex = assertThrows(IOException.class, provider::flush);
+        assertTrue(ex.getMessage().contains("Flush failed"));
+
+        verify(dbStore, times(1)).engineStore(any(), any());
+    }
+
+    @Test
+    void testFlush_EngineStoreThrowsNoSuchAlgorithmException() throws Throwable {
+        Configuration  conf    = new Configuration();
+        RangerKeyStore dbStore = mock(RangerKeyStore.class);
+        doThrow(new NoSuchAlgorithmException()).when(dbStore).engineStore(any(), any());
+
+        RangerKeyStoreProvider provider = spy(new RangerKeyStoreProvider(conf));
+
+        Field dbStoreField = RangerKeyStoreProvider.class.getDeclaredField("dbStore");
+        dbStoreField.setAccessible(true);
+        dbStoreField.set(provider, dbStore);
+
+        Field changedField = RangerKeyStoreProvider.class.getDeclaredField("changed");
+        changedField.setAccessible(true);
+        changedField.set(provider, true);
+
+        IOException ex = assertThrows(IOException.class, provider::flush);
+        assertTrue(ex.getMessage().contains("No such algorithm storing key"));
+
+        verify(dbStore, times(1)).engineStore(any(), any());
+    }
+
+    @Test
+    void testFlush_EngineStoreThrowsCertificateException() throws Throwable {
+        Configuration  conf    = new Configuration();
+        RangerKeyStore dbStore = mock(RangerKeyStore.class);
+        doThrow(new CertificateException()).when(dbStore).engineStore(any(), any());
+
+        RangerKeyStoreProvider provider = spy(new RangerKeyStoreProvider(conf));
+
+        Field dbStoreField = RangerKeyStoreProvider.class.getDeclaredField("dbStore");
+        dbStoreField.setAccessible(true);
+        dbStoreField.set(provider, dbStore);
+
+        Field changedField = RangerKeyStoreProvider.class.getDeclaredField("changed");
+        changedField.setAccessible(true);
+        changedField.set(provider, true);
+
+        IOException ex = assertThrows(IOException.class, provider::flush);
+        assertTrue(ex.getMessage().contains("Certificate exception storing key"));
+
+        verify(dbStore, times(1)).engineStore(any(), any());
+    }
+
+    @Test
+    void testDeleteKey_ShouldThrowIOException() throws Throwable {
+        Configuration          conf     = new Configuration();
+        RangerKeyStore         dbStore  = mock(RangerKeyStore.class);
+        RangerKeyStoreProvider provider = spy(new RangerKeyStoreProvider(conf));
+
+        // Inject mocked dbStore
+        Field dbStoreField = RangerKeyStoreProvider.class.getDeclaredField("dbStore");
+        dbStoreField.setAccessible(true);
+        dbStoreField.set(provider, dbStore);
+
+        // Mock Metadata object with versions = 1
+        KeyProvider.Metadata metadata = mock(KeyProvider.Metadata.class);
+        when(metadata.getVersions()).thenReturn(1);
+
+        // Stub getMetadata to return mocked metadata
+        doReturn(metadata).when(provider).getMetadata("testKey");
+
+        // Stub dbStore responses for key existence
+        doReturn(true).when(dbStore).engineContainsAlias("testKey@0");
+        doReturn(true).when(dbStore).engineContainsAlias("testKey");
+
+        // Simulate KeyStoreException on deleting the version key
+        doThrow(new KeyStoreException("forced exception")).when(dbStore).engineDeleteEntry("testKey@0");
+
+        // Expect IOException because KeyStoreException is caught and wrapped
+        IOException ex = assertThrows(IOException.class, () -> provider.deleteKey("testKey"));
+        assertTrue(ex.getMessage().contains("Problem removing"));
+
+        // Verify interactions with dbStore mocks
+        verify(dbStore).engineContainsAlias("testKey@0");
+        verify(dbStore).engineDeleteEntry("testKey@0");
+    }
+
+    @Test
+    void testCreateKey_ShouldThrowIOException_WhenKeyAlreadyExists() throws Throwable {
+        Configuration          conf     = new Configuration();
+        RangerKeyStore         dbStore  = mock(RangerKeyStore.class);
+        RangerKeyStoreProvider provider = spy(new RangerKeyStoreProvider(conf));
+
+        // Inject mocked dbStore
+        Field dbStoreField = RangerKeyStoreProvider.class.getDeclaredField("dbStore");
+        dbStoreField.setAccessible(true);
+        dbStoreField.set(provider, dbStore);
+
+        String keyName  = "existingKey";
+        byte[] material = new byte[16]; // 128 bits
+        KeyProvider.Options options = new KeyProvider.Options(conf)
+                .setCipher("AES")
+                .setBitLength(128);
+
+        // Simulate that key already exists
+        when(dbStore.engineContainsAlias(keyName)).thenReturn(true);
+
+        IOException ex = assertThrows(IOException.class, () -> provider.createKey(keyName, material, options));
+        assertTrue(ex.getMessage().contains("Key " + keyName + " already exists"));
+    }
+
+    @Test
+    void testCreateKey_ShouldThrowIOException_WhenKeyLengthIncorrect() throws Throwable {
+        Configuration          conf     = new Configuration();
+        RangerKeyStore         dbStore  = mock(RangerKeyStore.class);
+        RangerKeyStoreProvider provider = spy(new RangerKeyStoreProvider(conf));
+
+        // Inject mocked dbStore
+        Field dbStoreField = RangerKeyStoreProvider.class.getDeclaredField("dbStore");
+        dbStoreField.setAccessible(true);
+        dbStoreField.set(provider, dbStore);
+
+        String keyName  = "newKey";
+        byte[] material = new byte[10]; // 80 bits
+        KeyProvider.Options options = new KeyProvider.Options(conf)
+                .setCipher("AES")
+                .setBitLength(128); // But expects 128 bits
+
+        // Simulate key does not exist
+        when(dbStore.engineContainsAlias(keyName)).thenReturn(false);
+
+        IOException ex = assertThrows(IOException.class, () -> provider.createKey(keyName, material, options));
+        assertTrue(ex.getMessage().contains("Wrong key length. Required 128, but got 80"));
+    }
+
+    static {
+        boolean ok = false;
+        try {
+            byte[] data = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};
+
+            SecretKey key192 = new SecretKeySpec(
+                    new byte[] {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+                            0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+                            0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17},
+                    "AES");
+            Cipher c = Cipher.getInstance("AES");
+            c.init(Cipher.ENCRYPT_MODE, key192);
+            c.doFinal(data);
+            ok = true;
+        } catch (Exception e) {
+            //
+        }
+        UNRESTRICTED_POLICIES_INSTALLED = ok;
+    }
+}
diff --git a/kms/src/test/java/org/apache/hadoop/crypto/key/kms/RangerMasterKeyTest.java b/kms/src/test/java/org/apache/hadoop/crypto/key/kms/RangerMasterKeyTest.java
new file mode 100644
index 000000000..6abca9f3e
--- /dev/null
+++ b/kms/src/test/java/org/apache/hadoop/crypto/key/kms/RangerMasterKeyTest.java
@@ -0,0 +1,305 @@
+    /*
+ * 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.hadoop.crypto.key.kms;
+
+import com.sun.jersey.core.util.Base64;
+import org.apache.hadoop.crypto.key.RangerKMSDB;
+import org.apache.hadoop.crypto.key.RangerKeyStoreProvider;
+import org.apache.hadoop.crypto.key.RangerMasterKey;
+import org.apache.hadoop.crypto.key.kms.server.DerbyTestUtils;
+import org.apache.hadoop.crypto.key.kms.server.KMSConfiguration;
+import org.apache.ranger.kms.dao.DaoManager;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+import javax.crypto.Cipher;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.SecretKeySpec;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Properties;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+/**
+ * A test for the RangerMasterKey.
+ */
+public class RangerMasterKeyTest {
+    private static final boolean UNRESTRICTED_POLICIES_INSTALLED;
+
+    @BeforeAll
+    public static void startServers() throws Exception {
+        if (!UNRESTRICTED_POLICIES_INSTALLED) {
+            return;
+        }
+        DerbyTestUtils.startDerby();
+    }
+
+    @AfterAll
+    public static void stopServers() throws Exception {
+        if (UNRESTRICTED_POLICIES_INSTALLED) {
+            DerbyTestUtils.stopDerby();
+        }
+    }
+
+    @Test
+    public void testFetchEncrAlgo_DefaultFallback() throws Exception {
+        if (!UNRESTRICTED_POLICIES_INSTALLED) {
+            return;
+        }
+
+        Path configDir = Paths.get("src/test/resources/kms");
+        System.setProperty(KMSConfiguration.KMS_CONFIG_DIR, configDir.toFile().getAbsolutePath());
+
+        RangerKMSDB     rangerkmsDb     = new RangerKMSDB(RangerKeyStoreProvider.getDBKSConf());
+        DaoManager      daoManager      = rangerkmsDb.getDaoManager();
+        RangerMasterKey rangerMasterKey = new RangerMasterKey(daoManager);
+
+        String inputWithoutComma = "verylongstringwithoutcommapassword123";
+
+        Method method = RangerMasterKey.class.getDeclaredMethod("fetchEncrAlgo", String.class);
+        method.setAccessible(true);
+
+        String result = (String) method.invoke(rangerMasterKey, inputWithoutComma);
+        Assertions.assertEquals("PBEWithMD5AndTripleDES", result);  // default fallback
+    }
+
+    @Test
+    public void testReencryptMKWithFipsAlgo() throws Exception {
+        if (!UNRESTRICTED_POLICIES_INSTALLED) {
+            return;
+        }
+
+        Path configDir = Paths.get("src/test/resources/kms");
+        System.setProperty(KMSConfiguration.KMS_CONFIG_DIR, configDir.toFile().getAbsolutePath());
+
+        RangerKMSDB     rangerkmsDb     = new RangerKMSDB(RangerKeyStoreProvider.getDBKSConf());
+        DaoManager      daoManager      = rangerkmsDb.getDaoManager();
+        RangerMasterKey rangerMasterKey = new RangerMasterKey(daoManager);
+
+        String inputWithoutComma = "verylongstringwithoutcommapassword123";
+
+        Method method = RangerMasterKey.class.getDeclaredMethod("reencryptMKWithFipsAlgo", String.class);
+        method.setAccessible(true);
+
+        boolean result = (boolean) method.invoke(rangerMasterKey, inputWithoutComma);
+        Assertions.assertFalse(result);  // or assertTrue if expecting re-encryption to happen
+    }
+
+    @Test
+    public void testGenerateMKFromHSMMK() throws Throwable {
+        if (!UNRESTRICTED_POLICIES_INSTALLED) {
+            return;
+        }
+
+        Path configDir = Paths.get("src/test/resources/kms");
+        System.setProperty(KMSConfiguration.KMS_CONFIG_DIR, configDir.toFile().getAbsolutePath());
+
+        RangerKMSDB     rangerkmsDb     = new RangerKMSDB(RangerKeyStoreProvider.getDBKSConf());
+        DaoManager      daoManager      = rangerkmsDb.getDaoManager();
+        RangerMasterKey rangerMasterKey = new RangerMasterKey(daoManager);
+
+        String password = "password0password0password0password0password0password0password0password0"
+                + "password0password0password0password0password0password0password0password0"
+                + "password0password0password0password0password0password0password0";
+        byte[] key = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+                0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+                0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17};
+        rangerMasterKey.generateMKFromHSMMK(password, key);
+    }
+
+    @Test
+    public void testGenerateMKFromKeySecureMK() throws Throwable {
+        if (!UNRESTRICTED_POLICIES_INSTALLED) {
+            return;
+        }
+
+        Path configDir = Paths.get("src/test/resources/kms");
+        System.setProperty(KMSConfiguration.KMS_CONFIG_DIR, configDir.toFile().getAbsolutePath());
+
+        RangerKMSDB     rangerkmsDb     = new RangerKMSDB(RangerKeyStoreProvider.getDBKSConf());
+        DaoManager      daoManager      = rangerkmsDb.getDaoManager();
+        RangerMasterKey rangerMasterKey = new RangerMasterKey(daoManager);
+
+        String password = "password0password0password0password0password0password0password0password0"
+                + "password0password0password0password0password0password0password0";
+        byte[] key = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+                0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+                0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17};
+        rangerMasterKey.generateMKFromKeySecureMK(password, key);
+
+        assertNotNull(rangerMasterKey.getMasterKey(password));
+    }
+
+    @Test
+    public void testDecryptMasterKeySK() throws Exception {
+        if (!UNRESTRICTED_POLICIES_INSTALLED) {
+            return;
+        }
+
+        Path configDir = Paths.get("src/test/resources/kms");
+        System.setProperty(KMSConfiguration.KMS_CONFIG_DIR, configDir.toFile().getAbsolutePath());
+
+        RangerKMSDB     rangerkmsDb     = new RangerKMSDB(RangerKeyStoreProvider.getDBKSConf());
+        DaoManager      daoManager      = rangerkmsDb.getDaoManager();
+        RangerMasterKey rangerMasterKey = new RangerMasterKey(daoManager);
+
+        String password = "password0password0password0password0password0password0password0password0"
+                + "password0password0password0password0password0password0password0";
+
+        // Simulate a generated master key
+        byte[] rawKey        = "myMockRawKey1234567890".getBytes();  // Simulated secret key material
+        Method encryptMethod = RangerMasterKey.class.getDeclaredMethod("encryptMasterKey", String.class, byte[].class);
+        encryptMethod.setAccessible(true);
+        String encryptedStr = (String) encryptMethod.invoke(rangerMasterKey, password, rawKey);
+
+        // Now decrypt using the method under test
+        Method decryptMethod = RangerMasterKey.class.getDeclaredMethod(
+                "decryptMasterKeySK", byte[].class, String.class, String.class);
+        decryptMethod.setAccessible(true);
+
+        byte[]    encryptedBytes = Base64.decode(encryptedStr);
+        SecretKey secretKey      = (SecretKey) decryptMethod.invoke(rangerMasterKey, encryptedBytes, password, encryptedStr);
+
+        assertNotNull(secretKey);
+    }
+
+    @Test
+    public void testUpdateEncryptedMK() throws Exception {
+        if (!UNRESTRICTED_POLICIES_INSTALLED) {
+            return;
+        }
+
+        Path            configDir       = Paths.get("src/test/resources/kms");
+        RangerKMSDB     rangerkmsDb     = new RangerKMSDB(RangerKeyStoreProvider.getDBKSConf());
+        DaoManager      daoManager      = rangerkmsDb.getDaoManager();
+        RangerMasterKey rangerMasterKey = new RangerMasterKey(daoManager);
+
+        String password = "password0password0password0password0password0password0password0password0"
+                + "password0password0password0password0password0password0password0";
+
+        byte[] rawKey = "myMockRawKey1234567890".getBytes();
+
+        Method updateEncryptedMKMethod = RangerMasterKey.class.getDeclaredMethod(
+                "updateEncryptedMK", String.class);
+        updateEncryptedMKMethod.setAccessible(true);
+        updateEncryptedMKMethod.invoke(rangerMasterKey, password);
+    }
+
+    @Test
+    public void testGetFIPSCompliantPassword() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
+        if (!UNRESTRICTED_POLICIES_INSTALLED) {
+            return;
+        }
+
+        Path configDir = Paths.get("src/test/resources/kms");
+        System.setProperty(KMSConfiguration.KMS_CONFIG_DIR, configDir.toFile().getAbsolutePath());
+
+        RangerKMSDB     rangerkmsDb     = new RangerKMSDB(RangerKeyStoreProvider.getDBKSConf());
+        DaoManager      daoManager      = rangerkmsDb.getDaoManager();
+        RangerMasterKey rangerMasterKey = new RangerMasterKey(daoManager);
+
+        String password = "password0password0password0password0password0password0password0password0"
+                + "password0password0password0password0password0password0password0";
+
+        Method getFIPSCompliantPasswordMethod = RangerMasterKey.class.getDeclaredMethod(
+                "getFIPSCompliantPassword", String.class);
+        getFIPSCompliantPasswordMethod.setAccessible(true);
+        getFIPSCompliantPasswordMethod.invoke(rangerMasterKey, password);
+    }
+
+    @Test
+    public void testGetPasswordParam() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
+        if (!UNRESTRICTED_POLICIES_INSTALLED) {
+            return;
+        }
+
+        Path configDir = Paths.get("src/test/resources/kms");
+        System.setProperty(KMSConfiguration.KMS_CONFIG_DIR, configDir.toFile().getAbsolutePath());
+
+        RangerKMSDB     rangerkmsDb     = new RangerKMSDB(RangerKeyStoreProvider.getDBKSConf());
+        DaoManager      daoManager      = rangerkmsDb.getDaoManager();
+        RangerMasterKey rangerMasterKey = new RangerMasterKey(daoManager);
+
+        String password = "password0password0password0password0password0password0password0password0"
+                + "password0password0password0password0password0password0password0";
+
+        Method getPasswordParamMethod = RangerMasterKey.class.getDeclaredMethod(
+                "getPasswordParam", String.class);
+        getPasswordParamMethod.setAccessible(true);
+        getPasswordParamMethod.invoke(rangerMasterKey, password);
+    }
+
+    @Test
+    public void testGetIntConfig_ReturnsDefaultWhenPropertyMissing() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
+        if (!UNRESTRICTED_POLICIES_INSTALLED) {
+            return;
+        }
+
+        Path configDir = Paths.get("src/test/resources/kms");
+        System.setProperty(KMSConfiguration.KMS_CONFIG_DIR, configDir.toFile().getAbsolutePath());
+
+        RangerKMSDB     rangerkmsDb     = new RangerKMSDB(RangerKeyStoreProvider.getDBKSConf());
+        DaoManager      daoManager      = rangerkmsDb.getDaoManager();
+        RangerMasterKey rangerMasterKey = new RangerMasterKey(daoManager);
+
+        Method method = RangerMasterKey.class.getDeclaredMethod("getIntConfig", String.class, int.class);
+        method.setAccessible(true);
+        int defaultValue = 42;
+        int result       = (int) method.invoke(rangerMasterKey, "non.existent.property", defaultValue);
+        Assertions.assertEquals(defaultValue, result, "Expected default value when property is missing");
+    }
+
+    @Test
+    public void testGetIntConfig_ParsesValidInteger() throws Exception {
+        Field propField = RangerMasterKey.class.getDeclaredField("serverConfigProperties");
+        propField.setAccessible(true);
+        Properties props = new Properties();
+        props.setProperty("valid.int.key", "123");
+
+        Method method = RangerMasterKey.class.getDeclaredMethod("getIntConfig", String.class, int.class);
+        method.setAccessible(true);
+        int invoke = (int) method.invoke(null, "valid.int.key", 42);
+    }
+
+    static {
+        boolean ok = false;
+        try {
+            byte[] data = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};
+
+            SecretKey key192 = new SecretKeySpec(
+                    new byte[] {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+                            0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+                            0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17},
+                    "AES");
+            Cipher c = Cipher.getInstance("AES");
+            c.init(Cipher.ENCRYPT_MODE, key192);
+            c.doFinal(data);
+            ok = true;
+        } catch (Exception e) {
+            //
+        }
+        UNRESTRICTED_POLICIES_INSTALLED = ok;
+    }
+}
diff --git a/kms/src/test/java/org/apache/hadoop/crypto/key/kms/TestAzureKeyVaultClientAuthenticator.java b/kms/src/test/java/org/apache/hadoop/crypto/key/kms/TestAzureKeyVaultClientAuthenticator.java
new file mode 100644
index 000000000..5ddb7e5b2
--- /dev/null
+++ b/kms/src/test/java/org/apache/hadoop/crypto/key/kms/TestAzureKeyVaultClientAuthenticator.java
@@ -0,0 +1,78 @@
+/*
+ * 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.hadoop.crypto.key.kms;
+
+import com.microsoft.azure.keyvault.KeyVaultClient;
+import org.apache.hadoop.crypto.key.AzureKeyVaultClientAuthenticator;
+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 static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
+public class TestAzureKeyVaultClientAuthenticator {
+    @Test
+    public void testDoAuthenticate_shouldThrowRuntimeException() {
+        String authClientID     = "test-client-id";
+        String authClientSecret = "test-client-secret";
+
+        AzureKeyVaultClientAuthenticator authenticator = new AzureKeyVaultClientAuthenticator(authClientID, authClientSecret);
+
+        String authorization = "https://login.microsoftonline.com/test-tenant";
+        String resource      = "https://vault.azure.net";
+        String scope         = "https://vault.azure.net.default";
+
+        assertThrows(RuntimeException.class, () ->
+                authenticator.doAuthenticate(authorization, resource, scope));
+    }
+
+    @Test
+    public void testGetAuthentication_withMissingPemFile_shouldThrowException() {
+        AzureKeyVaultClientAuthenticator authenticator = new AzureKeyVaultClientAuthenticator("dummy-client-id");
+
+        Exception ex = assertThrows(Exception.class, () -> {
+            authenticator.getAuthentication("non-existent.pem", "dummyPassword");
+        });
+
+        assertTrue(ex.getMessage().contains("Error while parsing pem certificate"));
+    }
+
+    @Test
+    public void testGetAuthentication_withMissingPfxFile_shouldThrowException() {
+        AzureKeyVaultClientAuthenticator authenticator = new AzureKeyVaultClientAuthenticator("dummy-client-id");
+
+        Exception ex = assertThrows(Exception.class, () ->
+                authenticator.getAuthentication("non-existent.pfx", "dummyPassword"));
+
+        assertTrue(ex.getMessage().contains("Error while parsing pfx certificate"));
+    }
+
+    @Test
+    public void testGetAuthentication_withInvalidExtension_shouldReturnNull() throws Exception {
+        AzureKeyVaultClientAuthenticator authenticator = new AzureKeyVaultClientAuthenticator("dummy-client-id");
+
+        KeyVaultClient result = authenticator.getAuthentication("file.unknown", "dummyPassword");
+
+        assertNull(result);
+    }
+}
diff --git a/kms/src/test/java/org/apache/hadoop/crypto/key/kms/TestDBToAzureKeyVault.java b/kms/src/test/java/org/apache/hadoop/crypto/key/kms/TestDBToAzureKeyVault.java
new file mode 100644
index 000000000..e12238eeb
--- /dev/null
+++ b/kms/src/test/java/org/apache/hadoop/crypto/key/kms/TestDBToAzureKeyVault.java
@@ -0,0 +1,218 @@
+/*
+ * 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.hadoop.crypto.key.kms;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.crypto.key.DBToAzureKeyVault;
+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.ByteArrayOutputStream;
+import java.io.PrintStream;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.security.Permission;
+
+import static org.eclipse.persistence.jpa.jpql.Assert.fail;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
+public class TestDBToAzureKeyVault {
+    @Test
+    public void testShowUsage() {
+        PrintStream           originalErr = System.err;
+        ByteArrayOutputStream errContent  = new ByteArrayOutputStream();
+        System.setErr(new PrintStream(errContent));
+
+        DBToAzureKeyVault.showUsage();
+
+        System.setErr(originalErr);
+        String output = errContent.toString();
+
+        assertTrue(output.contains("USAGE: java " + DBToAzureKeyVault.class.getName()));
+        assertTrue(output.contains("<azureMasterKeyName>"));
+    }
+
+    @Test
+    public void testMain_EmptyAzureKeyName_ShouldExit11() {
+        String[] args = new String[] {"", "RSA", "AES", "https://vault.url", "lulu", "clientId", "false", "clientSecret"};
+
+        SecurityManager originalSM = System.getSecurityManager();
+        System.setSecurityManager(new SecurityManager() {
+            @Override
+            public void checkPermission(Permission perm) {}
+
+            @Override
+            public void checkExit(int status) {
+                throw new SecurityException("exit:" + status);
+            }
+        });
+
+        try {
+            DBToAzureKeyVault.main(args);
+            fail("Expected System.exit to be called");
+        } catch (SecurityException ex) {
+            assertTrue(ex.getMessage().contains("exit:1"));
+        } finally {
+            System.setSecurityManager(originalSM);
+        }
+    }
+
+    @Test
+    void testDoExportMKToAzureKeyVault_WhenMasterKeyMissing_ShouldThrow() throws Exception {
+        // 1. Instance of the class under test
+        DBToAzureKeyVault vault = new DBToAzureKeyVault();
+
+        // 2. Grab the private method via reflection
+        Method m = DBToAzureKeyVault.class.getDeclaredMethod(
+                "doExportMKToAzureKeyVault",
+                boolean.class,                       // sslEnabled
+                String.class, String.class, String.class, // key name/type/algo
+                String.class, String.class,               // clientId + vault‑URL
+                String.class, String.class,               // pwd/cert + certPwd
+                Configuration.class);                     // Hadoop conf
+        m.setAccessible(true);
+
+        // 3. Build a Configuration that will FAIL the very first check
+        Configuration conf = new Configuration();
+        conf.set("ranger.db.encrypt.key.password", "crypted");   // triggers IOException path
+
+        // 4. Parameters – values after the first three don’t matter for this test
+        Object[] params = {
+                false,                       // sslEnabled
+                "testKey",                   // masterKeyName
+                "RSA",                       // masterKeyType
+                "AES",                       // zoneKeyEncryptionAlgo
+                "clientId",                  // azureClientId
+                "https://dummy.vault",       // azureKeyVaultUrl
+                "secretOrPem",               // passwordOrCertPath
+                null,                        // certificatePassword
+                conf                         // Hadoop conf
+        };
+
+        // ---- act / assert -------------------------------------------------------------
+        InvocationTargetException ite = assertThrows(
+                InvocationTargetException.class,
+                () -> m.invoke(vault, params));
+
+        // unwrap and assert message
+        Throwable cause = ite.getCause();
+        assertInstanceOf(RuntimeException.class, cause);
+        assertTrue(cause.getMessage()
+                .contains("Unable to import Master key from Ranger DB to Azure Key Vault"));
+    }
+
+    @Test
+    void test01_MissingMasterKeyType_ShouldExit() {
+        assertExitsWithMessage(
+                new String[] {"azureKey", "", "AES", "https://vault", "clientId", "false", "password"},
+                "Azure master key type not provided.");
+    }
+
+    @Test
+    void test02_MissingZoneKeyAlgo_ShouldExit() {
+        assertExitsWithMessage(
+                new String[] {"azureKey", "RSA", "", "https://vault", "clientId", "false", "password"},
+                "Zone Key Encryption algorithm name not provided.");
+    }
+
+    @Test
+    void test03_MissingVaultUrl_ShouldExit() {
+        assertExitsWithMessage(
+                new String[] {"azureKey", "RSA", "AES", "", "clientId", "false", "password"},
+                "Azure Key Vault url not provided.");
+    }
+
+    @Test
+    void test04_MissingClientId_ShouldExit() {
+        assertExitsWithMessage(
+                new String[] {"azureKey", "RSA", "AES", "https://vault", "", "false", "password"},
+                "Azure Client Id is not provided.");
+    }
+
+    @Test
+    void test05_MissingIsSslEnabled_ShouldExit() {
+        assertExitsWithMessage(
+                new String[] {"azureKey", "RSA", "AES", "https://vault", "clientId", "", "password"},
+                "isSSLEnabled not provided.");
+    }
+
+    @Test
+    void test06_InvalidIsSslEnabled_ShouldExit() {
+        assertExitsWithMessage(
+                new String[] {"azureKey", "RSA", "AES", "https://vault", "clientId", "maybe", "password"},
+                "Please provide the valid value for isSSLEnabled");
+    }
+
+    @Test
+    void test07_MissingPasswordOrCert_ShouldExit() {
+        assertExitsWithMessage(
+                new String[] {"azureKey", "RSA", "AES", "https://vault", "clientId", "false", ""},
+                "Please provide Azure client password of certificate password");
+    }
+
+    @Test
+    void test08_InvalidCertExtension_ShouldExit() {
+        assertExitsWithMessage(
+                new String[] {"azureKey", "RSA", "AES", "https://vault", "clientId", "true", "notCert.txt"},
+                "Please provide valid certificate file path E.G .pem /.pfx");
+    }
+
+    @Test
+    void test09_InvalidCertExtension_ShouldExit() {
+        assertExitsWithMessage(
+                new String[] {"azureKey", "RSA", "AES", "https://vault", "clientId", "true", "notCert.txt", "turuturu", "ewgifug"},
+                "Please provide valid certificate file path E.G .pem /.pfx");
+    }
+
+    private void assertExitsWithMessage(String[] args, String expectedMsg) {
+        SecurityManager originalSM  = System.getSecurityManager();
+        PrintStream     originalErr = System.err;
+
+        ByteArrayOutputStream errBuf = new ByteArrayOutputStream();
+        System.setErr(new PrintStream(errBuf));
+
+        System.setSecurityManager(new SecurityManager() {
+            @Override
+            public void checkPermission(Permission perm) {}
+
+            @Override
+            public void checkExit(int status) {
+                throw new SecurityException("exit:" + status);
+            }
+        });
+
+        try {
+            DBToAzureKeyVault.main(args);
+            fail("Expected System.exit(1)");
+        } catch (SecurityException ex) {
+            assertEquals("exit:1", ex.getMessage());
+            assertTrue(errBuf.toString().contains(expectedMsg),
+                    "stderr did not contain: " + expectedMsg);
+        } finally {
+            System.setSecurityManager(originalSM);
+            System.setErr(originalErr);
+        }
+    }
+}
diff --git a/kms/src/test/java/org/apache/hadoop/crypto/key/kms/TestJKS2RangerUtil.java b/kms/src/test/java/org/apache/hadoop/crypto/key/kms/TestJKS2RangerUtil.java
new file mode 100644
index 000000000..b941b0511
--- /dev/null
+++ b/kms/src/test/java/org/apache/hadoop/crypto/key/kms/TestJKS2RangerUtil.java
@@ -0,0 +1,197 @@
+/*
+ * 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.hadoop.crypto.key.kms;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.crypto.key.JKS2RangerUtil;
+import org.apache.hadoop.crypto.key.RangerMasterKey;
+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.ByteArrayOutputStream;
+import java.io.File;
+import java.io.PrintStream;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.security.Permission;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.lenient;
+import static org.mockito.Mockito.mock;
+
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
+public class TestJKS2RangerUtil {
+    @Test
+    public void testGetFromJceks() throws Exception {
+        Configuration conf = new org.apache.hadoop.conf.Configuration();
+        conf.set("keystore.path", "mock/path/to/jceks.jceks");
+        conf.set("keystore.alias", "test-alias");
+
+        JKS2RangerUtil jKS2RangerUtil = new JKS2RangerUtil();
+
+        Method method = JKS2RangerUtil.class.getDeclaredMethod("getFromJceks", Configuration.class, String.class, String.class, String.class);
+        method.setAccessible(true);
+
+        String targetKey = "db.password";
+
+        method.invoke(jKS2RangerUtil, conf, "keystore.path", "keystore.alias", targetKey);
+    }
+
+    @Test
+    public void testDoImportKeysFromJKS_elseBranch() throws Exception {
+        JKS2RangerUtil util = new JKS2RangerUtil();
+
+        // Dummy config with no KeySecure or Azure enabled
+        Configuration conf = mock(Configuration.class);
+        lenient().when(conf.get("ranger.plugin.kms.encryption.key.password")).thenReturn("testpass");
+        lenient().when(conf.get(anyString())).thenReturn(null); // ensures keysecure/azure conditions fail
+
+        // Create a dummy keystore file
+        File dummyJceks = File.createTempFile("dummy", ".jceks");
+        dummyJceks.deleteOnExit();
+
+        Method method = JKS2RangerUtil.class.getDeclaredMethod("doImportKeysFromJKS", String.class, String.class);
+        method.setAccessible(true);
+
+        try {
+            method.invoke(util, dummyJceks.getAbsolutePath(), "jceks");
+            //
+        } catch (InvocationTargetException e) {
+            Throwable cause = e.getCause();
+            assertNotNull(cause);
+        }
+    }
+
+    @Test
+    public void testDoImportKeysFromJKS_if() throws Throwable {
+        JKS2RangerUtil util = new JKS2RangerUtil();
+
+        RangerMasterKey rangerMasterKey = mock(RangerMasterKey.class);
+        Method          method          = JKS2RangerUtil.class.getDeclaredMethod("doImportKeysFromJKS", String.class, String.class);
+        method.setAccessible(true);
+
+        try {
+            method.invoke(util, "nonexistent.jceks", "jceks");
+        } catch (InvocationTargetException e) {
+        }
+    }
+
+    @Test
+    public void testShowUsage() {
+        PrintStream originalErr = System.err;
+
+        ByteArrayOutputStream errContent = new ByteArrayOutputStream();
+        System.setErr(new PrintStream(errContent));
+
+        JKS2RangerUtil.showUsage();
+
+        System.setErr(originalErr);
+
+        String output = errContent.toString();
+
+        assertTrue(output.contains("USAGE: java " + JKS2RangerUtil.class.getName()));
+        assertTrue(output.contains("KeyStoreType"));
+        assertTrue(output.contains("keystore password"));
+        assertTrue(output.contains("key password"));
+    }
+
+    @Test
+    public void testMain_NoArgs_ShouldPrintUsageAndExit() {
+        SecurityManager originalSM  = System.getSecurityManager();
+        PrintStream     originalErr = System.err;
+
+        ByteArrayOutputStream errContent = new ByteArrayOutputStream();
+        System.setErr(new PrintStream(errContent));
+
+        System.setSecurityManager(new SecurityManager() {
+            public void checkPermission(Permission perm) {}
+
+            @Override
+            public void checkExit(int status) {
+                throw new SecurityException("Intercepted System.exit(" + status + ")");
+            }
+        });
+
+        try {
+            JKS2RangerUtil.main(new String[0]);
+            //
+        } catch (SecurityException ex) {
+            assertTrue(ex.getMessage().contains("Intercepted System.exit(1)"));
+        } finally {
+            System.setSecurityManager(originalSM);
+            System.setErr(originalErr);
+        }
+
+        String output = errContent.toString();
+        assertTrue(output.contains("Invalid number of parameters found."));
+        assertTrue(output.contains("USAGE: java " + JKS2RangerUtil.class.getName()));
+    }
+
+    @Test
+    public void testMain_FileNotExists_ShouldExit1() {
+        SecurityManager originalSM = System.getSecurityManager();
+        System.setSecurityManager(new SecurityManager() {
+            @Override
+            public void checkPermission(Permission perm) {}
+
+            @Override
+            public void checkExit(int status) {
+                throw new SecurityException("exit:" + status);
+            }
+        });
+
+        try {
+            JKS2RangerUtil.main(new String[] {"nonexistent.jceks", "jceks", "testpass", "testkeypass"});
+            //
+        } catch (SecurityException ex) {
+            assertTrue(ex.getMessage().contains("exit:1"));
+        } finally {
+            System.setSecurityManager(originalSM);
+        }
+    }
+
+    @Test
+    public void testDoImportKeysFromJKS_elseBranchcc() throws Exception {
+        JKS2RangerUtil util = new JKS2RangerUtil();
+
+        // Dummy config with no KeySecure or Azure enabled
+        Configuration conf = mock(Configuration.class);
+        lenient().when(conf.get("ranger.plugin.kms.encryption.key.password")).thenReturn("testpass");
+        lenient().when(conf.get(anyString())).thenReturn(null); // ensures keysecure/azure conditions fail
+
+        // Create a dummy keystore file
+        File dummyJceks = File.createTempFile("dummy", ".jceks");
+        dummyJceks.deleteOnExit();
+
+        Method method = JKS2RangerUtil.class.getDeclaredMethod("doImportKeysFromJKS", String.class, String.class);
+        method.setAccessible(true);
+
+        try {
+            method.invoke(util, dummyJceks.getAbsolutePath(), "jceks");
+            //
+        } catch (InvocationTargetException e) {
+            Throwable cause = e.getCause();
+            assertNotNull(cause);
+        }
+    }
+}
diff --git a/kms/src/test/java/org/apache/hadoop/crypto/key/kms/TestKeySecureToRangerDBMKUtil.java b/kms/src/test/java/org/apache/hadoop/crypto/key/kms/TestKeySecureToRangerDBMKUtil.java
new file mode 100644
index 000000000..c4a3a40a3
--- /dev/null
+++ b/kms/src/test/java/org/apache/hadoop/crypto/key/kms/TestKeySecureToRangerDBMKUtil.java
@@ -0,0 +1,198 @@
+/*
+ * 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.hadoop.crypto.key.kms;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.crypto.key.KeySecureToRangerDBMKUtil;
+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.ByteArrayOutputStream;
+import java.io.PrintStream;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+import static org.eclipse.persistence.jpa.jpql.Assert.fail;
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
+public class TestKeySecureToRangerDBMKUtil {
+    private final ByteArrayOutputStream errContent = new ByteArrayOutputStream();
+
+    @Test
+    public void testShowUsage() {
+        // Backup original System.err
+        PrintStream originalErr = System.err;
+
+        // Prepare to capture System.err
+        ByteArrayOutputStream errContent = new ByteArrayOutputStream();
+        System.setErr(new PrintStream(errContent));
+
+        try {
+            // Call method
+            KeySecureToRangerDBMKUtil.showUsage();
+
+            // Flush and verify output
+            System.err.flush();
+            String output = errContent.toString();
+            assertTrue(output.contains("USAGE: java "), "Expected usage message in System.err");
+        } finally {
+            System.setErr(originalErr);
+        }
+    }
+
+    @Test
+    public void testDoImportMKFromKeySecure() throws Exception {
+        KeySecureToRangerDBMKUtil keySecureToRangerDBMKUtil = new KeySecureToRangerDBMKUtil();
+        Method                    method                    = KeySecureToRangerDBMKUtil.class.getDeclaredMethod("doImportMKFromKeySecure", String.class);
+        method.setAccessible(true);
+        String[] args = new String[] {"testKeyAlias"};
+        try {
+            method.invoke(keySecureToRangerDBMKUtil, args[0]);
+        } catch (Exception e) {
+            // Handle exception if needed
+        }
+    }
+
+    @Test
+    void testGetFromJceks_whenAliasMissing_skipsCredentialReader() throws Exception {
+        Configuration confMock = mock(Configuration.class);
+
+        String pathProp   = "ranger.ks.jpa.jdbc.credential.provider.path";
+        String aliasProp  = "ranger.kms.keysecure.login.password.alias";
+        String resultProp = "ranger.kms.keysecure.login.password";
+
+        when(confMock.get(pathProp)).thenReturn("jceks://file/ignored.jceks");
+        when(confMock.get(aliasProp)).thenReturn("jceks://file/ignored.jceks!missingAlias");
+
+        Method m = KeySecureToRangerDBMKUtil.class
+                .getDeclaredMethod("getFromJceks",
+                        Configuration.class, String.class, String.class, String.class);
+        m.setAccessible(true);
+        m.invoke(null, confMock, pathProp, aliasProp, resultProp);
+    }
+
+    @Test
+    void testMain_invalidArgs_showsUsage_and_exit1() throws Exception {
+        // Capture System.err
+        PrintStream           originalErr = System.err;
+        ByteArrayOutputStream errBuf      = new ByteArrayOutputStream();
+        System.setErr(new PrintStream(errBuf));
+
+        // Intercept System.exit
+        SecurityManager originalSM = System.getSecurityManager();
+        System.setSecurityManager(new SecurityManager() {
+            @Override
+            public void checkPermission(java.security.Permission perm) {}
+
+            @Override
+            public void checkExit(int status) {
+                throw new SecurityException("exit:" + status);
+            }
+        });
+
+        try {
+            Method main = KeySecureToRangerDBMKUtil.class.getDeclaredMethod("main", String[].class);
+            try {
+                main.invoke(null, (Object) new String[0]); // invoke static main
+                fail("Expected SecurityException to be thrown");
+            } catch (InvocationTargetException ex) {
+                Throwable cause = ex.getCause();
+                assertInstanceOf(SecurityException.class, cause);
+                assertTrue(cause.getMessage().contains("exit:1"));
+            }
+
+            String stderr = errBuf.toString();
+            assertTrue(stderr.contains("USAGE: java "), "Expected usage message in stderr");
+        } finally {
+            System.setSecurityManager(originalSM);
+            System.setErr(originalErr);
+        }
+    }
+
+    @Test
+    void testMain_validArg_printsSuccess_and_exit0() throws Exception {
+        PrintStream           originalOut = System.out;
+        ByteArrayOutputStream outBuf      = new ByteArrayOutputStream();
+        System.setOut(new PrintStream(outBuf));
+
+        SecurityManager originalSM = System.getSecurityManager();
+        System.setSecurityManager(new SecurityManager() {
+            @Override
+            public void checkPermission(java.security.Permission perm) {}
+
+            @Override
+            public void checkExit(int status) {
+                throw new SecurityException("exit:" + status);
+            }
+        });
+
+        try {
+            Method main = KeySecureToRangerDBMKUtil.class.getDeclaredMethod("main", String[].class);
+            try {
+                main.invoke(null, (Object) new String[] {"dummyPassword"});
+                fail("Expected SecurityException due to System.exit");
+            } catch (InvocationTargetException ex) {
+                Throwable cause = ex.getCause();
+            }
+            outBuf.toString();
+        } finally {
+            System.setSecurityManager(originalSM);
+            System.setOut(originalOut);
+        }
+    }
+
+    @Test
+    void testMain_withEmptyPassword_shouldExit1() throws Exception {
+        SecurityManager       originalSM = System.getSecurityManager();
+        ByteArrayOutputStream errBuf     = new ByteArrayOutputStream();
+        System.setErr(new PrintStream(errBuf));
+
+        System.setSecurityManager(new SecurityManager() {
+            @Override
+            public void checkPermission(java.security.Permission perm) {}
+
+            @Override
+            public void checkExit(int status) {
+                throw new SecurityException("exit:" + status);
+            }
+        });
+
+        try {
+            Method main = KeySecureToRangerDBMKUtil.class.getDeclaredMethod("main", String[].class);
+            InvocationTargetException ex = assertThrows(
+                    InvocationTargetException.class,
+                    () -> main.invoke(null, (Object) new String[] {"  "}));
+            Throwable cause = ex.getCause();
+            assertInstanceOf(SecurityException.class, cause);
+            assertTrue(cause.getMessage().contains("exit:1"));
+            assertTrue(errBuf.toString().contains("KMS master key password not provided"));
+            assertTrue(errBuf.toString().contains("USAGE: java"));
+        } finally {
+            System.setErr(System.err);
+            System.setSecurityManager(originalSM);
+        }
+    }
+}
diff --git a/kms/src/test/java/org/apache/hadoop/crypto/key/kms/TestMigrateDBMKeyToGCP.java b/kms/src/test/java/org/apache/hadoop/crypto/key/kms/TestMigrateDBMKeyToGCP.java
new file mode 100644
index 000000000..d70d133f3
--- /dev/null
+++ b/kms/src/test/java/org/apache/hadoop/crypto/key/kms/TestMigrateDBMKeyToGCP.java
@@ -0,0 +1,113 @@
+/*
+ * 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.hadoop.crypto.key.kms;
+
+import org.apache.hadoop.crypto.key.MigrateDBMKeyToGCP;
+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.ByteArrayOutputStream;
+import java.io.PrintStream;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.security.Permission;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
+public class TestMigrateDBMKeyToGCP {
+    @Test
+    public void testShowUsage() throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
+        MigrateDBMKeyToGCP migrateDBMKeyToGCP = new MigrateDBMKeyToGCP();
+
+        Method method = MigrateDBMKeyToGCP.class.getDeclaredMethod("showUsage");
+        method.setAccessible(true);
+        method.invoke(migrateDBMKeyToGCP);
+    }
+
+    @Test
+    public void testMain_NoArgs_ShouldPrintUsageAndExit() {
+        SecurityManager originalSM  = System.getSecurityManager();
+        PrintStream     originalErr = System.err;
+
+        ByteArrayOutputStream errContent = new ByteArrayOutputStream();
+        System.setErr(new PrintStream(errContent));
+
+        System.setSecurityManager(new SecurityManager() {
+            @Override
+            public void checkPermission(Permission perm) {}
+
+            @Override
+            public void checkExit(int status) {
+                throw new SecurityException("Intercepted System.exit(" + status + ")");
+            }
+        });
+
+        try {
+            MigrateDBMKeyToGCP.main(new String[0]);
+            //
+        } catch (Exception ex) {
+            assertTrue(ex.getMessage().contains("Intercepted System.exit(1)"));
+        } finally {
+            System.setSecurityManager(originalSM);
+            System.setErr(originalErr);
+        }
+
+        String output = errContent.toString();
+        assertTrue(output.contains("Invalid number of parameters found."));
+        assertTrue(output.contains("USAGE: java " + MigrateDBMKeyToGCP.class.getName()));
+    }
+
+    @Test
+    public void testMain() throws Exception {
+        SecurityManager originalSM  = System.getSecurityManager();
+        PrintStream     originalErr = System.err;
+
+        ByteArrayOutputStream errContent = new ByteArrayOutputStream();
+        System.setErr(new PrintStream(errContent));
+
+        System.setSecurityManager(new SecurityManager() {
+            @Override
+            public void checkPermission(Permission perm) {}
+
+            @Override
+            public void checkExit(int status) {
+                throw new SecurityException("Intercepted System.exit(" + status + ")");
+            }
+        });
+
+        String[] args = {
+                "gcpMasterKeyName",
+                "gcpProjectId",
+                "gcpKeyRingId",
+                "gcpKeyRingLocationId",
+                "pathOfJsonCredFile"
+        };
+        try {
+            MigrateDBMKeyToGCP.main(args);
+            //
+        } catch (Exception ex) {
+        } finally {
+            System.setSecurityManager(originalSM);
+            System.setErr(originalErr);
+        }
+    }
+}
diff --git a/kms/src/test/java/org/apache/hadoop/crypto/key/kms/TestRanger2JKSUtil.java b/kms/src/test/java/org/apache/hadoop/crypto/key/kms/TestRanger2JKSUtil.java
new file mode 100644
index 000000000..7792f09cc
--- /dev/null
+++ b/kms/src/test/java/org/apache/hadoop/crypto/key/kms/TestRanger2JKSUtil.java
@@ -0,0 +1,74 @@
+/*
+ * 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.hadoop.crypto.key.kms;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.crypto.key.Ranger2JKSUtil;
+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.lang.reflect.Method;
+
+import static org.junit.jupiter.api.Assertions.fail;
+
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
+public class TestRanger2JKSUtil {
+    @Test
+    public void testShowUsage() {
+        Ranger2JKSUtil ranger2JKSUtil = new Ranger2JKSUtil();
+        Ranger2JKSUtil.showUsage();
+    }
+
+    @Test
+    public void testDoExportKeysFromJKS() throws NoSuchMethodException {
+        Ranger2JKSUtil ranger2JKSUtil = new Ranger2JKSUtil();
+        String[]       args           = {"-jks", "test.jks", "-out", "output.txt"};
+
+        Method method = Ranger2JKSUtil.class.getDeclaredMethod(
+                "doExportKeysFromJKS", String.class, String.class);
+        method.setAccessible(true);
+        try {
+            method.invoke(ranger2JKSUtil, args[1], args[3]);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    @Test
+    public void testGetFromJceks() throws NoSuchMethodException {
+        Ranger2JKSUtil ranger2JKSUtil = new Ranger2JKSUtil();
+        Configuration  conf           = new Configuration();
+        String         path           = "test.jceks";
+        String         alias          = "testAlias";
+        String         key            = "testKey";
+
+        Method method = Ranger2JKSUtil.class.getDeclaredMethod(
+                "getFromJceks", Configuration.class, String.class, String.class, String.class);
+
+        method.setAccessible(true);
+        try {
+            method.invoke(ranger2JKSUtil, conf, path, alias, key);
+        } catch (Exception e) {
+            e.printStackTrace();
+            fail("Method invocation failed: " + e.getMessage());
+        }
+    }
+}
diff --git a/kms/src/test/java/org/apache/hadoop/crypto/key/kms/TestRangerAzureKeyVaultKeyGenerator.java b/kms/src/test/java/org/apache/hadoop/crypto/key/kms/TestRangerAzureKeyVaultKeyGenerator.java
new file mode 100644
index 000000000..4031c0ba2
--- /dev/null
+++ b/kms/src/test/java/org/apache/hadoop/crypto/key/kms/TestRangerAzureKeyVaultKeyGenerator.java
@@ -0,0 +1,392 @@
+/*
+ * 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.hadoop.crypto.key.kms;
+
+import com.microsoft.azure.keyvault.webkey.JsonWebKeyEncryptionAlgorithm;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.crypto.key.RangerAzureKeyVaultKeyGenerator;
+import org.junit.jupiter.api.BeforeEach;
+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 javax.crypto.KeyGenerator;
+import javax.crypto.SecretKey;
+
+import java.lang.reflect.Method;
+import java.security.NoSuchAlgorithmException;
+
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
+public class TestRangerAzureKeyVaultKeyGenerator {
+    private static final String        VALID_VAULT_URL     = "https://test-keyvault.vault.azure.net/";
+    private static final String        VALID_MASTER_KEY    = "test-master-key";
+    private static final String        VALID_CLIENT_ID     = "test-client-id";
+    private static final String        VALID_CLIENT_SECRET = "test-client-secret";
+    private static final String        VALID_CERT_PATH     = "/path/to/cert.pfx";
+    private static final String        VALID_CERT_PASSWORD = "cert-password";
+    private              Configuration configuration;
+
+    @BeforeEach
+    public void setUp() {
+        configuration = new Configuration();
+    }
+
+    @Test
+    public void testConstructorWithValidConfigurationAndNullClient() {
+        setValidConfiguration();
+
+        assertDoesNotThrow(() -> {
+            RangerAzureKeyVaultKeyGenerator generator = new RangerAzureKeyVaultKeyGenerator(configuration, null);
+            assertNotNull(generator);
+        });
+    }
+
+    @Test
+    public void testConstructorWithConfiguration() throws Exception {
+        setValidConfiguration();
+
+        // This will fail because we don't have actual Azure credentials, but should not throw during construction
+        Exception exception = assertThrows(Exception.class, () -> {
+            RangerAzureKeyVaultKeyGenerator generator = new RangerAzureKeyVaultKeyGenerator(configuration);
+        });
+
+        assertNotNull(exception);
+    }
+
+    @Test
+    public void testCreateKeyVaultClientWithEmptyClientId() {
+        setValidConfiguration();
+        configuration.unset("ranger.kms.azure.client.id");
+
+        Exception exception = assertThrows(Exception.class, () -> {
+            RangerAzureKeyVaultKeyGenerator.createKeyVaultClient(configuration);
+        });
+
+        assertTrue(exception.getMessage().contains("client id is not configured"));
+    }
+
+    @Test
+    public void testCreateKeyVaultClientWithNullClientId() {
+        setValidConfiguration();
+        configuration.set("ranger.kms.azure.client.id", "");
+
+        Exception exception = assertThrows(Exception.class, () -> {
+            RangerAzureKeyVaultKeyGenerator.createKeyVaultClient(configuration);
+        });
+
+        assertTrue(exception.getMessage().contains("client id is not configured"));
+    }
+
+    @Test
+    public void testCreateKeyVaultClientWithNullConfiguration() {
+        Exception exception = assertThrows(Exception.class, () -> {
+            RangerAzureKeyVaultKeyGenerator.createKeyVaultClient(null);
+        });
+
+        assertNotNull(exception);
+    }
+
+    @Test
+    public void testCreateKeyVaultClientSSLDisabledWithoutSecret() {
+        setValidConfiguration();
+        configuration.set("ranger.kms.azure.keyvault.ssl.enabled", "false");
+        configuration.unset("ranger.kms.azure.client.secret");
+
+        Exception exception = assertThrows(Exception.class, () -> {
+            RangerAzureKeyVaultKeyGenerator.createKeyVaultClient(configuration);
+        });
+
+        assertTrue(exception.getMessage().contains("client password/secret is not configured"));
+    }
+
+    @Test
+    public void testCreateKeyVaultClientSSLDisabledWithEmptySecret() {
+        setValidConfiguration();
+        configuration.set("ranger.kms.azure.keyvault.ssl.enabled", "false");
+        configuration.set("ranger.kms.azure.client.secret", "");
+
+        Exception exception = assertThrows(Exception.class, () -> {
+            RangerAzureKeyVaultKeyGenerator.createKeyVaultClient(configuration);
+        });
+
+        assertTrue(exception.getMessage().contains("client password/secret is not configured"));
+    }
+
+    @Test
+    public void testCreateKeyVaultClientSSLEnabledWithoutCertPath() {
+        setValidConfiguration();
+        configuration.set("ranger.kms.azure.keyvault.ssl.enabled", "true");
+        configuration.unset("ranger.kms.azure.keyvault.certificate.path");
+
+        Exception exception = assertThrows(Exception.class, () -> {
+            RangerAzureKeyVaultKeyGenerator.createKeyVaultClient(configuration);
+        });
+
+        assertTrue(exception.getMessage().contains("Please provide certificate path for authentication"));
+    }
+
+    @Test
+    public void testCreateKeyVaultClientSSLEnabledWithEmptyCertPath() {
+        setValidConfiguration();
+        configuration.set("ranger.kms.azure.keyvault.ssl.enabled", "true");
+        configuration.set("ranger.kms.azure.keyvault.certificate.path", "");
+
+        Exception exception = assertThrows(Exception.class, () -> {
+            RangerAzureKeyVaultKeyGenerator.createKeyVaultClient(configuration);
+        });
+
+        assertTrue(exception.getMessage().contains("Please provide certificate path for authentication"));
+    }
+
+    @Test
+    public void testCreateKeyVaultClientSSLDefaultEnabledWithoutCertPath() {
+        setValidConfiguration();
+        // Don't set SSL enabled, should default to true
+        configuration.unset("ranger.kms.azure.keyvault.certificate.path");
+
+        Exception exception = assertThrows(Exception.class, () -> {
+            RangerAzureKeyVaultKeyGenerator.createKeyVaultClient(configuration);
+        });
+
+        assertTrue(exception.getMessage().contains("Please provide certificate path for authentication"));
+    }
+
+    @Test
+    public void testGetMasterKeyReturnsNull() {
+        setValidConfiguration();
+
+        RangerAzureKeyVaultKeyGenerator generator = new RangerAzureKeyVaultKeyGenerator(configuration, null);
+
+        String result = generator.getMasterKey("test-secret");
+
+        assertNull(result, "getMasterKey should always return null for Azure Key Vault");
+    }
+
+    @Test
+    public void testGetMasterKeyWithNullParameter() {
+        setValidConfiguration();
+
+        RangerAzureKeyVaultKeyGenerator generator = new RangerAzureKeyVaultKeyGenerator(configuration, null);
+
+        String result = generator.getMasterKey(null);
+
+        assertNull(result, "getMasterKey should always return null for Azure Key Vault");
+    }
+
+    @Test
+    public void testGetMasterKeyWithEmptyParameter() {
+        setValidConfiguration();
+
+        RangerAzureKeyVaultKeyGenerator generator = new RangerAzureKeyVaultKeyGenerator(configuration, null);
+
+        String result = generator.getMasterKey("");
+
+        assertNull(result, "getMasterKey should always return null for Azure Key Vault");
+    }
+
+    @Test
+    public void testGenerateMasterKeyWithNullClient() {
+        setValidConfiguration();
+
+        RangerAzureKeyVaultKeyGenerator generator = new RangerAzureKeyVaultKeyGenerator(configuration, null);
+
+        Exception exception = assertThrows(Exception.class, () -> {
+            generator.generateMasterKey("password");
+        });
+
+        assertTrue(exception.getMessage().contains("Key Vault Client is null"));
+    }
+
+    @Test
+    public void testGenerateMasterKeyWithNullPassword() {
+        setValidConfiguration();
+
+        RangerAzureKeyVaultKeyGenerator generator = new RangerAzureKeyVaultKeyGenerator(configuration, null);
+
+        Exception exception = assertThrows(Exception.class, () -> {
+            generator.generateMasterKey(null);
+        });
+
+        assertTrue(exception.getMessage().contains("Key Vault Client is null"));
+    }
+
+    @Test
+    public void testGenerateMasterKeyWithEmptyPassword() {
+        setValidConfiguration();
+
+        RangerAzureKeyVaultKeyGenerator generator = new RangerAzureKeyVaultKeyGenerator(configuration, null);
+
+        Exception exception = assertThrows(Exception.class, () -> {
+            generator.generateMasterKey("");
+        });
+
+        assertTrue(exception.getMessage().contains("Key Vault Client is null"));
+    }
+
+    @Test
+    public void testEncryptZoneKeyWithNullClient() {
+        setValidConfiguration();
+
+        RangerAzureKeyVaultKeyGenerator generator = new RangerAzureKeyVaultKeyGenerator(configuration, null);
+
+        assertThrows(Exception.class, () -> {
+            generator.encryptZoneKey(generateTestKey());
+        });
+    }
+
+    @Test
+    public void testEncryptZoneKeyWithNullKey() {
+        setValidConfiguration();
+
+        RangerAzureKeyVaultKeyGenerator generator = new RangerAzureKeyVaultKeyGenerator(configuration, null);
+
+        assertThrows(Exception.class, () -> {
+            generator.encryptZoneKey(null);
+        });
+    }
+
+    @Test
+    public void testDecryptZoneKeyWithNullClient() {
+        setValidConfiguration();
+
+        RangerAzureKeyVaultKeyGenerator generator = new RangerAzureKeyVaultKeyGenerator(configuration, null);
+
+        assertThrows(Exception.class, () -> {
+            generator.decryptZoneKey("test".getBytes());
+        });
+    }
+
+    @Test
+    public void testDecryptZoneKeyWithNullData() {
+        setValidConfiguration();
+
+        RangerAzureKeyVaultKeyGenerator generator = new RangerAzureKeyVaultKeyGenerator(configuration, null);
+
+        assertThrows(Exception.class, () -> {
+            generator.decryptZoneKey(null);
+        });
+    }
+
+    @Test
+    public void testDecryptZoneKeyWithEmptyData() {
+        setValidConfiguration();
+
+        RangerAzureKeyVaultKeyGenerator generator = new RangerAzureKeyVaultKeyGenerator(configuration, null);
+
+        assertThrows(Exception.class, () -> {
+            generator.decryptZoneKey(new byte[0]);
+        });
+    }
+
+    @Test
+    public void testGetZoneKeyEncryptionAlgoWithDifferentAlgorithms() throws Exception {
+        setValidConfiguration();
+
+        String[] algorithms = {"RSA_OAEP", "RSA_OAEP_256", "RSA1_5", "INVALID_ALGO"};
+        JsonWebKeyEncryptionAlgorithm[] expectedAlgos = {
+                JsonWebKeyEncryptionAlgorithm.RSA_OAEP,
+                JsonWebKeyEncryptionAlgorithm.RSA_OAEP_256,
+                JsonWebKeyEncryptionAlgorithm.RSA1_5,
+                JsonWebKeyEncryptionAlgorithm.RSA_OAEP // default
+        };
+
+        for (int i = 0; i < algorithms.length; i++) {
+            configuration.set("ranger.kms.azure.zonekey.encryption.algorithm", algorithms[i]);
+
+            RangerAzureKeyVaultKeyGenerator generator = new RangerAzureKeyVaultKeyGenerator(configuration, null);
+
+            // Use reflection to test the private method
+            Method getZoneKeyEncryptionAlgoMethod = RangerAzureKeyVaultKeyGenerator.class.getDeclaredMethod("getZoneKeyEncryptionAlgo");
+            getZoneKeyEncryptionAlgoMethod.setAccessible(true);
+
+            JsonWebKeyEncryptionAlgorithm result = (JsonWebKeyEncryptionAlgorithm) getZoneKeyEncryptionAlgoMethod.invoke(generator);
+
+            assertEquals(expectedAlgos[i], result, "Algorithm should match for input: " + algorithms[i]);
+        }
+    }
+
+    @Test
+    public void testCreateKeyVaultClientWithValidSSLEnabledConfiguration() {
+        setValidConfiguration();
+        configuration.set("ranger.kms.azure.keyvault.ssl.enabled", "true");
+        configuration.set("ranger.kms.azure.keyvault.certificate.path", VALID_CERT_PATH);
+
+        // This will fail because we don't have actual Azure credentials, but should not fail on validation
+        Exception exception = assertThrows(Exception.class, () -> {
+            RangerAzureKeyVaultKeyGenerator.createKeyVaultClient(configuration);
+        });
+
+        // Should not be a configuration validation error but rather an authentication error
+        assertFalse(exception.getMessage().contains("client id is not configured"));
+        assertFalse(exception.getMessage().contains("Please provide certificate path for authentication"));
+    }
+
+    @Test
+    public void testCreateKeyVaultClientWithCertificatePassword() {
+        setValidConfiguration();
+        configuration.set("ranger.kms.azure.keyvault.ssl.enabled", "true");
+        configuration.set("ranger.kms.azure.keyvault.certificate.path", VALID_CERT_PATH);
+        configuration.set("ranger.kms.azure.keyvault.certificate.password", VALID_CERT_PASSWORD);
+
+        // This will fail because we don't have actual Azure credentials, but should not fail on validation
+        Exception exception = assertThrows(Exception.class, () -> {
+            RangerAzureKeyVaultKeyGenerator.createKeyVaultClient(configuration);
+        });
+
+        // Should not be a configuration validation error
+        assertFalse(exception.getMessage().contains("client id is not configured"));
+        assertFalse(exception.getMessage().contains("Please provide certificate path for authentication"));
+    }
+
+    @Test
+    public void testConfigurationValuesAreSetCorrectly() {
+        setValidConfiguration();
+
+        // Test that constructor accepts and uses the configuration values
+        assertDoesNotThrow(() -> {
+            RangerAzureKeyVaultKeyGenerator generator = new RangerAzureKeyVaultKeyGenerator(configuration, null);
+            assertNotNull(generator);
+        });
+    }
+
+    private void setValidConfiguration() {
+        configuration.set("ranger.kms.azurekeyvault.url", VALID_VAULT_URL);
+        configuration.set("ranger.kms.azure.masterkey.name", VALID_MASTER_KEY);
+        configuration.set("ranger.kms.azure.masterkey.type", "RSA");
+        configuration.set("ranger.kms.azure.zonekey.encryption.algorithm", "RSA_OAEP");
+        configuration.set("ranger.kms.azure.client.id", VALID_CLIENT_ID);
+        configuration.set("ranger.kms.azure.client.secret", VALID_CLIENT_SECRET);
+    }
+
+    private SecretKey generateTestKey() throws NoSuchAlgorithmException {
+        KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
+        keyGenerator.init(256);
+        return keyGenerator.generateKey();
+    }
+}
diff --git a/kms/src/test/java/org/apache/hadoop/crypto/key/kms/TestRangerGoogleCloudHSMProvider.java b/kms/src/test/java/org/apache/hadoop/crypto/key/kms/TestRangerGoogleCloudHSMProvider.java
new file mode 100644
index 000000000..988cce338
--- /dev/null
+++ b/kms/src/test/java/org/apache/hadoop/crypto/key/kms/TestRangerGoogleCloudHSMProvider.java
@@ -0,0 +1,380 @@
+/*
+ * 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.hadoop.crypto.key.kms;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.crypto.key.RangerGoogleCloudHSMProvider;
+import org.bouncycastle.crypto.RuntimeCryptoException;
+import org.junit.jupiter.api.BeforeEach;
+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 javax.crypto.KeyGenerator;
+import javax.crypto.SecretKey;
+
+import java.lang.reflect.Method;
+import java.security.NoSuchAlgorithmException;
+
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
+public class TestRangerGoogleCloudHSMProvider {
+    private static final String        VALID_PROJECT_ID      = "test-project-id";
+    private static final String        VALID_LOCATION_ID     = "us-central1";
+    private static final String        VALID_KEYRING_ID      = "test-keyring";
+    private static final String        VALID_MASTER_KEY_NAME = "test-master-key";
+    private static final String        VALID_CRED_FILE       = "/path/to/credentials.json";
+    private static final String        INVALID_CRED_FILE     = "/path/to/credentials.txt";
+    private              Configuration configuration;
+
+    @BeforeEach
+    public void setUp() {
+        configuration = new Configuration();
+    }
+
+    @Test
+    public void testConstructorWithValidConfiguration() throws Exception {
+        setValidConfiguration();
+
+        RangerGoogleCloudHSMProvider provider = new RangerGoogleCloudHSMProvider(configuration);
+
+        assertNotNull(provider);
+    }
+
+    @Test
+    public void testConstructorWithNullConfiguration() {
+        assertThrows(NullPointerException.class, () -> {
+            RangerGoogleCloudHSMProvider provider = new RangerGoogleCloudHSMProvider(null);
+        });
+    }
+
+    @Test
+    public void testValidateGcpPropsWithValidConfiguration() throws Exception {
+        setValidConfiguration();
+
+        RangerGoogleCloudHSMProvider provider = new RangerGoogleCloudHSMProvider(configuration);
+
+        Method validateMethod = RangerGoogleCloudHSMProvider.class.getDeclaredMethod("validateGcpProps");
+        validateMethod.setAccessible(true);
+
+        assertDoesNotThrow(() -> {
+            validateMethod.invoke(provider);
+        });
+    }
+
+    @Test
+    public void testValidateGcpPropsWithInvalidCredentialFile() throws Exception {
+        setValidConfiguration();
+        configuration.set("ranger.kms.gcp.cred.file", INVALID_CRED_FILE);
+
+        RangerGoogleCloudHSMProvider provider = new RangerGoogleCloudHSMProvider(configuration);
+
+        Method validateMethod = RangerGoogleCloudHSMProvider.class.getDeclaredMethod("validateGcpProps");
+        validateMethod.setAccessible(true);
+
+        Exception exception = assertThrows(Exception.class, () ->
+                validateMethod.invoke(provider));
+
+        Throwable cause = exception.getCause();
+        assertInstanceOf(RuntimeCryptoException.class, cause);
+        assertTrue(cause.getMessage().contains("Invalid GCP app Credential JSON file"));
+    }
+
+    @Test
+    public void testValidateGcpPropsWithEmptyCredentialFile() throws Exception {
+        setValidConfiguration();
+        configuration.set("ranger.kms.gcp.cred.file", "");
+
+        RangerGoogleCloudHSMProvider provider = new RangerGoogleCloudHSMProvider(configuration);
+
+        Method validateMethod = RangerGoogleCloudHSMProvider.class.getDeclaredMethod("validateGcpProps");
+        validateMethod.setAccessible(true);
+
+        Exception exception = assertThrows(Exception.class, () ->
+                validateMethod.invoke(provider));
+
+        Throwable cause = exception.getCause();
+        assertInstanceOf(RuntimeCryptoException.class, cause);
+        assertTrue(cause.getMessage().contains("Invalid GCP app Credential JSON file"));
+    }
+
+    @Test
+    public void testValidateGcpPropsWithEmptyKeyRingId() throws Exception {
+        setValidConfiguration();
+        configuration.set("ranger.kms.gcp.keyring.id", "");
+
+        RangerGoogleCloudHSMProvider provider = new RangerGoogleCloudHSMProvider(configuration);
+
+        Method validateMethod = RangerGoogleCloudHSMProvider.class.getDeclaredMethod("validateGcpProps");
+        validateMethod.setAccessible(true);
+
+        Exception exception = assertThrows(Exception.class, () ->
+                validateMethod.invoke(provider));
+
+        Throwable cause = exception.getCause();
+        assertInstanceOf(RuntimeCryptoException.class, cause);
+        assertTrue(cause.getMessage().contains("Please provide GCP app KeyringId"));
+    }
+
+    @Test
+    public void testValidateGcpPropsWithEmptyLocationId() throws Exception {
+        setValidConfiguration();
+        configuration.set("ranger.kms.gcp.location.id", "");
+
+        RangerGoogleCloudHSMProvider provider = new RangerGoogleCloudHSMProvider(configuration);
+
+        Method validateMethod = RangerGoogleCloudHSMProvider.class.getDeclaredMethod("validateGcpProps");
+        validateMethod.setAccessible(true);
+
+        Exception exception = assertThrows(Exception.class, () ->
+                validateMethod.invoke(provider));
+
+        Throwable cause = exception.getCause();
+        assertInstanceOf(RuntimeCryptoException.class, cause);
+        assertTrue(cause.getMessage().contains("Please provide the GCP app location Id"));
+    }
+
+    @Test
+    public void testValidateGcpPropsWithEmptyProjectId() throws Exception {
+        setValidConfiguration();
+        configuration.set("ranger.kms.gcp.project.id", "");
+
+        RangerGoogleCloudHSMProvider provider = new RangerGoogleCloudHSMProvider(configuration);
+
+        Method validateMethod = RangerGoogleCloudHSMProvider.class.getDeclaredMethod("validateGcpProps");
+        validateMethod.setAccessible(true);
+
+        Exception exception = assertThrows(Exception.class, () ->
+                validateMethod.invoke(provider));
+
+        Throwable cause = exception.getCause();
+        assertInstanceOf(RuntimeCryptoException.class, cause);
+        assertTrue(cause.getMessage().contains("Please provide the GCP app project Id"));
+    }
+
+    @Test
+    public void testValidateGcpPropsWithEmptyMasterKeyName() throws Exception {
+        setValidConfiguration();
+        configuration.set("ranger.kms.gcp.masterkey.name", "");
+
+        RangerGoogleCloudHSMProvider provider = new RangerGoogleCloudHSMProvider(configuration);
+
+        Method validateMethod = RangerGoogleCloudHSMProvider.class.getDeclaredMethod("validateGcpProps");
+        validateMethod.setAccessible(true);
+
+        Exception exception = assertThrows(Exception.class, () -> {
+            validateMethod.invoke(provider);
+        });
+
+        Throwable cause = exception.getCause();
+        assertInstanceOf(RuntimeCryptoException.class, cause);
+        assertTrue(cause.getMessage().contains("Master key name must not be empty"));
+    }
+
+    @Test
+    public void testValidateGcpPropsWithNullValues() throws Exception {
+        RangerGoogleCloudHSMProvider provider = new RangerGoogleCloudHSMProvider(configuration);
+
+        Method validateMethod = RangerGoogleCloudHSMProvider.class.getDeclaredMethod("validateGcpProps");
+        validateMethod.setAccessible(true);
+
+        Exception exception = assertThrows(Exception.class, () -> {
+            validateMethod.invoke(provider);
+        });
+
+        Throwable cause = exception.getCause();
+        assertInstanceOf(RuntimeCryptoException.class, cause);
+        assertTrue(cause.getMessage().contains("Invalid GCP app Credential JSON file"));
+    }
+
+    @Test
+    public void testGetMasterKeyReturnsNull() throws Throwable {
+        setValidConfiguration();
+
+        RangerGoogleCloudHSMProvider provider = new RangerGoogleCloudHSMProvider(configuration);
+
+        String result = provider.getMasterKey("test-password");
+
+        assertNull(result, "getMasterKey should return null as master key cannot be retrieved from GCP HSM");
+    }
+
+    @Test
+    public void testGetMasterKeyWithNullPassword() throws Throwable {
+        setValidConfiguration();
+
+        RangerGoogleCloudHSMProvider provider = new RangerGoogleCloudHSMProvider(configuration);
+
+        String result = provider.getMasterKey(null);
+
+        assertNull(result, "getMasterKey should return null regardless of password input");
+    }
+
+    @Test
+    public void testGetMasterKeyWithEmptyPassword() throws Throwable {
+        setValidConfiguration();
+
+        RangerGoogleCloudHSMProvider provider = new RangerGoogleCloudHSMProvider(configuration);
+
+        String result = provider.getMasterKey("");
+
+        assertNull(result, "getMasterKey should return null regardless of password input");
+    }
+
+    @Test
+    public void testEncryptZoneKeyWithNullKey() throws Exception {
+        setValidConfiguration();
+
+        RangerGoogleCloudHSMProvider provider = new RangerGoogleCloudHSMProvider(configuration);
+
+        assertThrows(Exception.class, () -> {
+            provider.encryptZoneKey(null);
+        });
+    }
+
+    @Test
+    public void testDecryptZoneKeyWithNullBytes() throws Exception {
+        setValidConfiguration();
+
+        RangerGoogleCloudHSMProvider provider = new RangerGoogleCloudHSMProvider(configuration);
+
+        assertThrows(Exception.class, () -> {
+            provider.decryptZoneKey(null);
+        });
+    }
+
+    @Test
+    public void testDecryptZoneKeyWithEmptyBytes() throws Exception {
+        setValidConfiguration();
+
+        RangerGoogleCloudHSMProvider provider = new RangerGoogleCloudHSMProvider(configuration);
+
+        assertThrows(Exception.class, () ->
+                provider.decryptZoneKey(new byte[0]));
+    }
+
+    @Test
+    public void testOnInitializationWithInvalidConfiguration() throws Exception {
+        RangerGoogleCloudHSMProvider provider = new RangerGoogleCloudHSMProvider(configuration);
+
+        RuntimeCryptoException exception = assertThrows(RuntimeCryptoException.class, () -> {
+            provider.onInitialization();
+        });
+
+        assertNotNull(exception.getMessage());
+        assertTrue(exception.getMessage().contains("Invalid GCP app Credential JSON file") ||
+                exception.getMessage().contains("Please provide"));
+    }
+
+    @Test
+    public void testGenerateMasterKeyWithValidConfiguration() throws Exception {
+        setValidConfiguration();
+
+        RangerGoogleCloudHSMProvider provider = new RangerGoogleCloudHSMProvider(configuration);
+
+        assertThrows(Exception.class, () ->
+                provider.generateMasterKey("test-password"));
+    }
+
+    @Test
+    public void testGenerateMasterKeyWithNullPassword() throws Exception {
+        setValidConfiguration();
+
+        RangerGoogleCloudHSMProvider provider = new RangerGoogleCloudHSMProvider(configuration);
+
+        assertThrows(Exception.class, () ->
+                provider.generateMasterKey(null));
+    }
+
+    @Test
+    public void testGenerateMasterKeyWithEmptyPassword() throws Exception {
+        setValidConfiguration();
+
+        RangerGoogleCloudHSMProvider provider = new RangerGoogleCloudHSMProvider(configuration);
+
+        assertThrows(Exception.class, () ->
+                provider.generateMasterKey(""));
+    }
+
+    @Test
+    public void testEncryptZoneKeyWithValidKey() throws Exception {
+        setValidConfiguration();
+
+        RangerGoogleCloudHSMProvider provider = new RangerGoogleCloudHSMProvider(configuration);
+
+        SecretKey testKey = generateTestKey();
+
+        assertThrows(Exception.class, () ->
+                provider.encryptZoneKey(testKey));
+    }
+
+    @Test
+    public void testConfigurationPropertiesAreUsed() {
+        setValidConfiguration();
+
+        assertDoesNotThrow(() -> {
+            RangerGoogleCloudHSMProvider provider = new RangerGoogleCloudHSMProvider(configuration);
+            assertNotNull(provider);
+        });
+    }
+
+    @Test
+    public void testPrivateGetKeyClientMethod() throws Exception {
+        setValidConfiguration();
+
+        RangerGoogleCloudHSMProvider provider = new RangerGoogleCloudHSMProvider(configuration);
+
+        Method getKeyClientMethod = RangerGoogleCloudHSMProvider.class.getDeclaredMethod("getKeyClient", String.class);
+        getKeyClientMethod.setAccessible(true);
+
+        Object result = getKeyClientMethod.invoke(provider, VALID_CRED_FILE);
+
+        assertNull(result, "getKeyClient should return null when credentials are invalid or file doesn't exist");
+    }
+
+    @Test
+    public void testUpdateEnvMethod() throws Exception {
+        Method updateEnvMethod = RangerGoogleCloudHSMProvider.class.getDeclaredMethod("updateEnv", String.class, String.class);
+        updateEnvMethod.setAccessible(true);
+
+        assertDoesNotThrow(() -> {
+            updateEnvMethod.invoke(null, "TEST_ENV_VAR", "test_value");
+        });
+    }
+
+    private void setValidConfiguration() {
+        configuration.set("ranger.kms.gcp.project.id", VALID_PROJECT_ID);
+        configuration.set("ranger.kms.gcp.location.id", VALID_LOCATION_ID);
+        configuration.set("ranger.kms.gcp.keyring.id", VALID_KEYRING_ID);
+        configuration.set("ranger.kms.gcp.masterkey.name", VALID_MASTER_KEY_NAME);
+        configuration.set("ranger.kms.gcp.cred.file", VALID_CRED_FILE);
+    }
+
+    private SecretKey generateTestKey() throws NoSuchAlgorithmException {
+        KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
+        keyGenerator.init(256);
+        return keyGenerator.generateKey();
+    }
+}
diff --git a/kms/src/test/java/org/apache/hadoop/crypto/key/kms/TestRangerKeyStore.java b/kms/src/test/java/org/apache/hadoop/crypto/key/kms/TestRangerKeyStore.java
index 333fbc206..7be4f7fa4 100644
--- a/kms/src/test/java/org/apache/hadoop/crypto/key/kms/TestRangerKeyStore.java
+++ b/kms/src/test/java/org/apache/hadoop/crypto/key/kms/TestRangerKeyStore.java
@@ -17,8 +17,14 @@
 
 package org.apache.hadoop.crypto.key.kms;
 
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.crypto.key.KeyProvider;
+import org.apache.hadoop.crypto.key.RangerAzureKeyVaultKeyGenerator;
 import org.apache.hadoop.crypto.key.RangerKeyStore;
+import org.apache.hadoop.crypto.key.RangerMasterKey;
+import org.apache.ranger.entity.XXRangerKeyStore;
 import org.apache.ranger.kms.dao.DaoManager;
+import org.apache.ranger.kms.dao.RangerKMSDao;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.BeforeEach;
@@ -26,21 +32,51 @@
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.TestMethodOrder;
 import org.junit.jupiter.api.extension.ExtendWith;
-import org.mockito.Mockito;
 import org.mockito.junit.jupiter.MockitoExtension;
 
 import javax.crypto.KeyGenerator;
 
+import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.nio.charset.StandardCharsets;
 import java.security.Key;
 import java.security.KeyStore;
 import java.security.KeyStoreException;
 import java.security.NoSuchAlgorithmException;
+import java.security.cert.Certificate;
 import java.security.cert.CertificateException;
+import java.util.Collections;
+import java.util.Date;
+import java.util.Map;
+
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNotSame;
+import static org.junit.jupiter.api.Assertions.assertNull;
+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.eq;
+import static org.mockito.Mockito.anyString;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.lenient;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 @ExtendWith(MockitoExtension.class)
 @TestMethodOrder(MethodOrderer.MethodName.class)
@@ -63,7 +99,7 @@ public void cleanKeystoreFile() {
 
     @Test
     public void testInvalidKey1() {
-        DaoManager     daoManager     = Mockito.mock(DaoManager.class);
+        DaoManager     daoManager     = mock(DaoManager.class);
         RangerKeyStore rangerKeyStore = new RangerKeyStore(daoManager);
         String         keyValue       = "enckey:1";
         Exception exception = Assertions.assertThrows(IOException.class, () -> {
@@ -75,7 +111,7 @@ public void testInvalidKey1() {
 
     @Test
     public void testInvalidKey2() throws NoSuchAlgorithmException, CertificateException, IOException, KeyStoreException {
-        DaoManager     daoManager     = Mockito.mock(DaoManager.class);
+        DaoManager     daoManager     = mock(DaoManager.class);
         RangerKeyStore rangerKeyStore = new RangerKeyStore(daoManager);
         String         keyValue       = "1%enckey";
         Assertions.assertThrows(IOException.class, () -> {
@@ -87,7 +123,7 @@ public void testInvalidKey2() throws NoSuchAlgorithmException, CertificateExcept
 
     @Test
     public void testInvalidKey3() throws NoSuchAlgorithmException, CertificateException, IOException, KeyStoreException {
-        DaoManager     daoManager     = Mockito.mock(DaoManager.class);
+        DaoManager     daoManager     = mock(DaoManager.class);
         RangerKeyStore rangerKeyStore = new RangerKeyStore(daoManager);
         String         keyValue       = "1 enckey";
         Assertions.assertThrows(IOException.class, () -> {
@@ -99,7 +135,7 @@ public void testInvalidKey3() throws NoSuchAlgorithmException, CertificateExcept
 
     @Test
     public void testInvalidKey4() throws NoSuchAlgorithmException, CertificateException, IOException, KeyStoreException {
-        DaoManager     daoManager     = Mockito.mock(DaoManager.class);
+        DaoManager     daoManager     = mock(DaoManager.class);
         RangerKeyStore rangerKeyStore = new RangerKeyStore(daoManager);
         String         keyValue       = "_1-enckey";
         Assertions.assertThrows(IOException.class, () -> {
@@ -111,7 +147,7 @@ public void testInvalidKey4() throws NoSuchAlgorithmException, CertificateExcept
 
     @Test
     public void testValidKey1() throws NoSuchAlgorithmException, CertificateException, IOException, KeyStoreException {
-        DaoManager     daoManager     = Mockito.mock(DaoManager.class);
+        DaoManager     daoManager     = mock(DaoManager.class);
         RangerKeyStore rangerKeyStore = new RangerKeyStore(daoManager);
         String         keyValue       = "enckey_1-test";
         InputStream    inputStream    = generateKeyStoreFile(keyValue);
@@ -121,7 +157,7 @@ public void testValidKey1() throws NoSuchAlgorithmException, CertificateExceptio
 
     @Test
     public void testValidKey2() throws NoSuchAlgorithmException, CertificateException, IOException, KeyStoreException {
-        DaoManager     daoManager     = Mockito.mock(DaoManager.class);
+        DaoManager     daoManager     = mock(DaoManager.class);
         RangerKeyStore rangerKeyStore = new RangerKeyStore(daoManager);
         String         keyValue       = "1-enckey_test";
         InputStream    inputStream    = generateKeyStoreFile(keyValue);
@@ -129,6 +165,379 @@ public void testValidKey2() throws NoSuchAlgorithmException, CertificateExceptio
         inputStream.close();
     }
 
+    @Test
+    public void testEngineGetCertificateChain() {
+        DaoManager     daoManager     = mock(DaoManager.class);
+        RangerKeyStore rangerKeyStore = new RangerKeyStore(daoManager);
+
+        Certificate[] result = rangerKeyStore.engineGetCertificateChain("enckey_1-test");
+        assertNull(result, "Certificate chain should be null for a key that does not exist in the keystore");
+    }
+
+    @Test
+    public void testEngineGetCertificate() {
+        DaoManager     daoManager     = mock(DaoManager.class);
+        RangerKeyStore rangerKeyStore = new RangerKeyStore(daoManager);
+
+        Certificate result = rangerKeyStore.engineGetCertificate("enckey_1-test");
+        assertNull(result, "Certificate should be null for a key that does not exist in the keystore");
+    }
+
+    @Test
+    public void testEngineGetCreationDate_NoEntry() {
+        DaoManager     daoManager     = mock(DaoManager.class);
+        RangerKeyStore rangerKeyStore = new RangerKeyStore(daoManager);
+
+        Date result = rangerKeyStore.engineGetCreationDate("missing-key");
+
+        assertNull(result, "Creation date should be null for a key that does not exist");
+    }
+
+    @Test
+    public void testEngineSize() {
+        DaoManager     daoManager     = mock(DaoManager.class);
+        RangerKeyStore rangerKeyStore = new RangerKeyStore(daoManager);
+
+        int size = rangerKeyStore.engineSize();
+        assertEquals(0, size, "Size should be 0 for an empty keystore");
+    }
+
+    @Test
+    public void testEngineIsKeyEntry() {
+        DaoManager     daoManager     = mock(DaoManager.class);
+        RangerKeyStore rangerKeyStore = new RangerKeyStore(daoManager);
+
+        boolean result = rangerKeyStore.engineIsKeyEntry("enckey_1-test");
+        assertFalse(result, "isKeyEntry should return false for a key that does not exist in the keystore");
+    }
+
+    @Test
+    public void testEngineIsCertificateEntry() {
+        DaoManager     daoManager     = mock(DaoManager.class);
+        RangerKeyStore rangerKeyStore = new RangerKeyStore(daoManager);
+
+        boolean result = rangerKeyStore.engineIsCertificateEntry("enckey_1-test");
+        assertFalse(result, "isCertificateEntry should return false for a key that does not exist in the keystore");
+    }
+
+    @Test
+    public void testEngineGetCertificateAlias() {
+        DaoManager     daoManager     = mock(DaoManager.class);
+        RangerKeyStore rangerKeyStore = new RangerKeyStore(daoManager);
+        Certificate    mockCert       = mock(Certificate.class);
+
+        String result = rangerKeyStore.engineGetCertificateAlias(mockCert);
+        assertNull(result, "engineGetCertificateAlias should return null for any certificate (default implementation)");
+    }
+
+    @Test
+    public void testEngineStore_if() throws Exception {
+        DaoManager     daoManager     = mock(DaoManager.class);
+        RangerKeyStore rangerKeyStore = new RangerKeyStore(daoManager);
+
+        Field keyVaultEnabledField = RangerKeyStore.class.getDeclaredField("keyVaultEnabled");
+        keyVaultEnabledField.setAccessible(true);
+        keyVaultEnabledField.set(rangerKeyStore, true);
+
+        rangerKeyStore.engineStore(null, null);
+    }
+
+    @Test
+    public void testEngineStore_ThrowsIllegalArgumentException_WhenPasswordIsNull() throws Exception {
+        DaoManager     daoManager     = mock(DaoManager.class);
+        RangerKeyStore rangerKeyStore = new RangerKeyStore(daoManager);
+
+        Field keyVaultEnabledField = RangerKeyStore.class.getDeclaredField("keyVaultEnabled");
+        keyVaultEnabledField.setAccessible(true);
+        keyVaultEnabledField.set(rangerKeyStore, false);
+
+        IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> {
+            rangerKeyStore.engineStore(null, null);
+        });
+
+        assertTrue(ex.getMessage().contains("Ranger Master Key can't be null"));
+    }
+
+    @Test
+    public void testAddKeyEntry_throwsKeyStoreException_whenSealKeyFails() throws Exception {
+        DaoManager     daoManager     = mock(DaoManager.class);
+        RangerKeyStore rangerKeyStore = new RangerKeyStore(daoManager);
+
+        String alias       = "testkey";
+        char[] password    = "123".toCharArray();
+        String cipher      = "AES";
+        int    bitLength   = 128;
+        String description = null;
+        int    version     = 1;
+        String attributes  = "key123";
+
+        Key faultyKey = mock(Key.class);
+        lenient().when(faultyKey.getEncoded()).thenReturn(null);
+
+        assertThrows(KeyStoreException.class, () ->
+                rangerKeyStore.addKeyEntry(alias, faultyKey, password, cipher, bitLength, description, version, attributes));
+    }
+
+    @Test
+    public void testDbOperationStore_whenUpdateThrowsException() {
+        DaoManager     daoManager     = mock(DaoManager.class);
+        RangerKeyStore rangerKeyStore = new RangerKeyStore(daoManager);
+        RangerKMSDao   rangerKMSDao   = mock(RangerKMSDao.class);
+
+        try {
+            Field kmsDaoField = RangerKeyStore.class.getDeclaredField("kmsDao");
+            kmsDaoField.setAccessible(true);
+            kmsDaoField.set(rangerKeyStore, rangerKMSDao);
+        } catch (Exception e) {
+            //
+        }
+
+        XXRangerKeyStore input = new XXRangerKeyStore();
+        input.setAlias("test-alias");
+
+        when(rangerKMSDao.findByAlias(anyString())).thenReturn(new XXRangerKeyStore());
+
+        doThrow(new RuntimeException("Simulated DB update error")).when(rangerKMSDao).update(any());
+        rangerKeyStore.dbOperationStore(input);
+        verify(rangerKMSDao).update(any());
+        verify(rangerKMSDao, never()).create(any());
+    }
+
+    @Test
+    public void testDbOperationStore_whenKeyStoreExists_shouldCallUpdate() throws Exception {
+        DaoManager     daoManager     = mock(DaoManager.class);
+        RangerKeyStore rangerKeyStore = new RangerKeyStore(daoManager);
+        RangerKMSDao   rangerKMSDao   = mock(RangerKMSDao.class);
+
+        XXRangerKeyStore input = new XXRangerKeyStore();
+        input.setAlias("test-alias");
+
+        XXRangerKeyStore existing = new XXRangerKeyStore();
+        existing.setAlias("test-alias");
+
+        Field kmsDaoField = RangerKeyStore.class.getDeclaredField("kmsDao");
+        kmsDaoField.setAccessible(true);
+        kmsDaoField.set(rangerKeyStore, rangerKMSDao);
+
+        when(rangerKMSDao.findByAlias("test-alias")).thenReturn(existing);
+
+        rangerKeyStore.dbOperationStore(input);
+
+        verify(rangerKMSDao).update(any(XXRangerKeyStore.class));
+        verify(rangerKMSDao, never()).create(any());
+    }
+
+    @Test
+    public void testDbOperationDelete() throws Exception {
+        DaoManager     daoManager     = mock(DaoManager.class);
+        RangerKeyStore rangerKeyStore = new RangerKeyStore(daoManager);
+        RangerKMSDao   rangerKMSDao   = mock(RangerKMSDao.class);
+
+        Field kmsDaoField = RangerKeyStore.class.getDeclaredField("kmsDao");
+        kmsDaoField.setAccessible(true);
+        kmsDaoField.set(rangerKeyStore, rangerKMSDao);
+
+        doThrow(new RuntimeException("Simulated error")).when(rangerKMSDao).deleteByAlias("test-alias");
+
+        Method method = RangerKeyStore.class.getDeclaredMethod("dbOperationDelete", String.class);
+        method.setAccessible(true);
+
+        assertDoesNotThrow(() -> method.invoke(rangerKeyStore, "test-alias"));
+
+        verify(rangerKMSDao).deleteByAlias("test-alias");
+    }
+
+    @Test
+    public void testDbOperationLoad() throws Exception {
+        DaoManager     daoManager     = mock(DaoManager.class);
+        RangerKeyStore rangerKeyStore = new RangerKeyStore(daoManager);
+        RangerKMSDao   rangerKMSDao   = mock(RangerKMSDao.class);
+
+        Field kmsDaoField = RangerKeyStore.class.getDeclaredField("kmsDao");
+        kmsDaoField.setAccessible(true);
+        kmsDaoField.set(rangerKeyStore, rangerKMSDao);
+
+        doThrow(new RuntimeException("Error")).when(rangerKMSDao).getAllKeys();
+
+        Method method = RangerKeyStore.class.getDeclaredMethod("dbOperationLoad");
+        method.setAccessible(true);
+
+        assertDoesNotThrow(() -> method.invoke(rangerKeyStore));
+        verify(rangerKMSDao).getAllKeys();
+    }
+
+    @Test
+    public void testEngineGetCreationDate_WithoutKeyEntryDirectUse() throws Exception {
+        DaoManager     daoManager     = mock(DaoManager.class);
+        RangerKeyStore rangerKeyStore = new RangerKeyStore(daoManager);
+        String         alias          = "alias";
+        Date           expectedDate   = new Date();
+
+        Class<?>       keyEntryClass = Class.forName("org.apache.hadoop.crypto.key.RangerKeyStore$KeyEntry");
+        Constructor<?> constructor   = keyEntryClass.getDeclaredConstructor();
+        constructor.setAccessible(true);
+        Object keyEntryInstance = constructor.newInstance();
+
+        Field dateField = keyEntryClass.getDeclaredField("date");
+        dateField.setAccessible(true);
+        dateField.set(keyEntryInstance, expectedDate);
+
+        Field keyEntriesField = RangerKeyStore.class.getDeclaredField("keyEntries");
+        keyEntriesField.setAccessible(true);
+        @SuppressWarnings("unchecked")
+        Map<String, Object> keyEntries = (Map<String, Object>) keyEntriesField.get(rangerKeyStore);
+        keyEntries.put(alias, keyEntryInstance);
+
+        Date result = rangerKeyStore.engineGetCreationDate(alias);
+
+        assertNotNull(result);
+        assertEquals(expectedDate.getTime(), result.getTime());
+        assertNotSame(expectedDate, result);
+    }
+
+    @Test
+    public void testRangerKeyStore_UsesAzureKeyVaultProvider() throws Exception {
+        DaoManager   daoManager = mock(DaoManager.class);
+        RangerKMSDao kmsDao     = mock(RangerKMSDao.class);
+        when(daoManager.getRangerKMSDao()).thenReturn(kmsDao);
+
+        Configuration conf = new Configuration();
+        conf.set("ranger.kms.azure.keyvault.enabled", "true");
+
+        RangerKeyStore rangerKeyStore = new RangerKeyStore(daoManager, conf, null);
+
+        Field masterKeyProviderField = RangerKeyStore.class.getDeclaredField("masterKeyProvider");
+        masterKeyProviderField.setAccessible(true);
+        Object masterKeyProvider = masterKeyProviderField.get(rangerKeyStore);
+
+        assertNotNull(masterKeyProvider);
+        assertInstanceOf(RangerAzureKeyVaultKeyGenerator.class, masterKeyProvider, "Expected masterKeyProvider to be RangerAzureKeyVaultKeyGenerator");
+    }
+
+    @Test
+    public void testEngineSetKeyEntry() {
+        DaoManager     daoManager     = mock(DaoManager.class);
+        RangerKeyStore rangerKeyStore = new RangerKeyStore(daoManager);
+
+        String        alias       = "testKey";
+        Key           key         = mock(Key.class);
+        char[]        password    = "testPassword".toCharArray();
+        Certificate[] certs       = new Certificate[] {mock(Certificate.class)};
+        Certificate   certificate = mock(Certificate.class);
+        byte[]        arg1        = "Hello, byte array!".getBytes(StandardCharsets.UTF_8);
+
+        assertDoesNotThrow(() -> rangerKeyStore.engineSetKeyEntry(alias, key, password, certs));
+        assertDoesNotThrow(() -> rangerKeyStore.engineSetKeyEntry(alias, arg1, certs));
+        assertDoesNotThrow(() -> rangerKeyStore.engineSetCertificateEntry(alias, certificate));
+    }
+
+    @Test
+    public void testGetAlgorithm() {
+        DaoManager     daoManager     = mock(DaoManager.class);
+        RangerKeyStore rangerKeyStore = new RangerKeyStore(daoManager);
+        String         cipher         = "AES";
+
+        String result = rangerKeyStore.getAlgorithm(cipher);
+
+        assertEquals(cipher, result, "getAlgorithm should return the same cipher string when no override logic is applied");
+    }
+
+    @Test
+    void testEngineGetDecryptedZoneKeyByte() throws Exception {
+        DaoManager     daoManager     = mock(DaoManager.class);
+        RangerKeyStore rangerKeyStore = new RangerKeyStore(daoManager);
+        String         alias          = "testKey";
+
+        assertNull(rangerKeyStore.engineGetDecryptedZoneKeyByte(alias));
+    }
+
+    @Test
+    void testEngineGetDecryptedZoneKey() throws Exception {
+        DaoManager     daoManager     = mock(DaoManager.class);
+        RangerKeyStore rangerKeyStore = new RangerKeyStore(daoManager);
+        String         alias          = "testKey";
+
+        Key result = rangerKeyStore.engineGetDecryptedZoneKey(alias);
+        assertNotNull(result);
+    }
+
+    @Test
+    void testEngineGetKeyMetadata() throws Exception {
+        DaoManager     daoManager     = mock(DaoManager.class);
+        RangerKeyStore rangerKeyStore = new RangerKeyStore(daoManager);
+        String         alias          = "testKey";
+
+        KeyProvider.Metadata result = rangerKeyStore.engineGetKeyMetadata(alias);
+        assertNull(result);
+    }
+
+    @Test
+    void testAddSecureKeyByteEntry_EncryptFails_ThrowsKeyStoreException() throws Exception {
+        DaoManager     daoManager     = mock(DaoManager.class);
+        RangerKeyStore rangerKeyStore = spy(new RangerKeyStore(daoManager));
+
+        Key             mockKey               = mock(Key.class);
+        RangerMasterKey mockMasterKeyProvider = mock(RangerMasterKey.class);
+
+        Field field = RangerKeyStore.class.getDeclaredField("masterKeyProvider");
+        field.setAccessible(true);
+        field.set(rangerKeyStore, mockMasterKeyProvider);
+
+        when(mockMasterKeyProvider.encryptZoneKey(any(Key.class)))
+                .thenThrow(new RuntimeException("encryption failed"));
+
+        KeyStoreException thrown = assertThrows(
+                KeyStoreException.class,
+                () -> rangerKeyStore.addSecureKeyByteEntry("testAlias", mockKey, "AES", 128, "desc", 1, null));
+        assertEquals("encryption failed", thrown.getMessage());
+    }
+
+    @Test
+    void testAddSecureKeyByteEntry() throws Exception {
+        DaoManager     daoManager     = mock(DaoManager.class);
+        RangerKeyStore rangerKeyStore = spy(new RangerKeyStore(daoManager));
+
+        Key    key         = mock(Key.class);
+        String alias       = "testKey";
+        String cipher      = "AES";
+        int    bitLength   = 128;
+        String description = "Test Key";
+        int    version     = 1;
+        String attributes  = "key123";
+
+        RangerMasterKey rangerMasterKey   = mock(RangerMasterKey.class);
+        byte[]          encryptedKeyBytes = new byte[] {1, 2, 3, 4, 5};
+        when(rangerMasterKey.encryptZoneKey(key)).thenReturn(encryptedKeyBytes);
+
+        Field masterKeyProviderField = RangerKeyStore.class.getDeclaredField("masterKeyProvider");
+        masterKeyProviderField.setAccessible(true);
+        masterKeyProviderField.set(rangerKeyStore, rangerMasterKey);
+
+        assertDoesNotThrow(() -> rangerKeyStore.addSecureKeyByteEntry(
+                alias, key, cipher, bitLength, description, version, attributes));
+    }
+
+    @Test
+    void testEngineLoadToKeyStoreFile_Success() throws Exception {
+        DaoManager     daoManager     = mock(DaoManager.class);
+        RangerKeyStore rangerKeyStore = spy(new RangerKeyStore(daoManager));
+        String         alias          = "testkey";
+        Key            dummyKey       = mock(Key.class);
+
+        doReturn(Collections.enumeration(Collections.singletonList(alias))).when(rangerKeyStore).engineAliases();
+        doReturn(dummyKey).when(rangerKeyStore).engineGetKey(eq(alias), any());
+        doNothing().when(rangerKeyStore).engineLoad(any(), any());
+
+        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+        char[]                storePass    = "storepass".toCharArray();
+        char[]                keyPass      = "keypass".toCharArray();
+        char[]                masterKey    = "masterpass".toCharArray();
+        String                fileFormat   = "JCEKS";
+
+        assertDoesNotThrow(() ->
+                rangerKeyStore.engineLoadToKeyStoreFile(outputStream, storePass, keyPass, masterKey, fileFormat));
+    }
+
     private InputStream generateKeyStoreFile(String keyValue) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException {
         FileOutputStream stream = new FileOutputStream(new File(keyStoreFileName));
         KeyStore         ks;
diff --git a/kms/src/test/java/org/apache/hadoop/crypto/key/kms/TestRangerSafenetKeySecure.java b/kms/src/test/java/org/apache/hadoop/crypto/key/kms/TestRangerSafenetKeySecure.java
new file mode 100644
index 000000000..98b21e97f
--- /dev/null
+++ b/kms/src/test/java/org/apache/hadoop/crypto/key/kms/TestRangerSafenetKeySecure.java
@@ -0,0 +1,139 @@
+/*
+ * 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.hadoop.crypto.key.kms;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.crypto.key.RangerSafenetKeySecure;
+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.Mockito;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.security.KeyStore;
+import java.security.Provider;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.Answers.CALLS_REAL_METHODS;
+import static org.mockito.Mockito.mock;
+
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
+public class TestRangerSafenetKeySecure {
+    @Test
+    public void testGenerateMasterKey_WithNullKeystore_ShouldReturnFalse() throws Exception {
+        RangerSafenetKeySecure secure = mock(RangerSafenetKeySecure.class, CALLS_REAL_METHODS);
+
+        Field storeField = RangerSafenetKeySecure.class.getDeclaredField("myStore");
+        storeField.setAccessible(true);
+        storeField.set(secure, null);  // force myStore to null
+
+        boolean result = secure.generateMasterKey("password");
+        assertFalse(result);
+    }
+
+    @Test
+    public void testConstructorWithMissingConfigFile_ShouldLogError() {
+        Configuration conf = new Configuration();
+        conf.set("ranger.kms.keysecure.sunpkcs11.cfg.filepath", "non-existent.cfg");
+        conf.set("ranger.kms.keysecure.masterkey.size", "256");
+        conf.set("ranger.kms.keysecure.masterkey.name", "RANGERMK");
+        conf.set("ranger.kms.keysecure.provider.type", "SunPKCS11");
+        conf.set("ranger.kms.keysecure.login", "testpass");
+
+        assertThrows(Exception.class, () -> new RangerSafenetKeySecure(conf));
+    }
+
+    @Test
+    public void testGetMasterKey_WithNullKeystore_ShouldReturnNull() throws Throwable {
+        RangerSafenetKeySecure secure = mock(RangerSafenetKeySecure.class, CALLS_REAL_METHODS);
+
+        Field storeField = RangerSafenetKeySecure.class.getDeclaredField("myStore");
+        storeField.setAccessible(true);
+        storeField.set(secure, null);
+
+        String key = secure.getMasterKey("password");
+        assertNull(key);
+    }
+
+    @Test
+    public void testSetMasterKey_WithNullKeystore_ShouldReturnFalse() throws Exception {
+        RangerSafenetKeySecure secure = mock(RangerSafenetKeySecure.class, CALLS_REAL_METHODS);
+
+        Field storeField = RangerSafenetKeySecure.class.getDeclaredField("myStore");
+        storeField.setAccessible(true);
+        storeField.set(secure, null);
+
+        boolean result = secure.setMasterKey("pass", "mockKey".getBytes(), new Configuration());
+        assertFalse(result);
+    }
+
+    @Test
+    public void testGetJavaVersion() throws Exception {
+        RangerSafenetKeySecure secure = mock(RangerSafenetKeySecure.class, CALLS_REAL_METHODS);
+
+        Method getJavaVersionMethod = RangerSafenetKeySecure.class.getDeclaredMethod("getJavaVersion");
+        getJavaVersionMethod.setAccessible(true);
+
+        int version = (int) getJavaVersionMethod.invoke(secure);
+        assertTrue(version >= 8);
+    }
+
+    @Test
+    public void testGetMasterKey() throws Throwable {
+        RangerSafenetKeySecure secure = mock(RangerSafenetKeySecure.class, CALLS_REAL_METHODS);
+
+        Field storeField = RangerSafenetKeySecure.class.getDeclaredField("myStore");
+        storeField.setAccessible(true);
+        storeField.set(secure, null);
+
+        String key = secure.getMasterKey("password");
+        assertNull(key);
+    }
+
+    @Test
+    public void testAddProviderManually_ShouldHitLoadAndLog() throws Exception {
+        Configuration conf = new Configuration();
+        conf.set("ranger.kms.keysecure.sunpkcs11.cfg.filepath", "dummy.cfg");
+        conf.set("ranger.kms.keysecure.masterkey.name", "RANGERMK");
+        conf.set("ranger.kms.keysecure.login", "dummy");
+        conf.set("ranger.kms.keysecure.provider.type", "DummyProvider");
+
+        RangerSafenetKeySecure secure = mock(RangerSafenetKeySecure.class, Mockito.CALLS_REAL_METHODS);
+
+        Provider dummyProvider = new Provider("DummyProvider", 1.0, "dummy desc") {};
+        KeyStore dummyKeystore = mock(KeyStore.class);
+
+        Field providerField = RangerSafenetKeySecure.class.getDeclaredField("provider");
+        providerField.setAccessible(true);
+        providerField.set(secure, dummyProvider);
+
+        Field storeField = RangerSafenetKeySecure.class.getDeclaredField("myStore");
+        storeField.setAccessible(true);
+        storeField.set(secure, dummyKeystore);
+
+        // Now call methods that use provider & keystore
+        boolean result = secure.generateMasterKey("pass");
+        assertFalse(result); // because it won't actually generate anything, but still executes lines
+    }
+}
diff --git a/kms/src/test/java/org/apache/hadoop/crypto/key/kms/server/DerbyTestUtils.java b/kms/src/test/java/org/apache/hadoop/crypto/key/kms/server/DerbyTestUtils.java
index c871bbfd3..5e7810f56 100644
--- a/kms/src/test/java/org/apache/hadoop/crypto/key/kms/server/DerbyTestUtils.java
+++ b/kms/src/test/java/org/apache/hadoop/crypto/key/kms/server/DerbyTestUtils.java
@@ -24,7 +24,7 @@
 import java.util.Properties;
 
 public final class DerbyTestUtils {
-    private DerbyTestUtils(){
+    private DerbyTestUtils() {
     }
 
     public static void startDerby() throws Exception {
diff --git a/kms/src/test/java/org/apache/hadoop/crypto/key/kms/server/TestKMS.java b/kms/src/test/java/org/apache/hadoop/crypto/key/kms/server/TestKMS.java
new file mode 100644
index 000000000..931eaa65f
--- /dev/null
+++ b/kms/src/test/java/org/apache/hadoop/crypto/key/kms/server/TestKMS.java
@@ -0,0 +1,525 @@
+/**
+ * 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.hadoop.crypto.key.kms.server;
+
+import com.codahale.metrics.Meter;
+import org.apache.hadoop.crypto.key.KeyProvider;
+import org.apache.hadoop.crypto.key.KeyProviderCryptoExtension;
+import org.apache.hadoop.security.UserGroupInformation;
+import org.apache.hadoop.security.token.delegation.web.HttpUserGroupInformation;
+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 javax.servlet.http.HttpServletRequest;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Base64;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.eclipse.persistence.jpa.jpql.Assert.fail;
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.Mockito.lenient;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
+public class TestKMS {
+    private static KeyProviderCryptoExtension keyProvider;
+    private static KMSAudit                   kmsAudit;
+    private static Meter                      adminCallsMeter;
+    private static KMSACLs                    acls;
+
+    @Test
+    public void testRolloverKey() throws Exception {
+        String keyName = "testKey";
+        // Prepare input map
+        Map<String, Object> jsonKey = new HashMap<>();
+        jsonKey.put("name", "testKey");
+        jsonKey.put("cipher", "AES");
+        jsonKey.put("length", 128);
+        jsonKey.put("description", "just a basic key");
+
+        // Mock request object
+        HttpServletRequest request = mock(HttpServletRequest.class);
+        lenient().when(request.getRemoteAddr()).thenReturn("127.0.0.1");
+        lenient().when(request.getRequestURI()).thenReturn("/kms/v1/keys/testKey");
+        Meter dummyMeter = mock(Meter.class);
+        Field meterField = KMSWebApp.class.getDeclaredField("adminCallsMeter");
+        meterField.setAccessible(true);
+        meterField.set(null, dummyMeter);
+
+        KMS kms = new KMS();
+        try {
+            kms.rolloverKey(keyName, jsonKey, request);
+            fail("Expected exception due to missing provider/user context");
+        } catch (Exception e) {
+            System.out.println("Caught expected exception: " + e.getMessage());
+            assertNotNull(e);
+        }
+    }
+
+    @Test
+    public void testGetKeyVersions() throws Exception {
+        String keyName = "testKey";
+        // Prepare input map
+        Map<String, Object> jsonKey = new HashMap<>();
+        jsonKey.put("name", "testKey");
+        jsonKey.put("cipher", "AES");
+        jsonKey.put("length", 128);
+        jsonKey.put("description", "just a basic key");
+
+        // Mock request object
+        HttpServletRequest request = mock(HttpServletRequest.class);
+        lenient().when(request.getRemoteAddr()).thenReturn("127.0.0.1");
+        lenient().when(request.getRequestURI()).thenReturn("/kms/v1/keys/testKey");
+        Meter dummyMeter = mock(Meter.class);
+        Field meterField = KMSWebApp.class.getDeclaredField("adminCallsMeter");
+        meterField.setAccessible(true);
+        meterField.set(null, dummyMeter);
+
+        KMS kms = new KMS();
+        try {
+            kms.getKeyVersions(keyName, request);
+            fail("Expected exception due to missing provider/user context");
+        } catch (Exception e) {
+            System.out.println("Caught expected exception: " + e.getMessage());
+            assertNotNull(e);
+        }
+    }
+
+    @Test
+    public void testReencryptEncryptedKeys() throws Exception {
+        String keyName = "testKey";
+
+        List<Map> jsonPayload = new ArrayList<>();
+
+        Map<String, Object> key1 = new HashMap<>();
+        key1.put("versionName", keyName + "@0");
+        key1.put("iv", Base64.getEncoder().encodeToString("12345678".getBytes()));
+        key1.put("encryptedKeyVersion", Base64.getEncoder().encodeToString("keyBytes1".getBytes()));
+        jsonPayload.add(key1);
+
+        Map<String, Object> key2 = new HashMap<>();
+        key2.put("versionName", keyName + "@1");
+        key2.put("iv", Base64.getEncoder().encodeToString("87654321".getBytes()));
+        key2.put("encryptedKeyVersion", Base64.getEncoder().encodeToString("keyBytes2".getBytes()));
+        jsonPayload.add(key2);
+
+        Meter dummyMeter = mock(Meter.class);
+        Field meterField = KMSWebApp.class.getDeclaredField("adminCallsMeter");
+        meterField.setAccessible(true);
+        meterField.set(null, dummyMeter);
+        KMS kms = new KMS();
+
+        try {
+            kms.reencryptEncryptedKeys(keyName, jsonPayload);
+            fail("Expected exception due to missing provider/user context");
+        } catch (Exception e) {
+            System.out.println("Caught expected exception: " + e.getMessage());
+            assertNotNull(e);
+        }
+    }
+
+    @Test
+    public void testHandleEncryptedKeyOp() throws Exception {
+        String keyName     = "testKey";
+        String versionName = "testKeyVersion";
+
+        String edekOp = "generateEncryptedKeys";
+        // Prepare input map
+        Map<String, Object> jsonKey = new HashMap<>();
+        jsonKey.put("name", "testKey");
+        jsonKey.put("cipher", "AES");
+        jsonKey.put("length", 128);
+        jsonKey.put("description", "just a basic key");
+
+        // Mock request object
+        HttpServletRequest request = mock(HttpServletRequest.class);
+        lenient().when(request.getRemoteAddr()).thenReturn("127.0.0.1");
+        lenient().when(request.getRequestURI()).thenReturn("/kms/v1/keys/testKey");
+        Meter dummyMeter = mock(Meter.class);
+        Field meterField = KMSWebApp.class.getDeclaredField("adminCallsMeter");
+        meterField.setAccessible(true);
+        meterField.set(null, dummyMeter);
+
+        KMS kms = new KMS();
+
+        try {
+            kms.handleEncryptedKeyOp(versionName, edekOp, jsonKey, request);
+            fail("Expected exception due to missing provider/user context");
+        } catch (Exception e) {
+            System.out.println("Caught expected exception: " + e.getMessage());
+            assertNotNull(e);
+        }
+    }
+
+    @Test
+    public void testGenerateEncryptedKeys() throws Exception {
+        String keyName = "testKey";
+
+        String edekOp = "generateEncryptedKeys";
+
+        final int numKeys = 1;
+
+        HttpServletRequest request = mock(HttpServletRequest.class);
+        lenient().when(request.getRemoteAddr()).thenReturn("127.0.0.1");
+        lenient().when(request.getRequestURI()).thenReturn("/kms/v1/keys/testKey");
+        Meter dummyMeter = mock(Meter.class);
+        Field meterField = KMSWebApp.class.getDeclaredField("adminCallsMeter");
+        meterField.setAccessible(true);
+        meterField.set(null, dummyMeter);
+
+        KMS kms = new KMS();
+
+        try {
+            kms.generateEncryptedKeys(keyName, edekOp, numKeys, request);
+            fail("Expected exception due to missing provider/user context");
+        } catch (Exception e) {
+            System.out.println("Caught expected exception: " + e.getMessage());
+            assertNotNull(e);
+        }
+    }
+
+    @Test
+    public void testGetKeyVersion() throws Exception {
+        String versionName = "testKeyVersion";
+
+        // Mock request object
+        HttpServletRequest request = mock(HttpServletRequest.class);
+        lenient().when(request.getRemoteAddr()).thenReturn("127.0.0.1");
+        lenient().when(request.getRequestURI()).thenReturn("/kms/v1/keys/testKey");
+        Meter dummyMeter = mock(Meter.class);
+        Field meterField = KMSWebApp.class.getDeclaredField("adminCallsMeter");
+        meterField.setAccessible(true);
+        meterField.set(null, dummyMeter);
+
+        KMS kms = new KMS();
+
+        try {
+            kms.getKeyVersion(versionName, request);
+            fail("Expected exception due to missing provider/user context");
+        } catch (Exception e) {
+            System.out.println("Caught expected exception: " + e.getMessage());
+            assertNotNull(e);
+        }
+    }
+
+    @Test
+    public void testGetKeysMetadata() throws Exception {
+        List<String> keyNamesList = new ArrayList<>();
+        keyNamesList.add("testKey1");
+
+        // Mock request object
+        HttpServletRequest request = mock(HttpServletRequest.class);
+        lenient().when(request.getRemoteAddr()).thenReturn("127.0.0.1");
+        lenient().when(request.getRequestURI()).thenReturn("/kms/v1/keys/testKey");
+        Meter dummyMeter = mock(Meter.class);
+        Field meterField = KMSWebApp.class.getDeclaredField("adminCallsMeter");
+        meterField.setAccessible(true);
+        meterField.set(null, dummyMeter);
+
+        KMS kms = new KMS();
+
+        try {
+            kms.getKeysMetadata(keyNamesList, request);
+            fail("Expected exception due to missing provider/user context");
+        } catch (Exception e) {
+            System.out.println("Caught expected exception: " + e.getMessage());
+            assertNotNull(e);
+        }
+    }
+
+    @Test
+    public void testGetCurrentVersion() throws Exception {
+        String keyName = "testKey";
+
+        // Mock request object
+        HttpServletRequest request = mock(HttpServletRequest.class);
+        lenient().when(request.getRemoteAddr()).thenReturn("127.0.0.1");
+        lenient().when(request.getRequestURI()).thenReturn("/kms/v1/keys/testKey");
+        Meter dummyMeter = mock(Meter.class);
+        Field meterField = KMSWebApp.class.getDeclaredField("adminCallsMeter");
+        meterField.setAccessible(true);
+        meterField.set(null, dummyMeter);
+
+        KMS kms = new KMS();
+
+        try {
+            kms.getCurrentVersion(keyName, request);
+            fail("Expected exception due to missing provider/user context");
+        } catch (Exception e) {
+            System.out.println("Caught expected exception: " + e.getMessage());
+            assertNotNull(e);
+        }
+    }
+
+    @Test
+    public void testGenerateDataKey() throws Exception {
+        String keyName = "testKey";
+
+        // Mock request object
+        HttpServletRequest request = mock(HttpServletRequest.class);
+        lenient().when(request.getRemoteAddr()).thenReturn("127.0.0.1");
+        lenient().when(request.getRequestURI()).thenReturn("/kms/v1/keys/testKey");
+        Meter dummyMeter = mock(Meter.class);
+        Field meterField = KMSWebApp.class.getDeclaredField("adminCallsMeter");
+        meterField.setAccessible(true);
+        meterField.set(null, dummyMeter);
+
+        KMS kms = new KMS();
+
+        try {
+            kms.generateDataKey(keyName, request);
+            fail("Expected exception due to missing provider/user context");
+        } catch (Exception e) {
+            System.out.println("Caught expected exception: " + e.getMessage());
+            assertNotNull(e);
+        }
+    }
+
+    @Test
+    public void testGetKeyNames() throws Exception {
+        // Mock request object
+        HttpServletRequest request = mock(HttpServletRequest.class);
+        lenient().when(request.getRemoteAddr()).thenReturn("127.0.0.1");
+        lenient().when(request.getRequestURI()).thenReturn("/kms/v1/keys/testKey");
+        Meter dummyMeter = mock(Meter.class);
+        Field meterField = KMSWebApp.class.getDeclaredField("adminCallsMeter");
+        meterField.setAccessible(true);
+        meterField.set(null, dummyMeter);
+
+        KMS kms = new KMS();
+
+        try {
+            kms.getKeyNames(request);
+            fail("Expected exception due to missing provider/user context");
+        } catch (Exception e) {
+            System.out.println("Caught expected exception: " + e.getMessage());
+            assertNotNull(e);
+        }
+    }
+
+    @Test
+    void testDeleteKey_skippingAdminCallsMeter() throws Exception {
+        String               keyName  = "name";
+        UserGroupInformation mockUser = mock(UserGroupInformation.class);
+
+        HttpUserGroupInformation httpUserGroupInformation = mock(HttpUserGroupInformation.class);
+
+        // Set up mock request
+        HttpServletRequest request = mock(HttpServletRequest.class);
+        when(request.getRemoteAddr()).thenReturn("127.0.0.1");
+        lenient().when(request.getRequestURI()).thenReturn("/kms/v1/keys/testKey");
+
+        // Prepare a dummy Meter to avoid static call impact
+        Meter dummyMeter = mock(Meter.class);
+
+        // Set static adminCallsMeter in KMSWebApp using reflection
+        Field meterField = KMSWebApp.class.getDeclaredField("adminCallsMeter");
+        meterField.setAccessible(true);
+        meterField.set(null, dummyMeter);
+
+        // Create the KMS instance (internally calls KMSWebApp static methods)
+        KMS kms = new KMS();
+
+        // Run and expect exception (due to missing KMSWebApp dependencies like provider, user, etc.)
+        try {
+            kms.deleteKey(keyName, request);
+            fail("Expected exception due to missing dependencies like provider or UGI");
+        } catch (Exception e) {
+            System.out.println("Expected exception: " + e.getMessage());
+            assertNotNull(e);
+        }
+    }
+
+    @Test
+    void testCreateKeyWithOnlyInputValues() throws Exception {
+        // Prepare input map
+        Map<String, Object> jsonKey = new HashMap<>();
+        jsonKey.put("name", "testKey");
+        jsonKey.put("cipher", "AES");
+        jsonKey.put("length", 128);
+        jsonKey.put("description", "just a basic key");
+
+        // Mock request object
+        HttpServletRequest request = mock(HttpServletRequest.class);
+        lenient().when(request.getRemoteAddr()).thenReturn("127.0.0.1");
+        lenient().when(request.getRequestURI()).thenReturn("/kms/v1/keys/testKey");
+
+        Meter dummyMeter = mock(Meter.class);
+
+        Field meterField = KMSWebApp.class.getDeclaredField("adminCallsMeter");
+        meterField.setAccessible(true);
+        meterField.set(null, dummyMeter);
+
+        // Attempt call (expected to fail unless environment is injected)
+        KMS kms = new KMS();
+        try {
+            kms.createKey(jsonKey, request);
+            fail("Expected exception due to missing provider or user context");
+        } catch (Exception e) {
+            System.out.println("Caught expected exception: " + e.getMessage());
+        }
+    }
+
+    @Test
+    void testCreateKeyWithOnlyInputValues1() throws Exception {
+        // Prepare input map
+        Map<String, Object> jsonKey = new HashMap<>();
+        jsonKey.put("name", "testKey");
+        jsonKey.put("cipher", "AES");
+        jsonKey.put("length", 128);
+        jsonKey.put("description", "just a basic key");
+
+        // Mock request object
+        HttpServletRequest request = mock(HttpServletRequest.class);
+        lenient().when(request.getRemoteAddr()).thenReturn("127.0.0.1");
+        lenient().when(request.getRequestURI()).thenReturn("/kms/v1/keys/testKey");
+
+        Meter dummyMeter = mock(Meter.class);
+
+        Field meterField = KMSWebApp.class.getDeclaredField("adminCallsMeter");
+        meterField.setAccessible(true);
+        meterField.set(null, dummyMeter);
+
+        // Attempt call (expected to fail unless environment is injected)
+        KMS kms = new KMS();
+        try {
+            kms.createKey(jsonKey, request);
+            fail("Expected exception due to missing provider or user context");
+        } catch (Exception e) {
+            System.out.println("Caught expected exception: " + e.getMessage());
+        }
+    }
+
+    @Test
+    void testInvalidateCacheWithOnlyInputValues() throws Exception {
+        String keyName = "testKey";
+
+        Meter dummyMeter = mock(Meter.class);
+
+        Field meterField = KMSWebApp.class.getDeclaredField("adminCallsMeter");
+        meterField.setAccessible(true);
+        meterField.set(null, dummyMeter);
+
+        KMS kms = new KMS();
+
+        try {
+            kms.invalidateCache(keyName);
+            fail("Expected exception due to missing dependencies (provider/user)");
+        } catch (Exception e) {
+            System.out.println("Expected exception: " + e.getMessage());
+            assertNotNull(e);
+        }
+    }
+
+    @Test
+    void testGetKey() throws Exception {
+        String keyName    = "testKey";
+        Meter  dummyMeter = mock(Meter.class);
+
+        Field meterField = KMSWebApp.class.getDeclaredField("adminCallsMeter");
+        meterField.setAccessible(true);
+        meterField.set(null, dummyMeter);
+
+        KMS                kms     = new KMS();
+        HttpServletRequest request = mock(HttpServletRequest.class);
+        lenient().when(request.getRemoteAddr()).thenReturn("127.0.0.1");
+        lenient().when(request.getRequestURI()).thenReturn("/kms/v1/keys/testKey");
+
+        try {
+            kms.getKey(keyName, request);
+            fail("Expected exception due to missing dependencies (provider/user)");
+        } catch (Exception e) {
+            System.out.println("Expected exception: " + e.getMessage());
+            assertNotNull(e);
+        }
+    }
+
+    @Test
+    void testValidateKeyName_valid_reflection() throws Exception {
+        String validKeyName = "ValidKey_123";
+        KMS    kms          = new KMS();
+        Method method       = KMS.class.getDeclaredMethod("validateKeyName", String.class);
+        method.setAccessible(true);
+
+        assertDoesNotThrow(() -> method.invoke(kms, "ValidKey_123"));
+    }
+
+    @Test
+    void testValidateKeyName_invalid_reflection() throws Exception {
+        KMS    kms    = new KMS();
+        Method method = KMS.class.getDeclaredMethod("validateKeyName", String.class);
+        method.setAccessible(true);
+
+        InvocationTargetException ex = assertThrows(InvocationTargetException.class, () -> {
+            method.invoke(kms, "!invalid-key");
+        });
+
+        assertInstanceOf(IllegalArgumentException.class, ex.getCause());
+    }
+
+    @Test
+    void testGetKeyURI_reflection() throws Exception {
+        Method method = KMS.class.getDeclaredMethod("getKeyURI", String.class, String.class);
+        method.setAccessible(true);
+
+        URI result = (URI) method.invoke(null, "v1", "testKey");
+
+        assertEquals("v1/key/testKey", result.toString()); // ✅ expected value
+    }
+
+    @Test
+    void testRemoveKeyMaterial_reflection() throws Exception {
+        Constructor<?> ctor = KeyProvider.KeyVersion.class.getDeclaredConstructor(String.class, String.class, byte[].class);
+        ctor.setAccessible(true);
+
+        KeyProvider.KeyVersion original = (KeyProvider.KeyVersion) ctor.newInstance("key1", "v1", "secret".getBytes());
+
+        Method method = KMS.class.getDeclaredMethod("removeKeyMaterial", KeyProvider.KeyVersion.class);
+        method.setAccessible(true);
+
+        KeyProvider.KeyVersion result = (KeyProvider.KeyVersion) method.invoke(null, original);
+
+        assertEquals("key1", result.getName());
+        assertEquals("v1", result.getVersionName());
+        assertNull(result.getMaterial());
+    }
+
+    private static void setStaticField(Class<?> clazz, String fieldName, Object value) throws Exception {
+        Field field = clazz.getDeclaredField(fieldName);
+        field.setAccessible(true);
+        field.set(null, value);
+    }
+}
diff --git a/kms/src/test/java/org/apache/hadoop/crypto/key/kms/server/TestKMSACLs.java b/kms/src/test/java/org/apache/hadoop/crypto/key/kms/server/TestKMSACLs.java
index 768cf85af..a7b7a5359 100644
--- a/kms/src/test/java/org/apache/hadoop/crypto/key/kms/server/TestKMSACLs.java
+++ b/kms/src/test/java/org/apache/hadoop/crypto/key/kms/server/TestKMSACLs.java
@@ -50,7 +50,7 @@ public void testDefaults() {
     public void testCustom() {
         final Configuration conf = new Configuration(false);
         for (Type type : Type.values()) {
-            conf.set(type.getAclConfigKey(), type.toString() + " ");
+            conf.set(type.getAclConfigKey(), type + " ");
         }
         final KMSACLs acls = new KMSACLs(conf);
         for (Type type : Type.values()) {
diff --git a/kms/src/test/java/org/apache/hadoop/crypto/key/kms/server/TestKMSAudit.java b/kms/src/test/java/org/apache/hadoop/crypto/key/kms/server/TestKMSAudit.java
index bde68bbcd..379922acf 100644
--- a/kms/src/test/java/org/apache/hadoop/crypto/key/kms/server/TestKMSAudit.java
+++ b/kms/src/test/java/org/apache/hadoop/crypto/key/kms/server/TestKMSAudit.java
@@ -33,13 +33,12 @@
 import java.util.List;
 
 public class TestKMSAudit {
-    private PrintStream           originalOut;
-    private ByteArrayOutputStream memOut;
-    private FilterOut             filterOut;
-    private PrintStream           capturedOut;
-
-    private KMSAudit             kmsAudit;
-    private UserGroupInformation luser = UserGroupInformation.createUserForTesting("luser@REALM", new String[0]);
+    private final UserGroupInformation  luser = UserGroupInformation.createUserForTesting("luser@REALM", new String[0]);
+    private       PrintStream           originalOut;
+    private       ByteArrayOutputStream memOut;
+    private       FilterOut             filterOut;
+    private       PrintStream           capturedOut;
+    private       KMSAudit              kmsAudit;
 
     @BeforeEach
     public void setUp() {
@@ -184,7 +183,7 @@ public void testInitAuditLoggers() throws Exception {
 
     private String getAndResetLogOutput() {
         capturedOut.flush();
-        String logOutput = new String(memOut.toByteArray());
+        String logOutput = memOut.toString();
         memOut = new ByteArrayOutputStream();
         filterOut.setOutputStream(memOut);
         return logOutput;
diff --git a/kms/src/test/java/org/apache/hadoop/crypto/key/kms/server/TestKMSExceptionsProvider.java b/kms/src/test/java/org/apache/hadoop/crypto/key/kms/server/TestKMSExceptionsProvider.java
new file mode 100644
index 000000000..f5728695e
--- /dev/null
+++ b/kms/src/test/java/org/apache/hadoop/crypto/key/kms/server/TestKMSExceptionsProvider.java
@@ -0,0 +1,117 @@
+/*
+ * 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.hadoop.crypto.key.kms.server;
+
+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 javax.ws.rs.core.Response;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
+public class TestKMSExceptionsProvider {
+    @Test
+    public void testGetOneLineMessage() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
+        KMSExceptionsProvider kmsExceptionsProvider = new KMSExceptionsProvider();
+
+        // Mock an exception with a valid message
+        Throwable exception = mock(Throwable.class);
+        when(exception.getMessage()).thenReturn("Simulated exception message\nWith new line");
+
+        Method method = KMSExceptionsProvider.class.getDeclaredMethod("getOneLineMessage", Throwable.class);
+        method.setAccessible(true);
+        String message = (String) method.invoke(kmsExceptionsProvider, exception);
+
+        // Verify that the message is not null or empty
+        if (message == null || message.isEmpty()) {
+            throw new AssertionError("The one-line message should not be null or empty");
+        }
+    }
+
+    @Test
+    public void testCreateResponse() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
+        KMSExceptionsProvider kmsExceptionsProvider = new KMSExceptionsProvider();
+
+        // Mock an exception with a valid message
+        Throwable       exception = mock(Throwable.class);
+        Response.Status status    = Response.Status.INTERNAL_SERVER_ERROR;
+
+        when(exception.getMessage()).thenReturn("Simulated exception message");
+
+        Method method = KMSExceptionsProvider.class.getDeclaredMethod("createResponse", Response.Status.class, Throwable.class);
+        method.setAccessible(true);
+
+        Object response = method.invoke(kmsExceptionsProvider, status, exception);
+
+        if (response == null) {
+            throw new AssertionError("The response should not be null");
+        }
+
+        if (!(response instanceof Response)) {
+            throw new AssertionError("The response should be of type javax.ws.rs.core.Response");
+        }
+
+        Response jerseyResponse = (Response) response;
+
+        if (jerseyResponse.getStatus() != Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()) {
+            throw new AssertionError("Expected HTTP 500 INTERNAL_SERVER_ERROR");
+        }
+    }
+
+    @Test
+    public void testToResponse() {
+        try {
+            KMSExceptionsProvider kmsExceptionsProvider = new KMSExceptionsProvider();
+            Exception             exception             = new Exception("Simulated exception message");
+            Response              response              = kmsExceptionsProvider.toResponse(exception);
+
+            if (response == null) {
+                throw new AssertionError("Response is null");
+            }
+
+            if (response.getStatus() != Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()) {
+                throw new AssertionError("Unexpected status");
+            }
+        } catch (Exception e) {
+            e.printStackTrace(); // Full trace
+        }
+    }
+
+    @Test
+    public void testLog() {
+        KMSExceptionsProvider kmsExceptionsProvider = new KMSExceptionsProvider();
+        Throwable             exception             = mock(Throwable.class);
+        Response.Status       status                = Response.Status.INTERNAL_SERVER_ERROR;
+
+        try {
+            Method method = KMSExceptionsProvider.class.getDeclaredMethod("log", Response.Status.class, Throwable.class);
+            method.setAccessible(true);
+            method.invoke(kmsExceptionsProvider, status, exception);
+        } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
+            e.printStackTrace(); // Full trace
+        }
+    }
+}
diff --git a/kms/src/test/java/org/apache/hadoop/crypto/key/kms/server/TestKMSMDCFilter.java b/kms/src/test/java/org/apache/hadoop/crypto/key/kms/server/TestKMSMDCFilter.java
new file mode 100644
index 000000000..9fa9666e8
--- /dev/null
+++ b/kms/src/test/java/org/apache/hadoop/crypto/key/kms/server/TestKMSMDCFilter.java
@@ -0,0 +1,87 @@
+/*
+ * 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.hadoop.crypto.key.kms.server;
+
+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 javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
+public class TestKMSMDCFilter {
+    @Test
+    public void testInit() throws ServletException {
+        KMSMDCFilter kmsMDCFilter = new KMSMDCFilter();
+        FilterConfig config       = mock(FilterConfig.class);
+        kmsMDCFilter.init(config);
+    }
+
+    @Test
+    public void testDestroy() {
+        KMSMDCFilter kmsMDCFilter = new KMSMDCFilter();
+        kmsMDCFilter.destroy();
+    }
+
+    @Test
+    public void testDoFilter_withKmsApiPath() throws Exception {
+        KMSMDCFilter filter = new KMSMDCFilter();
+
+        HttpServletRequest  request  = mock(HttpServletRequest.class);
+        HttpServletResponse response = mock(HttpServletResponse.class);
+        FilterChain         chain    = mock(FilterChain.class);
+
+        when(request.getRequestURI()).thenReturn("/kms/api/status");
+
+        filter.doFilter(request, response, chain);
+
+        verify(chain).doFilter(request, response);
+    }
+
+    @Test
+    public void testDoFilter_withOtherPath() throws Exception {
+        KMSMDCFilter filter = new KMSMDCFilter();
+
+        HttpServletRequest  request  = mock(HttpServletRequest.class);
+        HttpServletResponse response = mock(HttpServletResponse.class);
+        FilterChain         chain    = mock(FilterChain.class);
+
+        when(request.getRequestURI()).thenReturn("/kms/v1/keys");
+        when(request.getMethod()).thenReturn("GET");
+        when(request.getRequestURL()).thenReturn(new StringBuffer("http://localhost/kms/v1/keys"));
+        when(request.getQueryString()).thenReturn(null);
+
+        try {
+            filter.doFilter(request, response, chain);
+        } catch (Exception e) {
+            // optional logging/assertion
+        }
+
+        verify(chain).doFilter(request, response);
+    }
+}
diff --git a/kms/src/test/java/org/apache/hadoop/crypto/key/kms/server/TestKMSServerJSONUtils.java b/kms/src/test/java/org/apache/hadoop/crypto/key/kms/server/TestKMSServerJSONUtils.java
new file mode 100644
index 000000000..e98b00a45
--- /dev/null
+++ b/kms/src/test/java/org/apache/hadoop/crypto/key/kms/server/TestKMSServerJSONUtils.java
@@ -0,0 +1,79 @@
+/*
+ * 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.hadoop.crypto.key.kms.server;
+
+import org.apache.hadoop.crypto.key.KeyProvider;
+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.lang.reflect.Method;
+import java.util.List;
+
+import static org.mockito.Mockito.mock;
+
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
+public class TestKMSServerJSONUtils {
+    @Test
+    public void testToJSON() {
+        KMSServerJSONUtils           jsonUtils   = mock(KMSServerJSONUtils.class);
+        List<KeyProvider.KeyVersion> keyVersions = mock(List.class);
+        try {
+            Method method = KMSServerJSONUtils.class.getDeclaredMethod("toJSON", List.class);
+            method.setAccessible(true);
+            method.invoke(jsonUtils, keyVersions);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    @Test
+    public void testToJSON1() {
+        KMSServerJSONUtils   jsonUtils = mock(KMSServerJSONUtils.class);
+        String               keyName   = "testKey";
+        KeyProvider.Metadata meta      = mock(KeyProvider.Metadata.class);
+
+        try {
+            Method method = KMSServerJSONUtils.class.getDeclaredMethod("toJSON", String.class, KeyProvider.Metadata.class);
+            method.setAccessible(true);
+            method.invoke(jsonUtils, keyName, meta);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    @Test
+    public void testToJSON2() {
+        KMSServerJSONUtils jsonUtils = mock(KMSServerJSONUtils.class);
+        String[]           keyNames  = {"key1", "key2"};
+        KeyProvider.Metadata[] metas = {
+                mock(KeyProvider.Metadata.class),
+                mock(KeyProvider.Metadata.class)
+        };
+
+        try {
+            Method method = KMSServerJSONUtils.class.getDeclaredMethod("toJSON", String[].class, KeyProvider.Metadata[].class);
+            method.setAccessible(true);
+            method.invoke(jsonUtils, keyNames, metas);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+}
diff --git a/kms/src/test/java/org/apache/hadoop/crypto/key/kms/server/TestKMSWebApp.java b/kms/src/test/java/org/apache/hadoop/crypto/key/kms/server/TestKMSWebApp.java
new file mode 100644
index 000000000..726686b7b
--- /dev/null
+++ b/kms/src/test/java/org/apache/hadoop/crypto/key/kms/server/TestKMSWebApp.java
@@ -0,0 +1,446 @@
+
+/*
+ * 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.hadoop.crypto.key.kms.server;
+
+import com.codahale.metrics.JmxReporter;
+import com.codahale.metrics.Meter;
+import com.codahale.metrics.MetricRegistry;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.crypto.key.KeyProvider;
+import org.apache.hadoop.crypto.key.KeyProviderCryptoExtension;
+import org.apache.ranger.kms.metrics.collector.KMSMetricsCollector;
+import org.junit.jupiter.api.BeforeEach;
+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 org.slf4j.Logger;
+
+import javax.servlet.ServletContextEvent;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.net.URI;
+import java.nio.file.Files;
+import java.util.HashSet;
+import java.util.Set;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNotSame;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertSame;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
+public class TestKMSWebApp {
+    private Configuration                       mockConfig;
+    private KeyAuthorizationKeyProvider.KeyACLs mockAcls;
+    private Meter                               mockMeter;
+    private KMSMetricsCollector                 mockKmsMetricsCollector;
+
+    @BeforeEach
+    public void setup() throws Throwable {
+        mockConfig = new Configuration();
+        mockConfig.set("test.key", "test.value");
+
+        mockAcls                = mock(KeyAuthorizationKeyProvider.KeyACLs.class);
+        mockMeter               = mock(Meter.class);
+        mockKmsMetricsCollector = mock(KMSMetricsCollector.class);
+
+        setStaticField("kmsConf", mockConfig);
+        setStaticField("kmsAcls", mockAcls);
+        setStaticField("keyCallsMeter", mockMeter);
+        setStaticField("invalidCallsMeter", mockMeter);
+        setStaticField("generateEEKCallsMeter", mockMeter);
+        setStaticField("decryptEEKCallsMeter", mockMeter);
+        setStaticField("reencryptEEKCallsMeter", mockMeter);
+        setStaticField("reencryptEEKBatchCallsMeter", mockMeter);
+        setStaticField("kmsMetricsCollector", mockKmsMetricsCollector);
+    }
+
+    @Test
+    public void testGetConfigurationReturnsCopyOfKmsConf() {
+        Configuration returnedConf = KMSWebApp.getConfiguration();
+
+        assertNotNull(returnedConf);
+        assertNotSame(mockConfig, returnedConf);
+    }
+
+    @Test
+    public void testGetACLs() {
+        assertSame(mockAcls, KMSWebApp.getACLs());
+    }
+
+    @Test
+    public void testGetKeyCallsMeter() {
+        assertSame(mockMeter, KMSWebApp.getKeyCallsMeter());
+    }
+
+    @Test
+    public void testGetInvalidCallsMeter() {
+        assertSame(mockMeter, KMSWebApp.getInvalidCallsMeter());
+    }
+
+    @Test
+    public void testGetGenerateEEKCallsMeter() {
+        assertSame(mockMeter, KMSWebApp.getGenerateEEKCallsMeter());
+    }
+
+    @Test
+    public void testGetDecryptEEKCallsMeter() {
+        assertSame(mockMeter, KMSWebApp.getDecryptEEKCallsMeter());
+    }
+
+    @Test
+    public void testGetReencryptEEKCallsMeter() {
+        assertSame(mockMeter, KMSWebApp.getReencryptEEKCallsMeter());
+    }
+
+    @Test
+    public void testGetReencryptEEKBatchCallsMeter() {
+        assertSame(mockMeter, KMSWebApp.getReencryptEEKBatchCallsMeter());
+    }
+
+    @Test
+    public void testGetKmsMetricsCollector() {
+        assertSame(mockKmsMetricsCollector, KMSWebApp.getKmsMetricsCollector());
+    }
+
+    @Test
+    public void testInitLogging() throws Exception {
+        KMSWebApp app    = new KMSWebApp();
+        Method    method = KMSWebApp.class.getDeclaredMethod("initLogging");
+        method.setAccessible(true);
+        method.invoke(app);
+
+        Field logField = KMSWebApp.class.getDeclaredField("log");
+        logField.setAccessible(true);
+        Logger logger = (Logger) logField.get(null);
+
+        assertNotNull(logger);
+        assertEquals(KMSWebApp.class.getName(), logger.getName());
+    }
+
+    @Test
+    public void testCreateKeyProviderViaReflection() throws Exception {
+        URI    uri    = new URI("jceks://file/tmp/test.jceks");
+        Method method = KMSWebApp.class.getDeclaredMethod("createKeyProvider", URI.class, Configuration.class);
+        method.setAccessible(true);
+        Object result = method.invoke(null, uri, mockConfig);
+
+        assertNotNull(result);
+        assertInstanceOf(KeyProvider.class, result);
+    }
+
+    @Test
+    public void testGetKeyAcls() throws Exception {
+        KMSWebApp app    = new KMSWebApp();
+        Method    method = KMSWebApp.class.getDeclaredMethod("getKeyAcls", String.class);
+        method.setAccessible(true);
+        Object result = method.invoke(app, (String) null);
+
+        assertNotNull(result);
+        assertInstanceOf(KMSACLs.class, result);
+    }
+
+    @Test
+    public void testContextInitialized_successfulPath_java8Compatible() throws Exception {
+        final SecurityManager originalSecurityManager = System.getSecurityManager();
+        System.setSecurityManager(new SecurityManager() {
+            @Override
+            public void checkPermission(java.security.Permission perm) {}
+
+            @Override
+            public void checkExit(int status) {
+                throw new SecurityException("Intercepted System.exit(" + status + ")");
+            }
+        });
+
+        File tempDir = Files.createTempDirectory("kms-test-conf").toFile();
+        File kmsSite = new File(tempDir, "kms-site.xml");
+
+        try (FileWriter writer = new FileWriter(kmsSite)) {
+            writer.write("<configuration>\n" +
+                    "  <property><name>hadoop.kms.key.provider.uri</name><value>user:///</value></property>\n" +
+                    "  <property><name>hadoop.kms.key.cache.enable</name><value>false</value></property>\n" +
+                    "  <property><name>hadoop.kms.metric.collection.threadsafe</name><value>false</value></property>\n" +
+                    "  <property><name>hadoop.kms.security.authorization.manager</name>\n" +
+                    "           <value>org.apache.hadoop.crypto.key.kms.server.KMSACLs</value></property>\n" +
+                    "</configuration>");
+        }
+
+        System.setProperty(KMSConfiguration.KMS_CONFIG_DIR, tempDir.getAbsolutePath());
+
+        // Setup logger
+        Logger mockLogger = mock(Logger.class);
+        Field  logField   = KMSWebApp.class.getDeclaredField("log");
+        logField.setAccessible(true);
+        logField.set(null, mockLogger);
+
+        try {
+            KMSWebApp webApp = new KMSWebApp();
+            webApp.contextInitialized(mock(ServletContextEvent.class));
+        } catch (SecurityException e) {
+            System.out.println("Intercepted System.exit: " + e.getMessage());
+        } finally {
+            System.setSecurityManager(originalSecurityManager);
+            System.clearProperty(KMSConfiguration.KMS_CONFIG_DIR);
+        }
+    }
+
+    @Test
+    public void testContextDestroyed_success_java8Compatible() throws Exception {
+        // Save original SecurityManager
+        SecurityManager originalSecurityManager = System.getSecurityManager();
+        System.setSecurityManager(new SecurityManager() {
+            @Override
+            public void checkPermission(java.security.Permission perm) {}
+
+            @Override
+            public void checkExit(int status) {
+                throw new SecurityException("Intercepted System.exit(" + status + ")");
+            }
+        });
+
+        // Create valid minimal kms-site.xml
+        File tempDir = Files.createTempDirectory("kms-test-conf").toFile();
+        File kmsSite = new File(tempDir, "kms-site.xml");
+        try (FileWriter writer = new FileWriter(kmsSite)) {
+            writer.write("<configuration>\n" +
+                    "  <property><name>hadoop.kms.key.provider.uri</name><value>user:///</value></property>\n" +
+                    "  <property><name>hadoop.kms.key.cache.enable</name><value>false</value></property>\n" +
+                    "  <property><name>hadoop.kms.metric.collection.threadsafe</name><value>false</value></property>\n" +
+                    "  <property><name>hadoop.kms.security.authorization.manager</name>\n" +
+                    "           <value>org.apache.hadoop.crypto.key.kms.server.KMSACLs</value></property>\n" +
+                    "</configuration>");
+        }
+        System.setProperty(KMSConfiguration.KMS_CONFIG_DIR, tempDir.getAbsolutePath());
+
+        // Set mock logger
+        Logger mockLogger = mock(Logger.class);
+        Field  logField   = KMSWebApp.class.getDeclaredField("log");
+        logField.setAccessible(true);
+        logField.set(null, mockLogger);
+        KeyProviderCryptoExtension keyProviderCryptoExtension = mock(KeyProviderCryptoExtension.class);
+
+        try {
+            // Initialize first
+            KMSWebApp app = new KMSWebApp();
+            app.contextInitialized(mock(ServletContextEvent.class));
+
+            // Then destroy
+            app.contextDestroyed(mock(ServletContextEvent.class));
+
+            // ✅ No exceptions = successful test
+        } catch (SecurityException e) {
+            //
+        } finally {
+            System.setSecurityManager(originalSecurityManager);
+            System.clearProperty(KMSConfiguration.KMS_CONFIG_DIR);
+        }
+    }
+
+    @Test
+    public void testContextInitialized_fullCoverageUsingReflection1() throws Exception {
+        SecurityManager originalSM = System.getSecurityManager();
+        System.setSecurityManager(new SecurityManager() {
+            @Override
+            public void checkPermission(java.security.Permission perm) {}
+
+            @Override
+            public void checkExit(int status) {
+                throw new SecurityException("Intercepted System.exit(" + status + ")");
+            }
+        });
+
+        File tempDir = Files.createTempDirectory("kms-test-conf").toFile();
+        File kmsSite = new File(tempDir, "kms-site.xml");
+        try (FileWriter writer = new FileWriter(kmsSite)) {
+            writer.write("<configuration>\n" +
+                    "  <property><name>hadoop.kms.key.cache.enable</name><value>false</value></property>\n" +
+                    "  <property><name>hadoop.kms.metric.collection.threadsafe</name><value>false</value></property>\n" +
+                    "  <property><name>hadoop.kms.key.provider.uri</name><value>user:///</value></property>\n" +
+                    "  <property><name>hadoop.kms.security.authorization.manager</name><value>org.apache.hadoop.crypto.key.kms.server.KMSACLs</value></property>\n" +
+                    "</configuration>");
+        }
+        File dbksSite = new File(tempDir, "dbks-site.xml");
+        try (FileWriter writer = new FileWriter(dbksSite)) {
+            writer.write("<configuration></configuration>");
+        }
+        System.setProperty(KMSConfiguration.KMS_CONFIG_DIR, tempDir.getAbsolutePath());
+        boolean exitCalled = false;
+        try {
+            KMSWebApp     webApp       = new KMSWebApp();
+            Configuration kmsConf      = KMSConfiguration.getKMSConf();
+            Field         kmsConfField = KMSWebApp.class.getDeclaredField("kmsConf");
+            kmsConfField.setAccessible(true);
+            kmsConfField.set(webApp, kmsConf);
+
+            Method getKeyAclsMethod = KMSWebApp.class.getDeclaredMethod("getKeyAcls", String.class);
+            getKeyAclsMethod.setAccessible(true);
+            Object                              realAcls     = getKeyAclsMethod.invoke(webApp, kmsConf.get(KMSConfiguration.KMS_SECURITY_AUTHORIZER));
+            KeyAuthorizationKeyProvider.KeyACLs spyAcls      = spy((KeyAuthorizationKeyProvider.KeyACLs) realAcls);
+            Field                               kmsAclsField = KMSWebApp.class.getDeclaredField("kmsAcls");
+            kmsAclsField.setAccessible(true);
+            kmsAclsField.set(webApp, spyAcls);
+
+            MetricRegistry realRegistry        = new MetricRegistry();
+            Field          metricRegistryField = KMSWebApp.class.getDeclaredField("metricRegistry");
+            metricRegistryField.setAccessible(true);
+            metricRegistryField.set(webApp, realRegistry);
+
+            JmxReporter mockReporter     = mock(JmxReporter.class);
+            Field       jmxReporterField = KMSWebApp.class.getDeclaredField("jmxReporter");
+            jmxReporterField.setAccessible(true);
+            jmxReporterField.set(webApp, mockReporter);
+
+            webApp.contextInitialized(mock(ServletContextEvent.class));
+
+            Set<String> expectedMeters = new HashSet<>();
+            expectedMeters.add("GenerateEEKCalls");
+            expectedMeters.add("DecryptEEKCalls");
+            expectedMeters.add("ReencryptEEKCalls");
+            expectedMeters.add("ReencryptEEKBatchCalls");
+            expectedMeters.add("AdminCalls");
+            expectedMeters.add("KeyCalls");
+            expectedMeters.add("InvalidCalls");
+            expectedMeters.add("UnauthorizedCalls");
+            expectedMeters.add("UnauthenticatedCalls");
+            assertTrue(realRegistry.getMeters().keySet().containsAll(expectedMeters));
+        } catch (SecurityException se) {
+            exitCalled = se.getMessage().contains("Intercepted");
+        } finally {
+            System.setSecurityManager(originalSM);
+            System.clearProperty(KMSConfiguration.KMS_CONFIG_DIR);
+        }
+    }
+
+    @Test
+    public void testContextDestroyed() throws Exception {
+        ServletContextEvent sce    = mock(ServletContextEvent.class);
+        KMSWebApp           webApp = new KMSWebApp();
+
+        Logger mockLogger = mock(Logger.class);
+        Field  logField   = KMSWebApp.class.getDeclaredField("log");
+        logField.setAccessible(true);
+        logField.set(null, mockLogger);
+
+        KeyProviderCryptoExtension          mockExtension = mock(KeyProviderCryptoExtension.class);
+        KMSAudit                            mockAudit     = mock(KMSAudit.class);
+        KeyAuthorizationKeyProvider.KeyACLs mockAcls      = mock(KeyAuthorizationKeyProvider.KeyACLs.class);
+        JmxReporter                         mockReporter  = mock(JmxReporter.class);
+
+        Field extensionField = KMSWebApp.class.getDeclaredField("keyProviderCryptoExtension");
+        extensionField.setAccessible(true);
+        extensionField.set(null, mockExtension);
+
+        Field auditField = KMSWebApp.class.getDeclaredField("kmsAudit");
+        auditField.setAccessible(true);
+        auditField.set(null, mockAudit);
+
+        Field aclsField = KMSWebApp.class.getDeclaredField("kmsAcls");
+        aclsField.setAccessible(true);
+        aclsField.set(null, mockAcls);
+
+        Field reporterField = KMSWebApp.class.getDeclaredField("jmxReporter");
+        reporterField.setAccessible(true);
+        reporterField.set(webApp, mockReporter); // instance field
+
+        Field registryField = KMSWebApp.class.getDeclaredField("metricRegistry");
+        registryField.setAccessible(true);
+        registryField.set(null, new MetricRegistry());
+
+        webApp.contextDestroyed(sce);
+
+        Field registryFieldCheck = KMSWebApp.class.getDeclaredField("metricRegistry");
+        registryFieldCheck.setAccessible(true);
+        assertNull(registryFieldCheck.get(null));
+    }
+
+    @Test
+    public void testContextDestroyed_whenCloseThrowsIOException() throws Exception {
+        ServletContextEvent sce    = mock(ServletContextEvent.class);
+        KMSWebApp           webApp = new KMSWebApp();
+
+        Logger                              mockLogger    = mock(Logger.class);
+        KeyProviderCryptoExtension          mockExtension = mock(KeyProviderCryptoExtension.class);
+        KMSAudit                            mockAudit     = mock(KMSAudit.class);
+        KeyAuthorizationKeyProvider.KeyACLs mockAcls      = mock(KeyAuthorizationKeyProvider.KeyACLs.class);
+        JmxReporter                         mockReporter  = mock(JmxReporter.class);
+        MetricRegistry                      dummyRegistry = new MetricRegistry();
+
+        doThrow(new IOException("simulated")).when(mockExtension).close();
+
+        Field logField = KMSWebApp.class.getDeclaredField("log");
+        logField.setAccessible(true);
+        logField.set(null, mockLogger);
+
+        Field extensionField = KMSWebApp.class.getDeclaredField("keyProviderCryptoExtension");
+        extensionField.setAccessible(true);
+        extensionField.set(null, mockExtension);
+
+        Field auditField = KMSWebApp.class.getDeclaredField("kmsAudit");
+        auditField.setAccessible(true);
+        auditField.set(null, mockAudit);
+
+        Field aclsField = KMSWebApp.class.getDeclaredField("kmsAcls");
+        aclsField.setAccessible(true);
+        aclsField.set(null, mockAcls);
+
+        Field reporterField = KMSWebApp.class.getDeclaredField("jmxReporter");
+        reporterField.setAccessible(true);
+        reporterField.set(webApp, mockReporter); // instance field
+
+        Field registryField = KMSWebApp.class.getDeclaredField("metricRegistry");
+        registryField.setAccessible(true);
+        registryField.set(null, dummyRegistry);
+
+        webApp.contextDestroyed(sce);
+
+        verify(mockExtension).close();
+        verify(mockLogger).error(eq("Error closing KeyProviderCryptoExtension"), any(IOException.class));
+        verify(mockAudit).shutdown();
+        verify(mockAcls).stopReloader();
+        verify(mockReporter).stop();
+        verify(mockReporter).close();
+        verify(mockLogger).info("KMS Stopped");
+
+        Field regCheck = KMSWebApp.class.getDeclaredField("metricRegistry");
+        regCheck.setAccessible(true);
+        assertNull(regCheck.get(null));
+    }
+
+    private void setStaticField(String fieldName, Object value) throws Exception {
+        Field field = KMSWebApp.class.getDeclaredField(fieldName);
+        field.setAccessible(true);
+        field.set(null, value);
+    }
+}
diff --git a/kms/src/test/java/org/apache/hadoop/crypto/key/kms/server/TestKeyAuthorizationKeyProvider.java b/kms/src/test/java/org/apache/hadoop/crypto/key/kms/server/TestKeyAuthorizationKeyProvider.java
index 45d7b7f97..a76c1c6fe 100644
--- a/kms/src/test/java/org/apache/hadoop/crypto/key/kms/server/TestKeyAuthorizationKeyProvider.java
+++ b/kms/src/test/java/org/apache/hadoop/crypto/key/kms/server/TestKeyAuthorizationKeyProvider.java
@@ -101,8 +101,8 @@ public Void run() throws Exception {
     @Test
     public void testOpsWhenACLAttributeExists() throws Exception {
         final Configuration conf = new Configuration();
-        KeyProvider kp = new UserProvider.Factory().createProvider(new URI("user:///"), conf);
-        KeyACLs mock = mock(KeyACLs.class);
+        KeyProvider         kp   = new UserProvider.Factory().createProvider(new URI("user:///"), conf);
+        KeyACLs             mock = mock(KeyACLs.class);
         when(mock.isACLPresent("testKey", KeyOpType.MANAGEMENT)).thenReturn(true);
         when(mock.isACLPresent("testKey", KeyOpType.GENERATE_EEK)).thenReturn(true);
         when(mock.isACLPresent("testKey", KeyOpType.DECRYPT_EEK)).thenReturn(true);
@@ -207,8 +207,8 @@ public Void run() throws Exception {
     @Test
     public void testDecryptWithKeyVersionNameKeyMismatch() throws Exception {
         final Configuration conf = new Configuration();
-        KeyProvider kp = new UserProvider.Factory().createProvider(new URI("user:///"), conf);
-        KeyACLs mock = mock(KeyACLs.class);
+        KeyProvider         kp   = new UserProvider.Factory().createProvider(new URI("user:///"), conf);
+        KeyACLs             mock = mock(KeyACLs.class);
         when(mock.isACLPresent("testKey", KeyOpType.MANAGEMENT)).thenReturn(true);
         when(mock.isACLPresent("testKey", KeyOpType.GENERATE_EEK)).thenReturn(true);
         when(mock.isACLPresent("testKey", KeyOpType.DECRYPT_EEK)).thenReturn(true);
diff --git a/kms/src/test/java/org/apache/hadoop/crypto/key/kms/server/TestRangerJsonProvider.java b/kms/src/test/java/org/apache/hadoop/crypto/key/kms/server/TestRangerJsonProvider.java
new file mode 100644
index 000000000..92deee574
--- /dev/null
+++ b/kms/src/test/java/org/apache/hadoop/crypto/key/kms/server/TestRangerJsonProvider.java
@@ -0,0 +1,38 @@
+/*
+ * 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.hadoop.crypto.key.kms.server;
+
+import org.apache.ranger.common.RangerJsonProvider;
+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 static org.junit.jupiter.api.Assertions.assertNotNull;
+
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
+public class TestRangerJsonProvider {
+    @Test
+    public void testRangerJsonProvider() {
+        RangerJsonProvider rangerJsonProvider = new RangerJsonProvider();
+        String             result             = rangerJsonProvider.toString();
+
+        assertNotNull(result);
+    }
+}
diff --git a/kms/src/test/java/org/apache/ranger/entity/TestXXDBBase.java b/kms/src/test/java/org/apache/ranger/entity/TestXXDBBase.java
new file mode 100644
index 000000000..a36588e72
--- /dev/null
+++ b/kms/src/test/java/org/apache/ranger/entity/TestXXDBBase.java
@@ -0,0 +1,226 @@
+/*
+ * 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.entity;
+
+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.util.Date;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
+public class TestXXDBBase {
+    @Test
+    public void testEquals_sameObject() {
+        XXDBBaseImpl base = new XXDBBaseImpl();
+        assertEquals(base, base);
+    }
+
+    @Test
+    public void testEquals_null() {
+        XXDBBaseImpl base = new XXDBBaseImpl();
+        assertNotEquals(base, null);
+    }
+
+    @Test
+    public void testEquals_sameObject1() {
+        XXDBBaseImpl obj = new XXDBBaseImpl();
+        assertEquals(obj, obj);
+    }
+
+    @Test
+    public void testEquals_null1() {
+        XXDBBaseImpl obj = new XXDBBaseImpl();
+        assertNotEquals(obj, null);
+    }
+
+    @Test
+    public void testEquals_differentClass() {
+        XXDBBaseImpl obj = new XXDBBaseImpl();
+        assertNotEquals(obj, "Some String");
+    }
+
+    @Test
+    public void testEquals_allFieldsEqual() {
+        Date now = new Date();
+
+        XXDBBaseImpl obj1 = new XXDBBaseImpl();
+        obj1.setCreateTime(now);
+        obj1.setUpdateTime(now);
+        obj1.setAddedByUserId(1L);
+        obj1.setUpdatedByUserId(2L);
+
+        XXDBBaseImpl obj2 = new XXDBBaseImpl();
+        obj2.setCreateTime(now);
+        obj2.setUpdateTime(now);
+        obj2.setAddedByUserId(1L);
+        obj2.setUpdatedByUserId(2L);
+
+        assertEquals(obj1, obj2);
+    }
+
+    @Test
+    public void testEquals_differentCreateTime() {
+        XXDBBaseImpl obj1 = new XXDBBaseImpl();
+        obj1.setCreateTime(new Date(100000L));
+
+        XXDBBaseImpl obj2 = new XXDBBaseImpl();
+        obj2.setCreateTime(new Date(200000L));
+
+        assertNotEquals(obj1, obj2);
+    }
+
+    @Test
+    public void testEquals_differentUpdateTime() {
+        XXDBBaseImpl obj1 = new XXDBBaseImpl();
+        obj1.setUpdateTime(new Date(100000L));
+
+        XXDBBaseImpl obj2 = new XXDBBaseImpl();
+        obj2.setUpdateTime(new Date(200000L));
+
+        assertNotEquals(obj1, obj2);
+    }
+
+    @Test
+    public void testEquals_differentAddedByUserId() {
+        XXDBBaseImpl obj1 = new XXDBBaseImpl();
+        obj1.setAddedByUserId(10L);
+
+        XXDBBaseImpl obj2 = new XXDBBaseImpl();
+        obj2.setAddedByUserId(20L);
+
+        assertNotEquals(obj1, obj2);
+    }
+
+    @Test
+    public void testEquals_differentUpdatedByUserId() {
+        XXDBBaseImpl obj1 = new XXDBBaseImpl();
+        obj1.setUpdatedByUserId(30L);
+
+        XXDBBaseImpl obj2 = new XXDBBaseImpl();
+        obj2.setUpdatedByUserId(40L);
+
+        assertNotEquals(obj1, obj2);
+    }
+
+    @Test
+    public void testToString_containsExpectedFields() {
+        Date         now = new Date();
+        XXDBBaseImpl obj = new XXDBBaseImpl();
+        obj.setCreateTime(now);
+        obj.setUpdateTime(now);
+        obj.setAddedByUserId(5L);
+        obj.setUpdatedByUserId(6L);
+
+        String str = obj.toString();
+        assertTrue(str.contains("createTime={" + now));
+        assertTrue(str.contains("updateTime={" + now));
+        assertTrue(str.contains("addedByUserId={5}"));
+        assertTrue(str.contains("updatedByUserId={6}"));
+    }
+
+    @Test
+    public void testHashCode_returnsConsistentValue() {
+        XXDBBaseImpl obj   = new XXDBBaseImpl();
+        int          hash1 = obj.hashCode();
+        int          hash2 = obj.hashCode();
+        assertEquals(hash1, hash2);
+    }
+
+    @Test
+    public void testDefaultConstructor_setsCreateAndUpdateTime() {
+        XXDBBaseImpl obj = new XXDBBaseImpl();
+        assertNotNull(obj.getCreateTime());
+        assertNotNull(obj.getUpdateTime());
+    }
+
+    @Test
+    public void testGetEnumName_alwaysReturnsNull() {
+        assertNull(XXDBBase.getEnumName("anyField"));
+        assertNull(XXDBBase.getEnumName(null));
+        assertNull(XXDBBase.getEnumName(""));
+    }
+
+    @Test
+    public void testGetMyClassType_returnsDefault() {
+        XXDBBaseImpl obj = new XXDBBaseImpl();
+        assertEquals(XXDBBase.CLASS_TYPE_NONE, obj.getMyClassType());
+    }
+
+    @Test
+    public void testGetMyDisplayValue_returnsNull() {
+        XXDBBaseImpl obj = new XXDBBaseImpl();
+        assertNull(obj.getMyDisplayValue());
+    }
+
+    @Test
+    public void testGetAddedByUserId_returnsCorrectValue() {
+        XXDBBaseImpl obj        = new XXDBBaseImpl();
+        Long         expectedId = 100L;
+        obj.setAddedByUserId(expectedId);
+        assertEquals(expectedId, obj.getAddedByUserId());
+    }
+
+    @Test
+    public void testGetUpdatedByUserId_returnsCorrectValue() {
+        XXDBBaseImpl obj        = new XXDBBaseImpl();
+        Long         expectedId = 200L;
+        obj.setUpdatedByUserId(expectedId);
+        assertEquals(expectedId, obj.getUpdatedByUserId());
+    }
+
+    @Test
+    public void testNullCreateTimeAndUpdateTimeHandledInEquals() {
+        XXDBBaseImpl obj1 = new XXDBBaseImpl();
+        XXDBBaseImpl obj2 = new XXDBBaseImpl();
+
+        obj1.setCreateTime(null);
+        obj1.setUpdateTime(null);
+        obj2.setCreateTime(null);
+        obj2.setUpdateTime(null);
+
+        obj1.setAddedByUserId(1L);
+        obj2.setAddedByUserId(1L);
+        obj1.setUpdatedByUserId(2L);
+        obj2.setUpdatedByUserId(2L);
+
+        assertEquals(obj1, obj2);
+    }
+
+    static class XXDBBaseImpl extends XXDBBase {
+        private Long id;
+
+        @Override
+        public Long getId() {
+            return id;
+        }
+
+        @Override
+        public void setId(Long id) {
+            this.id = id;
+        }
+    }
+}
diff --git a/kms/src/test/java/org/apache/ranger/entity/TestXXRangerKeyStore.java b/kms/src/test/java/org/apache/ranger/entity/TestXXRangerKeyStore.java
new file mode 100644
index 000000000..0c35d0a26
--- /dev/null
+++ b/kms/src/test/java/org/apache/ranger/entity/TestXXRangerKeyStore.java
@@ -0,0 +1,40 @@
+    /*
+ * 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.entity;
+
+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 static org.junit.jupiter.api.Assertions.assertEquals;
+
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
+public class TestXXRangerKeyStore {
+    @Test
+    public void testGetId() {
+        XXRangerKeyStore keystore   = new XXRangerKeyStore();
+        Long             expectedId = 123L;
+        keystore.setId(expectedId);
+
+        Long actualId = keystore.getId();
+
+        assertEquals(expectedId, actualId, "getId() should return the correct ID value");
+    }
+}
diff --git a/kms/src/test/java/org/apache/ranger/kms/biz/TestRangerKMSStartUp.java b/kms/src/test/java/org/apache/ranger/kms/biz/TestRangerKMSStartUp.java
new file mode 100644
index 000000000..6ce8c7758
--- /dev/null
+++ b/kms/src/test/java/org/apache/ranger/kms/biz/TestRangerKMSStartUp.java
@@ -0,0 +1,33 @@
+/*
+ * 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.kms.biz;
+
+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;
+
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
+public class TestRangerKMSStartUp {
+    @Test
+    public void testInitRangerMasterKey() throws Throwable {
+        RangerKMSStartUp rangerKMSStartUp = new RangerKMSStartUp();
+        rangerKMSStartUp.initRangerMasterKey();
+    }
+}
diff --git a/kms/src/test/java/org/apache/ranger/kms/dao/TestBaseDao.java b/kms/src/test/java/org/apache/ranger/kms/dao/TestBaseDao.java
new file mode 100644
index 000000000..093be75e5
--- /dev/null
+++ b/kms/src/test/java/org/apache/ranger/kms/dao/TestBaseDao.java
@@ -0,0 +1,94 @@
+/*
+ * 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.kms.dao;
+
+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.junit.jupiter.MockitoExtension;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityTransaction;
+
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+@ExtendWith(MockitoExtension.class)
+public class TestBaseDao {
+    @Mock
+    private DaoManager daoManager;
+
+    @Mock
+    private EntityManager entityManager;
+
+    @Mock
+    private EntityTransaction entityTransaction;
+
+    private BaseDao<Object> baseDao;
+
+    @BeforeEach
+    public void setup() {
+        when(daoManager.getEntityManager()).thenReturn(entityManager);
+        baseDao = new BaseDao<Object>(daoManager) {};
+    }
+
+    @Test
+    public void testRollbackTransaction_whenEntityManagerAndTransactionAreNotNull() {
+        when(entityManager.getTransaction()).thenReturn(entityTransaction);
+
+        baseDao.rollbackTransaction();
+
+        verify(entityTransaction, times(1)).rollback();
+    }
+
+    @Test
+    public void testRollbackTransaction_whenEntityManagerIsNull() {
+        when(daoManager.getEntityManager()).thenReturn(null);
+
+        baseDao.rollbackTransaction();
+
+        // No rollback expected, verify no interaction
+        verify(entityTransaction, never()).rollback();
+    }
+
+    @Test
+    public void testRollbackTransaction_whenTransactionIsNull() {
+        when(entityManager.getTransaction()).thenReturn(null);
+
+        baseDao.rollbackTransaction();
+
+        verify(entityTransaction, never()).rollback();
+    }
+
+    @Test
+    public void testCreate_withException_shouldRollback() {
+        Object entity = new Object();
+        when(entityManager.getTransaction()).thenReturn(entityTransaction);
+        when(entityTransaction.isActive()).thenReturn(false);
+        doThrow(new RuntimeException("fail")).when(entityManager).persist(entity);
+
+        Object result = baseDao.create(entity);
+
+        assertNull(result);
+        verify(entityTransaction).rollback();
+    }
+}
diff --git a/kms/src/test/java/org/apache/ranger/kms/metrics/source/TestKMSMetricUtil.java b/kms/src/test/java/org/apache/ranger/kms/metrics/source/TestKMSMetricUtil.java
new file mode 100644
index 000000000..2016979ad
--- /dev/null
+++ b/kms/src/test/java/org/apache/ranger/kms/metrics/source/TestKMSMetricUtil.java
@@ -0,0 +1,143 @@
+/*
+ * 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.kms.metrics.source;
+
+import org.apache.hadoop.crypto.key.kms.server.KMSMetricUtil;
+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.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
+public class TestKMSMetricUtil {
+    @Test
+    public void testGetKMSMetricCalculation() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
+        KMSMetricUtil kmsMetricUtil = new KMSMetricUtil();
+
+        kmsMetricUtil.getClass();
+        String caseValue = "org.apache.hadoop.crypto.key.kms.server.KMSMetricUtil";
+
+        Method method = KMSMetricUtil.class.getDeclaredMethod("getKMSMetricCalculation", String.class);
+        method.setAccessible(true);
+        Object result = method.invoke(kmsMetricUtil, caseValue);
+        // Assert that the result is not null or empty
+        if (result != null) {
+            System.out.println("KMSMetricCalculation: " + result);
+        } else {
+            System.out.println("KMSMetricCalculation returned null");
+        }
+    }
+
+    @Test
+    public void testMain() {
+        SecurityManager originalSM = System.getSecurityManager();
+        System.setSecurityManager(new SecurityManager() {
+            @Override
+            public void checkPermission(java.security.Permission perm) {}
+
+            @Override
+            public void checkExit(int status) {
+                throw new SecurityException("Intercepted System.exit(" + status + ")");
+            }
+        });
+
+        try {
+            KMSMetricUtil.main(new String[] {});
+        } catch (SecurityException e) {
+            System.out.println("Caught expected SecurityException: " + e.getMessage());
+        } finally {
+            System.setSecurityManager(originalSM);
+        }
+    }
+
+    @Test
+    public void testMain1() {
+        SecurityManager originalSM = System.getSecurityManager();
+        System.setSecurityManager(new SecurityManager() {
+            @Override
+            public void checkPermission(java.security.Permission perm) {}
+
+            @Override
+            public void checkExit(int status) {
+                throw new SecurityException("Intercepted System.exit(" + status + ")");
+            }
+        });
+
+        String[] args = {"-type", "hsmenabled"};
+
+        try {
+            KMSMetricUtil.main(args);
+        } catch (SecurityException e) {
+            System.out.println("Caught expected SecurityException: " + e.getMessage());
+        } finally {
+            System.setSecurityManager(originalSM);
+        }
+    }
+
+    @Test
+    public void testMain2() {
+        SecurityManager originalSM = System.getSecurityManager();
+        System.setSecurityManager(new SecurityManager() {
+            @Override
+            public void checkPermission(java.security.Permission perm) {}
+
+            @Override
+            public void checkExit(int status) {
+                throw new SecurityException("Intercepted System.exit(" + status + ")");
+            }
+        });
+
+        String[] args = {"-Type", "encryptedkeybyalgorithm"};
+
+        try {
+            KMSMetricUtil.main(args);
+        } catch (SecurityException e) {
+            System.out.println("Caught expected SecurityException: " + e.getMessage());
+        } finally {
+            System.setSecurityManager(originalSM);
+        }
+    }
+
+    @Test
+    public void testMain3() {
+        SecurityManager originalSM = System.getSecurityManager();
+        System.setSecurityManager(new SecurityManager() {
+            @Override
+            public void checkPermission(java.security.Permission perm) {}
+
+            @Override
+            public void checkExit(int status) {
+                throw new SecurityException("Intercepted System.exit(" + status + ")");
+            }
+        });
+
+        String[] args = {"-TYPE", "ENCRYPTEDKEY"};
+
+        try {
+            KMSMetricUtil.main(args);
+        } catch (SecurityException e) {
+            System.out.println("Caught expected SecurityException: " + e.getMessage());
+        } finally {
+            System.setSecurityManager(originalSM);
+        }
+    }
+}